-../scssphp/scssphp/bin/pscss
\ No newline at end of file
+#!/usr/bin/env sh
+
+dir=$(cd "${0%[/\\]*}" > /dev/null; cd "../scssphp/scssphp/bin" && pwd)
+
+if [ -d /proc/cygdrive ]; then
+ case $(which php) in
+ $(readlink -n /proc/cygdrive)/*)
+ # We are in Cygwin using Windows php, so the path must be translated
+ dir=$(cygpath -m "$dir");
+ ;;
+ esac
+fi
+
+"${dir}/pscss" "$@"
--- /dev/null
+@ECHO OFF
+setlocal DISABLEDELAYEDEXPANSION
+SET BIN_TARGET=%~dp0/../scssphp/scssphp/bin/pscss
+php "%BIN_TARGET%" %*
},
{
"name": "scssphp/scssphp",
- "version": "1.2.1",
+ "version": "1.3",
"source": {
"type": "git",
"url": "https://github.com/scssphp/scssphp.git",
- "reference": "a05ea68160b7286ebbfd6e5fd7ae9e1a946ad6e1"
+ "reference": "261cd018025d5790e135a1e5b694d6af186e6bca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/scssphp/scssphp/zipball/a05ea68160b7286ebbfd6e5fd7ae9e1a946ad6e1",
- "reference": "a05ea68160b7286ebbfd6e5fd7ae9e1a946ad6e1",
+ "url": "https://api.github.com/repos/scssphp/scssphp/zipball/261cd018025d5790e135a1e5b694d6af186e6bca",
+ "reference": "261cd018025d5790e135a1e5b694d6af186e6bca",
"shasum": ""
},
"require": {
"php": ">=5.6.0"
},
"require-dev": {
- "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
+ "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4",
"sass/sass-spec": "2020.08.10",
"squizlabs/php_codesniffer": "~3.5",
"twbs/bootstrap": "~4.3",
"scss",
"stylesheet"
],
- "time": "2020-09-07T21:15:42+00:00"
+ "support": {
+ "issues": "https://github.com/scssphp/scssphp/issues",
+ "source": "https://github.com/scssphp/scssphp/tree/1.3"
+ },
+ "time": "2020-10-29T11:09:57+00:00"
},
{
"name": "symfony/css-selector",
"php": "7.2.24",
"ext-gd": "0"
},
- "plugin-api-version": "1.1.0"
+ "plugin-api-version": "2.0.0"
}
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
- * @see http://www.php-fig.org/psr/psr-0/
- * @see http://www.php-fig.org/psr/psr-4/
+ * @see https://www.php-fig.org/psr/psr-0/
+ * @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
--- /dev/null
+<?php
+
+namespace Composer;
+
+use Composer\Semver\VersionParser;
+
+
+
+
+
+
+class InstalledVersions
+{
+private static $installed = array (
+ 'root' =>
+ array (
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'f448efb8521534c520f84e89a1a38296d4c0e5fd',
+ 'name' => '__root__',
+ ),
+ 'versions' =>
+ array (
+ '__root__' =>
+ array (
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'f448efb8521534c520f84e89a1a38296d4c0e5fd',
+ ),
+ 'chrisjean/php-ico' =>
+ array (
+ 'pretty_version' => '1.0.4',
+ 'version' => '1.0.4.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6',
+ ),
+ 'erusev/parsedown' =>
+ array (
+ 'pretty_version' => '1.7.4',
+ 'version' => '1.7.4.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
+ ),
+ 'ezyang/htmlpurifier' =>
+ array (
+ 'pretty_version' => 'v4.13.0',
+ 'version' => '4.13.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '08e27c97e4c6ed02f37c5b2b20488046c8d90d75',
+ ),
+ 'guzzlehttp/guzzle' =>
+ array (
+ 'pretty_version' => '7.2.0',
+ 'version' => '7.2.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '0aa74dfb41ae110835923ef10a9d803a22d50e79',
+ ),
+ 'guzzlehttp/promises' =>
+ array (
+ 'pretty_version' => '1.4.0',
+ 'version' => '1.4.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '60d379c243457e073cff02bc323a2a86cb355631',
+ ),
+ 'guzzlehttp/psr7' =>
+ array (
+ 'pretty_version' => '1.7.0',
+ 'version' => '1.7.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '53330f47520498c0ae1f61f7e2c90f55690c06a3',
+ ),
+ 'pear/net_idna2' =>
+ array (
+ 'pretty_version' => 'v0.2.0',
+ 'version' => '0.2.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '51734eaf8be2df58e8aad5835b9966459b2fb37c',
+ ),
+ 'pear/pear_exception' =>
+ array (
+ 'pretty_version' => 'v1.0.1',
+ 'version' => '1.0.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7',
+ ),
+ 'pelago/emogrifier' =>
+ array (
+ 'pretty_version' => 'v2.1.1',
+ 'version' => '2.1.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '8ee7fb5ad772915451ed3415c1992bd3697d4983',
+ ),
+ 'psr/http-client' =>
+ array (
+ 'pretty_version' => '1.0.1',
+ 'version' => '1.0.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
+ ),
+ 'psr/http-client-implementation' =>
+ array (
+ 'provided' =>
+ array (
+ 0 => '1.0',
+ ),
+ ),
+ 'psr/http-message' =>
+ array (
+ 'pretty_version' => '1.0.1',
+ 'version' => '1.0.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
+ ),
+ 'psr/http-message-implementation' =>
+ array (
+ 'provided' =>
+ array (
+ 0 => '1.0',
+ ),
+ ),
+ 'ralouphie/getallheaders' =>
+ array (
+ 'pretty_version' => '3.0.3',
+ 'version' => '3.0.3.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '120b605dfeb996808c31b6477290a714d356e822',
+ ),
+ 'scssphp/scssphp' =>
+ array (
+ 'pretty_version' => '1.3',
+ 'version' => '1.3.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '261cd018025d5790e135a1e5b694d6af186e6bca',
+ ),
+ 'symfony/css-selector' =>
+ array (
+ 'pretty_version' => 'v4.4.15',
+ 'version' => '4.4.15.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'bf17dc9f6ce144e41f786c32435feea4d8e11dcc',
+ ),
+ 'symfony/polyfill-mbstring' =>
+ array (
+ 'pretty_version' => 'v1.18.1',
+ 'version' => '1.18.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'a6977d63bf9a0ad4c65cd352709e230876f9904a',
+ ),
+ 'true/punycode' =>
+ array (
+ 'pretty_version' => 'v2.1.1',
+ 'version' => '2.1.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'a4d0c11a36dd7f4e7cd7096076cab6d3378a071e',
+ ),
+ ),
+);
+
+
+
+
+
+
+
+public static function getInstalledPackages()
+{
+return array_keys(self::$installed['versions']);
+}
+
+
+
+
+
+
+
+
+
+public static function isInstalled($packageName)
+{
+return isset(self::$installed['versions'][$packageName]);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public static function satisfies(VersionParser $parser, $packageName, $constraint)
+{
+$constraint = $parser->parseConstraints($constraint);
+$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+return $provided->matches($constraint);
+}
+
+
+
+
+
+
+
+
+
+
+public static function getVersionRanges($packageName)
+{
+if (!isset(self::$installed['versions'][$packageName])) {
+throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+}
+
+$ranges = array();
+if (isset(self::$installed['versions'][$packageName]['pretty_version'])) {
+$ranges[] = self::$installed['versions'][$packageName]['pretty_version'];
+}
+if (array_key_exists('aliases', self::$installed['versions'][$packageName])) {
+$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['aliases']);
+}
+if (array_key_exists('replaced', self::$installed['versions'][$packageName])) {
+$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['replaced']);
+}
+if (array_key_exists('provided', self::$installed['versions'][$packageName])) {
+$ranges = array_merge($ranges, self::$installed['versions'][$packageName]['provided']);
+}
+
+return implode(' || ', $ranges);
+}
+
+
+
+
+
+public static function getVersion($packageName)
+{
+if (!isset(self::$installed['versions'][$packageName])) {
+throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+}
+
+if (!isset(self::$installed['versions'][$packageName]['version'])) {
+return null;
+}
+
+return self::$installed['versions'][$packageName]['version'];
+}
+
+
+
+
+
+public static function getPrettyVersion($packageName)
+{
+if (!isset(self::$installed['versions'][$packageName])) {
+throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+}
+
+if (!isset(self::$installed['versions'][$packageName]['pretty_version'])) {
+return null;
+}
+
+return self::$installed['versions'][$packageName]['pretty_version'];
+}
+
+
+
+
+
+public static function getReference($packageName)
+{
+if (!isset(self::$installed['versions'][$packageName])) {
+throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+}
+
+if (!isset(self::$installed['versions'][$packageName]['reference'])) {
+return null;
+}
+
+return self::$installed['versions'][$packageName]['reference'];
+}
+
+
+
+
+
+public static function getRootPackage()
+{
+return self::$installed['root'];
+}
+
+
+
+
+
+
+
+public static function getRawData()
+{
+return self::$installed;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public static function reload($data)
+{
+self::$installed = $data;
+}
+}
$baseDir = $vendorDir;
return array(
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'PEAR_Exception' => $vendorDir . '/pear/pear_exception/PEAR/Exception.php',
'PHP_ICO' => $vendorDir . '/chrisjean/php-ico/class-php-ico.php',
);
return self::$loader;
}
+ require __DIR__ . '/platform_check.php';
+
spl_autoload_register(array('ComposerAutoloaderInita1f5f7c74275d47a45049a2936db1d0d', 'loadClassLoader'), true, false);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInita1f5f7c74275d47a45049a2936db1d0d', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
- require_once __DIR__ . '/autoload_static.php';
+ require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d::getInitializer($loader));
} else {
);
public static $classMap = array (
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'PEAR_Exception' => __DIR__ . '/..' . '/pear/pear_exception/PEAR/Exception.php',
'PHP_ICO' => __DIR__ . '/..' . '/chrisjean/php-ico/class-php-ico.php',
);
-[
- {
- "name": "chrisjean/php-ico",
- "version": "1.0.4",
- "version_normalized": "1.0.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/chrisbliss18/php-ico.git",
- "reference": "ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/chrisbliss18/php-ico/zipball/ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6",
- "reference": "ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6",
- "shasum": ""
- },
- "require": {
- "ext-gd": "*",
- "php": ">=5.2.4"
- },
- "time": "2016-09-27T22:00:56+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "classmap": [
- "class-php-ico.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "GPL-2.0+"
- ],
- "authors": [
- {
- "name": "Chris Jean",
- "homepage": "https://chrisjean.com",
- "role": "Developer"
- }
- ],
- "description": "An easy-to-use library to generate valid ICO files.",
- "homepage": "https://github.com/chrisbliss18/php-ico",
- "keywords": [
- "favicon",
- "ico"
- ]
- },
- {
- "name": "erusev/parsedown",
- "version": "1.7.4",
- "version_normalized": "1.7.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/erusev/parsedown.git",
- "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
- "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
- "shasum": ""
- },
- "require": {
- "ext-mbstring": "*",
- "php": ">=5.3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.8.35"
- },
- "time": "2019-12-30T22:54:17+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-0": {
- "Parsedown": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Emanuil Rusev",
- "email": "hello@erusev.com",
- "homepage": "http://erusev.com"
- }
- ],
- "description": "Parser for Markdown.",
- "homepage": "http://parsedown.org",
- "keywords": [
- "markdown",
- "parser"
- ]
- },
- {
- "name": "ezyang/htmlpurifier",
- "version": "v4.13.0",
- "version_normalized": "4.13.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/ezyang/htmlpurifier.git",
- "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
- "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
- "shasum": ""
- },
- "require": {
- "php": ">=5.2"
- },
- "require-dev": {
- "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
- },
- "time": "2020-06-29T00:56:53+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-0": {
- "HTMLPurifier": "library/"
- },
- "files": [
- "library/HTMLPurifier.composer.php"
- ],
- "exclude-from-classmap": [
- "/library/HTMLPurifier/Language/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "LGPL-2.1-or-later"
- ],
- "authors": [
- {
- "name": "Edward Z. Yang",
- "email": "admin@htmlpurifier.org",
- "homepage": "http://ezyang.com"
- }
- ],
- "description": "Standards compliant HTML filter written in PHP",
- "homepage": "http://htmlpurifier.org/",
- "keywords": [
- "html"
- ]
- },
- {
- "name": "guzzlehttp/guzzle",
- "version": "7.2.0",
- "version_normalized": "7.2.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/guzzle/guzzle.git",
- "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79",
- "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79",
- "shasum": ""
- },
- "require": {
- "ext-json": "*",
- "guzzlehttp/promises": "^1.4",
- "guzzlehttp/psr7": "^1.7",
- "php": "^7.2.5 || ^8.0",
- "psr/http-client": "^1.0"
- },
- "provide": {
- "psr/http-client-implementation": "1.0"
- },
- "require-dev": {
- "ext-curl": "*",
- "php-http/client-integration-tests": "^3.0",
- "phpunit/phpunit": "^8.5.5 || ^9.3.5",
- "psr/log": "^1.1"
- },
- "suggest": {
- "ext-curl": "Required for CURL handler support",
- "ext-intl": "Required for Internationalized Domain Name (IDN) support",
- "psr/log": "Required for using the Log middleware"
- },
- "time": "2020-10-10T11:47:56+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "7.1-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "GuzzleHttp\\": "src/"
- },
- "files": [
- "src/functions_include.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
- },
- {
- "name": "Márk Sági-Kazár",
- "email": "mark.sagikazar@gmail.com",
- "homepage": "https://sagikazarmark.hu"
- }
- ],
- "description": "Guzzle is a PHP HTTP client library",
- "homepage": "http://guzzlephp.org/",
- "keywords": [
- "client",
- "curl",
- "framework",
- "http",
- "http client",
- "psr-18",
- "psr-7",
- "rest",
- "web service"
- ],
- "funding": [
- {
- "url": "https://github.com/GrahamCampbell",
- "type": "github"
- },
- {
- "url": "https://github.com/Nyholm",
- "type": "github"
- },
- {
- "url": "https://github.com/alexeyshockov",
- "type": "github"
- },
- {
- "url": "https://github.com/gmponos",
- "type": "github"
- }
- ]
- },
- {
- "name": "guzzlehttp/promises",
- "version": "1.4.0",
- "version_normalized": "1.4.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/guzzle/promises.git",
- "reference": "60d379c243457e073cff02bc323a2a86cb355631"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/60d379c243457e073cff02bc323a2a86cb355631",
- "reference": "60d379c243457e073cff02bc323a2a86cb355631",
- "shasum": ""
- },
- "require": {
- "php": ">=5.5"
- },
- "require-dev": {
- "symfony/phpunit-bridge": "^4.4 || ^5.1"
- },
- "time": "2020-09-30T07:37:28+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "GuzzleHttp\\Promise\\": "src/"
- },
- "files": [
- "src/functions_include.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
- }
- ],
- "description": "Guzzle promises library",
- "keywords": [
- "promise"
- ]
- },
- {
- "name": "guzzlehttp/psr7",
- "version": "1.7.0",
- "version_normalized": "1.7.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/guzzle/psr7.git",
- "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3",
- "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3",
- "shasum": ""
- },
- "require": {
- "php": ">=5.4.0",
- "psr/http-message": "~1.0",
- "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
- },
- "provide": {
- "psr/http-message-implementation": "1.0"
- },
- "require-dev": {
- "ext-zlib": "*",
- "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
- },
- "suggest": {
- "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
- },
- "time": "2020-09-30T07:37:11+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.7-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "GuzzleHttp\\Psr7\\": "src/"
- },
- "files": [
- "src/functions_include.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
- },
- {
- "name": "Tobias Schultze",
- "homepage": "https://github.com/Tobion"
- }
- ],
- "description": "PSR-7 message implementation that also provides common utility methods",
- "keywords": [
- "http",
- "message",
- "psr-7",
- "request",
- "response",
- "stream",
- "uri",
- "url"
- ]
- },
- {
- "name": "pear/net_idna2",
- "version": "v0.2.0",
- "version_normalized": "0.2.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/pear/Net_IDNA2.git",
- "reference": "51734eaf8be2df58e8aad5835b9966459b2fb37c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/pear/Net_IDNA2/zipball/51734eaf8be2df58e8aad5835b9966459b2fb37c",
- "reference": "51734eaf8be2df58e8aad5835b9966459b2fb37c",
- "shasum": ""
- },
- "require": {
- "pear/pear_exception": "@stable"
- },
- "require-dev": {
- "phpunit/phpunit": "^4"
- },
- "time": "2017-03-06T20:46:41+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-0": {
- "Net": "./"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- "./"
- ],
- "license": [
- "LGPL"
- ],
- "authors": [
- {
- "name": "Stefan Neufeind",
- "email": "pear.neufeind@speedpartner.de",
- "role": "Lead"
- },
- {
- "name": "Daniel O'Connor",
- "email": "daniel.oconnor@gmail.com",
- "role": "Lead"
- }
- ],
- "description": "More info available on: https://pear.php.net/package/Net_IDNA2"
- },
- {
- "name": "pear/pear_exception",
- "version": "v1.0.1",
- "version_normalized": "1.0.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/pear/PEAR_Exception.git",
- "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
- "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
- "shasum": ""
- },
- "require": {
- "php": ">=4.4.0"
- },
- "require-dev": {
- "phpunit/phpunit": "*"
- },
- "time": "2019-12-10T10:24:42+00:00",
- "type": "class",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "classmap": [
- "PEAR/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- "."
- ],
- "license": [
- "BSD-2-Clause"
- ],
- "authors": [
- {
- "name": "Helgi Thormar",
- "email": "dufuz@php.net"
- },
- {
- "name": "Greg Beaver",
- "email": "cellog@php.net"
- }
- ],
- "description": "The PEAR Exception base class.",
- "homepage": "https://github.com/pear/PEAR_Exception",
- "keywords": [
- "exception"
- ]
- },
- {
- "name": "pelago/emogrifier",
- "version": "v2.1.1",
- "version_normalized": "2.1.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/MyIntervals/emogrifier.git",
- "reference": "8ee7fb5ad772915451ed3415c1992bd3697d4983"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/8ee7fb5ad772915451ed3415c1992bd3697d4983",
- "reference": "8ee7fb5ad772915451ed3415c1992bd3697d4983",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-libxml": "*",
- "php": "^5.5.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0",
- "symfony/css-selector": "^3.4.0 || ^4.0.0"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^2.2.0",
- "phpmd/phpmd": "^2.6.0",
- "phpunit/phpunit": "^4.8.0",
- "squizlabs/php_codesniffer": "^3.3.2"
- },
- "time": "2018-12-10T10:36:30+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.1.x-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Pelago\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "John Reeve",
- "email": "jreeve@pelagodesign.com"
- },
- {
- "name": "Cameron Brooks"
- },
- {
- "name": "Jaime Prado"
- },
- {
- "name": "Oliver Klee",
- "email": "github@oliverklee.de"
- },
- {
- "name": "Zoli Szabó",
- "email": "zoli.szabo+github@gmail.com"
- },
- {
- "name": "Jake Hotson",
- "email": "jake@qzdesign.co.uk"
- }
- ],
- "description": "Converts CSS styles into inline style attributes in your HTML code",
- "homepage": "https://www.myintervals.com/emogrifier.php",
- "keywords": [
- "css",
- "email",
- "pre-processing"
- ]
- },
- {
- "name": "psr/http-client",
- "version": "1.0.1",
- "version_normalized": "1.0.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/http-client.git",
- "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
- "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
- "shasum": ""
- },
- "require": {
- "php": "^7.0 || ^8.0",
- "psr/http-message": "^1.0"
- },
- "time": "2020-06-29T06:28:15+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Psr\\Http\\Client\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "description": "Common interface for HTTP clients",
- "homepage": "https://github.com/php-fig/http-client",
- "keywords": [
- "http",
- "http-client",
- "psr",
- "psr-18"
- ]
- },
- {
- "name": "psr/http-message",
- "version": "1.0.1",
- "version_normalized": "1.0.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/http-message.git",
- "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
- "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "time": "2016-08-06T14:39:51+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Psr\\Http\\Message\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "description": "Common interface for HTTP messages",
- "homepage": "https://github.com/php-fig/http-message",
- "keywords": [
- "http",
- "http-message",
- "psr",
- "psr-7",
- "request",
- "response"
- ]
- },
- {
- "name": "ralouphie/getallheaders",
- "version": "3.0.3",
- "version_normalized": "3.0.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/ralouphie/getallheaders.git",
- "reference": "120b605dfeb996808c31b6477290a714d356e822"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
- "reference": "120b605dfeb996808c31b6477290a714d356e822",
- "shasum": ""
- },
- "require": {
- "php": ">=5.6"
- },
- "require-dev": {
- "php-coveralls/php-coveralls": "^2.1",
- "phpunit/phpunit": "^5 || ^6.5"
- },
- "time": "2019-03-08T08:55:37+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "files": [
- "src/getallheaders.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Ralph Khattar",
- "email": "ralph.khattar@gmail.com"
- }
- ],
- "description": "A polyfill for getallheaders."
- },
- {
- "name": "scssphp/scssphp",
- "version": "1.2.1",
- "version_normalized": "1.2.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/scssphp/scssphp.git",
- "reference": "a05ea68160b7286ebbfd6e5fd7ae9e1a946ad6e1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/scssphp/scssphp/zipball/a05ea68160b7286ebbfd6e5fd7ae9e1a946ad6e1",
- "reference": "a05ea68160b7286ebbfd6e5fd7ae9e1a946ad6e1",
- "shasum": ""
- },
- "require": {
- "ext-ctype": "*",
- "ext-json": "*",
- "php": ">=5.6.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
- "sass/sass-spec": "2020.08.10",
- "squizlabs/php_codesniffer": "~3.5",
- "twbs/bootstrap": "~4.3",
- "zurb/foundation": "~6.5"
- },
- "time": "2020-09-07T21:15:42+00:00",
- "bin": [
- "bin/pscss"
- ],
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "ScssPhp\\ScssPhp\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Anthon Pang",
- "email": "apang@softwaredevelopment.ca",
- "homepage": "https://github.com/robocoder"
- },
- {
- "name": "Cédric Morin",
- "email": "cedric@yterium.com",
- "homepage": "https://github.com/Cerdic"
- }
- ],
- "description": "scssphp is a compiler for SCSS written in PHP.",
- "homepage": "http://scssphp.github.io/scssphp/",
- "keywords": [
- "css",
- "less",
- "sass",
- "scss",
- "stylesheet"
- ]
- },
- {
- "name": "symfony/css-selector",
- "version": "v4.4.15",
- "version_normalized": "4.4.15.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/css-selector.git",
- "reference": "bf17dc9f6ce144e41f786c32435feea4d8e11dcc"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/bf17dc9f6ce144e41f786c32435feea4d8e11dcc",
- "reference": "bf17dc9f6ce144e41f786c32435feea4d8e11dcc",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1.3"
- },
- "time": "2020-07-05T09:39:30+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "4.4-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\CssSelector\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Jean-François Simon",
- "email": "jeanfrancois.simon@sensiolabs.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony CssSelector Component",
- "homepage": "https://symfony.com",
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ]
- },
- {
- "name": "symfony/polyfill-mbstring",
- "version": "v1.18.1",
- "version_normalized": "1.18.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a",
- "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "time": "2020-07-14T12:35:20+00:00",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.18-dev"
- },
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ],
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ]
- },
- {
- "name": "true/punycode",
- "version": "v2.1.1",
- "version_normalized": "2.1.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/true/php-punycode.git",
- "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
- "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0",
- "symfony/polyfill-mbstring": "^1.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.7",
- "squizlabs/php_codesniffer": "~2.0"
- },
- "time": "2016-11-16T10:37:54+00:00",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "TrueBV\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Renan Gonçalves",
- "email": "renan.saddam@gmail.com"
- }
- ],
- "description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
- "homepage": "https://github.com/true/php-punycode",
- "keywords": [
- "idna",
- "punycode"
- ]
- }
-]
+{
+ "packages": [
+ {
+ "name": "chrisjean/php-ico",
+ "version": "1.0.4",
+ "version_normalized": "1.0.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/chrisbliss18/php-ico.git",
+ "reference": "ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/chrisbliss18/php-ico/zipball/ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6",
+ "reference": "ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-gd": "*",
+ "php": ">=5.2.4"
+ },
+ "time": "2016-09-27T22:00:56+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "class-php-ico.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Chris Jean",
+ "homepage": "https://chrisjean.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "An easy-to-use library to generate valid ICO files.",
+ "homepage": "https://github.com/chrisbliss18/php-ico",
+ "keywords": [
+ "favicon",
+ "ico"
+ ],
+ "install-path": "../chrisjean/php-ico"
+ },
+ {
+ "name": "erusev/parsedown",
+ "version": "1.7.4",
+ "version_normalized": "1.7.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/erusev/parsedown.git",
+ "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
+ "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35"
+ },
+ "time": "2019-12-30T22:54:17+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Parsedown": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Emanuil Rusev",
+ "email": "hello@erusev.com",
+ "homepage": "http://erusev.com"
+ }
+ ],
+ "description": "Parser for Markdown.",
+ "homepage": "http://parsedown.org",
+ "keywords": [
+ "markdown",
+ "parser"
+ ],
+ "install-path": "../erusev/parsedown"
+ },
+ {
+ "name": "ezyang/htmlpurifier",
+ "version": "v4.13.0",
+ "version_normalized": "4.13.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ezyang/htmlpurifier.git",
+ "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
+ "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2"
+ },
+ "require-dev": {
+ "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
+ },
+ "time": "2020-06-29T00:56:53+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "HTMLPurifier": "library/"
+ },
+ "files": [
+ "library/HTMLPurifier.composer.php"
+ ],
+ "exclude-from-classmap": [
+ "/library/HTMLPurifier/Language/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-2.1-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Edward Z. Yang",
+ "email": "admin@htmlpurifier.org",
+ "homepage": "http://ezyang.com"
+ }
+ ],
+ "description": "Standards compliant HTML filter written in PHP",
+ "homepage": "http://htmlpurifier.org/",
+ "keywords": [
+ "html"
+ ],
+ "install-path": "../ezyang/htmlpurifier"
+ },
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.2.0",
+ "version_normalized": "7.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79",
+ "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.4",
+ "guzzlehttp/psr7": "^1.7",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "ext-curl": "*",
+ "php-http/client-integration-tests": "^3.0",
+ "phpunit/phpunit": "^8.5.5 || ^9.3.5",
+ "psr/log": "^1.1"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "time": "2020-10-10T11:47:56+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "homepage": "http://guzzlephp.org/",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/alexeyshockov",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/gmponos",
+ "type": "github"
+ }
+ ],
+ "install-path": "../guzzlehttp/guzzle"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "1.4.0",
+ "version_normalized": "1.4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "60d379c243457e073cff02bc323a2a86cb355631"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/60d379c243457e073cff02bc323a2a86cb355631",
+ "reference": "60d379c243457e073cff02bc323a2a86cb355631",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ },
+ "time": "2020-09-30T07:37:28+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "install-path": "../guzzlehttp/promises"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "1.7.0",
+ "version_normalized": "1.7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3",
+ "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0",
+ "psr/http-message": "~1.0",
+ "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "ext-zlib": "*",
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "time": "2020-09-30T07:37:11+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.7-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ },
+ "files": [
+ "src/functions_include.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Schultze",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "install-path": "../guzzlehttp/psr7"
+ },
+ {
+ "name": "pear/net_idna2",
+ "version": "v0.2.0",
+ "version_normalized": "0.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pear/Net_IDNA2.git",
+ "reference": "51734eaf8be2df58e8aad5835b9966459b2fb37c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pear/Net_IDNA2/zipball/51734eaf8be2df58e8aad5835b9966459b2fb37c",
+ "reference": "51734eaf8be2df58e8aad5835b9966459b2fb37c",
+ "shasum": ""
+ },
+ "require": {
+ "pear/pear_exception": "@stable"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4"
+ },
+ "time": "2017-03-06T20:46:41+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-0": {
+ "Net": "./"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ "./"
+ ],
+ "license": [
+ "LGPL"
+ ],
+ "authors": [
+ {
+ "name": "Stefan Neufeind",
+ "email": "pear.neufeind@speedpartner.de",
+ "role": "Lead"
+ },
+ {
+ "name": "Daniel O'Connor",
+ "email": "daniel.oconnor@gmail.com",
+ "role": "Lead"
+ }
+ ],
+ "description": "More info available on: https://pear.php.net/package/Net_IDNA2",
+ "install-path": "../pear/net_idna2"
+ },
+ {
+ "name": "pear/pear_exception",
+ "version": "v1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pear/PEAR_Exception.git",
+ "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
+ "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=4.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "time": "2019-12-10T10:24:42+00:00",
+ "type": "class",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "PEAR/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ "."
+ ],
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Helgi Thormar",
+ "email": "dufuz@php.net"
+ },
+ {
+ "name": "Greg Beaver",
+ "email": "cellog@php.net"
+ }
+ ],
+ "description": "The PEAR Exception base class.",
+ "homepage": "https://github.com/pear/PEAR_Exception",
+ "keywords": [
+ "exception"
+ ],
+ "install-path": "../pear/pear_exception"
+ },
+ {
+ "name": "pelago/emogrifier",
+ "version": "v2.1.1",
+ "version_normalized": "2.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MyIntervals/emogrifier.git",
+ "reference": "8ee7fb5ad772915451ed3415c1992bd3697d4983"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/8ee7fb5ad772915451ed3415c1992bd3697d4983",
+ "reference": "8ee7fb5ad772915451ed3415c1992bd3697d4983",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "php": "^5.5.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0",
+ "symfony/css-selector": "^3.4.0 || ^4.0.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^2.2.0",
+ "phpmd/phpmd": "^2.6.0",
+ "phpunit/phpunit": "^4.8.0",
+ "squizlabs/php_codesniffer": "^3.3.2"
+ },
+ "time": "2018-12-10T10:36:30+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.1.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Pelago\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Reeve",
+ "email": "jreeve@pelagodesign.com"
+ },
+ {
+ "name": "Cameron Brooks"
+ },
+ {
+ "name": "Jaime Prado"
+ },
+ {
+ "name": "Oliver Klee",
+ "email": "github@oliverklee.de"
+ },
+ {
+ "name": "Zoli Szabó",
+ "email": "zoli.szabo+github@gmail.com"
+ },
+ {
+ "name": "Jake Hotson",
+ "email": "jake@qzdesign.co.uk"
+ }
+ ],
+ "description": "Converts CSS styles into inline style attributes in your HTML code",
+ "homepage": "https://www.myintervals.com/emogrifier.php",
+ "keywords": [
+ "css",
+ "email",
+ "pre-processing"
+ ],
+ "install-path": "../pelago/emogrifier"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+ "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0"
+ },
+ "time": "2020-06-29T06:28:15+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "install-path": "../psr/http-client"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2016-08-06T14:39:51+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "install-path": "../psr/http-message"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "version_normalized": "3.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "time": "2019-03-08T08:55:37+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "install-path": "../ralouphie/getallheaders"
+ },
+ {
+ "name": "scssphp/scssphp",
+ "version": "1.3",
+ "version_normalized": "1.3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/scssphp/scssphp.git",
+ "reference": "261cd018025d5790e135a1e5b694d6af186e6bca"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/scssphp/scssphp/zipball/261cd018025d5790e135a1e5b694d6af186e6bca",
+ "reference": "261cd018025d5790e135a1e5b694d6af186e6bca",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "php": ">=5.6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4",
+ "sass/sass-spec": "2020.08.10",
+ "squizlabs/php_codesniffer": "~3.5",
+ "twbs/bootstrap": "~4.3",
+ "zurb/foundation": "~6.5"
+ },
+ "time": "2020-10-29T11:09:57+00:00",
+ "bin": [
+ "bin/pscss"
+ ],
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "ScssPhp\\ScssPhp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Anthon Pang",
+ "email": "apang@softwaredevelopment.ca",
+ "homepage": "https://github.com/robocoder"
+ },
+ {
+ "name": "Cédric Morin",
+ "email": "cedric@yterium.com",
+ "homepage": "https://github.com/Cerdic"
+ }
+ ],
+ "description": "scssphp is a compiler for SCSS written in PHP.",
+ "homepage": "http://scssphp.github.io/scssphp/",
+ "keywords": [
+ "css",
+ "less",
+ "sass",
+ "scss",
+ "stylesheet"
+ ],
+ "support": {
+ "issues": "https://github.com/scssphp/scssphp/issues",
+ "source": "https://github.com/scssphp/scssphp/tree/1.3"
+ },
+ "install-path": "../scssphp/scssphp"
+ },
+ {
+ "name": "symfony/css-selector",
+ "version": "v4.4.15",
+ "version_normalized": "4.4.15.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/css-selector.git",
+ "reference": "bf17dc9f6ce144e41f786c32435feea4d8e11dcc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/bf17dc9f6ce144e41f786c32435feea4d8e11dcc",
+ "reference": "bf17dc9f6ce144e41f786c32435feea4d8e11dcc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.3"
+ },
+ "time": "2020-07-05T09:39:30+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.4-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\CssSelector\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Jean-François Simon",
+ "email": "jeanfrancois.simon@sensiolabs.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony CssSelector Component",
+ "homepage": "https://symfony.com",
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/css-selector"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.18.1",
+ "version_normalized": "1.18.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a6977d63bf9a0ad4c65cd352709e230876f9904a",
+ "reference": "a6977d63bf9a0ad4c65cd352709e230876f9904a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2020-07-14T12:35:20+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.18-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/polyfill-mbstring"
+ },
+ {
+ "name": "true/punycode",
+ "version": "v2.1.1",
+ "version_normalized": "2.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/true/php-punycode.git",
+ "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
+ "reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "symfony/polyfill-mbstring": "^1.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.7",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "time": "2016-11-16T10:37:54+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "TrueBV\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Renan Gonçalves",
+ "email": "renan.saddam@gmail.com"
+ }
+ ],
+ "description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
+ "homepage": "https://github.com/true/php-punycode",
+ "keywords": [
+ "idna",
+ "punycode"
+ ],
+ "install-path": "../true/punycode"
+ }
+ ],
+ "dev": false
+}
--- /dev/null
+<?php return array (
+ 'root' =>
+ array (
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'f448efb8521534c520f84e89a1a38296d4c0e5fd',
+ 'name' => '__root__',
+ ),
+ 'versions' =>
+ array (
+ '__root__' =>
+ array (
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'f448efb8521534c520f84e89a1a38296d4c0e5fd',
+ ),
+ 'chrisjean/php-ico' =>
+ array (
+ 'pretty_version' => '1.0.4',
+ 'version' => '1.0.4.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'ccd5c0d56554f3ddcd7a823e695be83e0d1e43b6',
+ ),
+ 'erusev/parsedown' =>
+ array (
+ 'pretty_version' => '1.7.4',
+ 'version' => '1.7.4.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
+ ),
+ 'ezyang/htmlpurifier' =>
+ array (
+ 'pretty_version' => 'v4.13.0',
+ 'version' => '4.13.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '08e27c97e4c6ed02f37c5b2b20488046c8d90d75',
+ ),
+ 'guzzlehttp/guzzle' =>
+ array (
+ 'pretty_version' => '7.2.0',
+ 'version' => '7.2.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '0aa74dfb41ae110835923ef10a9d803a22d50e79',
+ ),
+ 'guzzlehttp/promises' =>
+ array (
+ 'pretty_version' => '1.4.0',
+ 'version' => '1.4.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '60d379c243457e073cff02bc323a2a86cb355631',
+ ),
+ 'guzzlehttp/psr7' =>
+ array (
+ 'pretty_version' => '1.7.0',
+ 'version' => '1.7.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '53330f47520498c0ae1f61f7e2c90f55690c06a3',
+ ),
+ 'pear/net_idna2' =>
+ array (
+ 'pretty_version' => 'v0.2.0',
+ 'version' => '0.2.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '51734eaf8be2df58e8aad5835b9966459b2fb37c',
+ ),
+ 'pear/pear_exception' =>
+ array (
+ 'pretty_version' => 'v1.0.1',
+ 'version' => '1.0.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7',
+ ),
+ 'pelago/emogrifier' =>
+ array (
+ 'pretty_version' => 'v2.1.1',
+ 'version' => '2.1.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '8ee7fb5ad772915451ed3415c1992bd3697d4983',
+ ),
+ 'psr/http-client' =>
+ array (
+ 'pretty_version' => '1.0.1',
+ 'version' => '1.0.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
+ ),
+ 'psr/http-client-implementation' =>
+ array (
+ 'provided' =>
+ array (
+ 0 => '1.0',
+ ),
+ ),
+ 'psr/http-message' =>
+ array (
+ 'pretty_version' => '1.0.1',
+ 'version' => '1.0.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
+ ),
+ 'psr/http-message-implementation' =>
+ array (
+ 'provided' =>
+ array (
+ 0 => '1.0',
+ ),
+ ),
+ 'ralouphie/getallheaders' =>
+ array (
+ 'pretty_version' => '3.0.3',
+ 'version' => '3.0.3.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '120b605dfeb996808c31b6477290a714d356e822',
+ ),
+ 'scssphp/scssphp' =>
+ array (
+ 'pretty_version' => '1.3',
+ 'version' => '1.3.0.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => '261cd018025d5790e135a1e5b694d6af186e6bca',
+ ),
+ 'symfony/css-selector' =>
+ array (
+ 'pretty_version' => 'v4.4.15',
+ 'version' => '4.4.15.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'bf17dc9f6ce144e41f786c32435feea4d8e11dcc',
+ ),
+ 'symfony/polyfill-mbstring' =>
+ array (
+ 'pretty_version' => 'v1.18.1',
+ 'version' => '1.18.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'a6977d63bf9a0ad4c65cd352709e230876f9904a',
+ ),
+ 'true/punycode' =>
+ array (
+ 'pretty_version' => 'v2.1.1',
+ 'version' => '2.1.1.0',
+ 'aliases' =>
+ array (
+ ),
+ 'reference' => 'a4d0c11a36dd7f4e7cd7096076cab6d3378a071e',
+ ),
+ ),
+);
--- /dev/null
+<?php
+
+// platform_check.php @generated by Composer
+
+$issues = array();
+
+if (!(PHP_VERSION_ID >= 70205)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
+}
+
+$missingExtensions = array();
+extension_loaded('ctype') || $missingExtensions[] = 'ctype';
+extension_loaded('dom') || $missingExtensions[] = 'dom';
+extension_loaded('gd') || $missingExtensions[] = 'gd';
+extension_loaded('json') || $missingExtensions[] = 'json';
+extension_loaded('libxml') || $missingExtensions[] = 'libxml';
+extension_loaded('mbstring') || $missingExtensions[] = 'mbstring';
+
+if ($missingExtensions) {
+ $issues[] = 'Your Composer dependencies require the following PHP extensions to be installed: ' . implode(', ', $missingExtensions);
+}
+
+if ($issues) {
+ echo 'Composer detected issues in your platform:' . "\n\n" . implode("\n", $issues);
+ exit(104);
+}
# scssphp
### <https://scssphp.github.io/scssphp>
-[![Build](https://travis-ci.org/scssphp/scssphp.svg?branch=master)](https://travis-ci.org/scssphp/scssphp)
+[![Build](https://travis-ci.com/scssphp/scssphp.svg?branch=master)](https://travis-ci.com/scssphp/scssphp)
[![License](https://poser.pugx.org/scssphp/scssphp/license)](https://packagist.org/packages/scssphp/scssphp)
`scssphp` is a compiler for SCSS written in PHP.
$dumpTree = false;
$inputFile = null;
$changeDir = false;
-$debugInfo = false;
-$lineNumbers = false;
$encoding = false;
$sourceMap = false;
--help Show this message [-h, -?]
--continue-on-error [deprecated] Ignored
- --debug-info Annotate selectors with CSS referring to the source file and line number [-g]
+ --debug-info [deprecated] Ignored [-g]
--dump-tree Dump formatted parse tree [-T]
--iso8859-1 Use iso8859-1 encoding instead of default utf-8
- --line-numbers Annotate selectors with comments referring to the source file and line number [--line-comments]
+ --line-numbers [deprecated] Ignored [--line-comments]
--load-path=PATH Set import path [-I]
--precision=N [deprecated] Ignored. (default 10) [-p]
--sourcemap Create source map file
continue;
}
+ // Keep parsing it to avoid BC breaks for scripts using it
if ($argv[$i] === '-g' || $argv[$i] === '--debug-info') {
- $debugInfo = true;
+ // TODO report it as a warning ?
continue;
}
continue;
}
+ // Keep parsing it to avoid BC breaks for scripts using it
if ($argv[$i] === '--line-numbers' || $argv[$i] === '--line-comments') {
- $lineNumbers = true;
+ // TODO report it as a warning ?
continue;
}
$scss = new Compiler();
-if ($debugInfo) {
- $scss->setLineNumberStyle(Compiler::DEBUG_INFO);
-}
-
-if ($lineNumbers) {
- $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
-}
-
if ($loadPaths) {
$scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths));
}
"ext-ctype": "*"
},
"require-dev": {
+ "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4",
"sass/sass-spec": "2020.08.10",
"squizlabs/php_codesniffer": "~3.5",
- "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
"twbs/bootstrap": "~4.3",
"zurb/foundation": "~6.5"
},
}
}
],
- "minimum-stability": "dev",
"bin": ["bin/pscss"],
- "archive": {
- "exclude": [
- "/Makefile",
- "/.gitattributes",
- "/.gitignore",
- "/.travis.yml",
- "/phpunit.xml.dist",
- "/tests"
- ]
+ "config": {
+ "sort-packages": true
}
}
include_once __DIR__ . '/src/Compiler.php';
include_once __DIR__ . '/src/Compiler/Environment.php';
include_once __DIR__ . '/src/Exception/SassException.php';
+ include_once __DIR__ . '/src/Exception/SassScriptException.php';
include_once __DIR__ . '/src/Exception/CompilerException.php';
include_once __DIR__ . '/src/Exception/ParserException.php';
include_once __DIR__ . '/src/Exception/RangeException.php';
use ScssPhp\ScssPhp\Colors;
use ScssPhp\ScssPhp\Compiler\Environment;
use ScssPhp\ScssPhp\Exception\CompilerException;
+use ScssPhp\ScssPhp\Exception\SassScriptException;
use ScssPhp\ScssPhp\Formatter\OutputBlock;
use ScssPhp\ScssPhp\Node;
+use ScssPhp\ScssPhp\Node\Number;
use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
use ScssPhp\ScssPhp\Type;
use ScssPhp\ScssPhp\Parser;
*/
class Compiler
{
+ /**
+ * @deprecated
+ */
const LINE_COMMENTS = 1;
+ /**
+ * @deprecated
+ */
const DEBUG_INFO = 2;
+ /**
+ * @deprecated
+ */
const WITH_RULE = 1;
+ /**
+ * @deprecated
+ */
const WITH_MEDIA = 2;
+ /**
+ * @deprecated
+ */
const WITH_SUPPORTS = 4;
+ /**
+ * @deprecated
+ */
const WITH_ALL = 7;
const SOURCE_MAP_NONE = 0;
'<=' => 'lte',
'>=' => 'gte',
- '<=>' => 'cmp',
];
/**
public static $true = [Type::T_KEYWORD, 'true'];
public static $false = [Type::T_KEYWORD, 'false'];
+ /** @deprecated */
public static $NaN = [Type::T_KEYWORD, 'NaN'];
+ /** @deprecated */
public static $Infinity = [Type::T_KEYWORD, 'Infinity'];
public static $null = [Type::T_NULL];
public static $nullString = [Type::T_STRING, '', []];
];
protected $encoding = null;
+ /**
+ * @deprecated
+ */
protected $lineNumberStyle = null;
protected $sourceMap = self::SOURCE_MAP_NONE;
$this->shouldEvaluate = null;
$this->ignoreCallStackMessage = false;
- $this->parser = $this->parserFactory($path);
- $tree = $this->parser->parse($code);
- $this->parser = null;
+ try {
+ $this->parser = $this->parserFactory($path);
+ $tree = $this->parser->parse($code);
+ $this->parser = null;
- $this->formatter = new $this->formatter();
- $this->rootBlock = null;
- $this->rootEnv = $this->pushEnv($tree);
+ $this->formatter = new $this->formatter();
+ $this->rootBlock = null;
+ $this->rootEnv = $this->pushEnv($tree);
- $this->injectVariables($this->registeredVars);
- $this->compileRoot($tree);
- $this->popEnv();
+ $this->injectVariables($this->registeredVars);
+ $this->compileRoot($tree);
+ $this->popEnv();
- $sourceMapGenerator = null;
+ $sourceMapGenerator = null;
- if ($this->sourceMap) {
- if (\is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) {
- $sourceMapGenerator = $this->sourceMap;
- $this->sourceMap = self::SOURCE_MAP_FILE;
- } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) {
- $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions);
+ if ($this->sourceMap) {
+ if (\is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) {
+ $sourceMapGenerator = $this->sourceMap;
+ $this->sourceMap = self::SOURCE_MAP_FILE;
+ } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) {
+ $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions);
+ }
}
- }
- $out = $this->formatter->format($this->scope, $sourceMapGenerator);
+ $out = $this->formatter->format($this->scope, $sourceMapGenerator);
- if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
- $sourceMap = $sourceMapGenerator->generateJson();
- $sourceMapUrl = null;
+ if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
+ $sourceMap = $sourceMapGenerator->generateJson();
+ $sourceMapUrl = null;
- switch ($this->sourceMap) {
- case self::SOURCE_MAP_INLINE:
- $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap));
- break;
+ switch ($this->sourceMap) {
+ case self::SOURCE_MAP_INLINE:
+ $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap));
+ break;
- case self::SOURCE_MAP_FILE:
- $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap);
- break;
- }
+ case self::SOURCE_MAP_FILE:
+ $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap);
+ break;
+ }
- $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl);
+ $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl);
+ }
+ } catch (SassScriptException $e) {
+ throw $this->error($e->getMessage());
}
if ($this->cache && isset($cacheKey) && isset($compileOptions)) {
$this->cache->setCache('compile', $cacheKey, $v, $compileOptions);
}
+ if (!$this->charsetSeen && function_exists('mb_strlen')) {
+ if (strlen($out) !== mb_strlen($out)) {
+ $out = '@charset "UTF-8";' . "\n" . $out;
+ }
+ }
+
return $out;
}
$buffer = $matches[2];
$parser = $this->parserFactory(__METHOD__);
- if ($parser->parseSelector($buffer, $subSelectors)) {
+ if ($parser->parseSelector($buffer, $subSelectors, false)) {
foreach ($subSelectors as $ksub => $subSelector) {
$subExtended = [];
$this->matchExtends($subSelector, $subExtended, 0, false);
$wrapped->children = $media->children;
$media->children = [[Type::T_BLOCK, $wrapped]];
-
- if (isset($this->lineNumberStyle)) {
- $annotation = $this->makeOutputBlock(Type::T_COMMENT);
- $annotation->depth = 0;
-
- $file = $this->sourceNames[$media->sourceIndex];
- $line = $media->sourceLine;
-
- switch ($this->lineNumberStyle) {
- case static::LINE_COMMENTS:
- $annotation->lines[] = '/* line ' . $line
- . ($file ? ', ' . $file : '')
- . ' */';
- break;
-
- case static::DEBUG_INFO:
- $annotation->lines[] = '@media -sass-debug-info{'
- . ($file ? 'filename{font-family:"' . $file . '"}' : '')
- . 'line{font-family:' . $line . '}}';
- break;
- }
-
- $this->scope->children[] = $annotation;
- }
}
$this->compileChildrenNoReturn($media->children, $this->scope);
$s = reset($s);
}
- if (\is_object($s) && $s instanceof Node\Number) {
+ if (\is_object($s) && $s instanceof Number) {
return $this->testWithWithout('keyframes', $with, $without);
}
}
$out = $this->makeOutputBlock(null);
- if (isset($this->lineNumberStyle) && \count($env->selectors) && \count($block->children)) {
- $annotation = $this->makeOutputBlock(Type::T_COMMENT);
- $annotation->depth = 0;
-
- $file = $this->sourceNames[$block->sourceIndex];
- $line = $block->sourceLine;
-
- switch ($this->lineNumberStyle) {
- case static::LINE_COMMENTS:
- $annotation->lines[] = '/* line ' . $line
- . ($file ? ', ' . $file : '')
- . ' */';
- break;
-
- case static::DEBUG_INFO:
- $annotation->lines[] = '@media -sass-debug-info{'
- . ($file ? 'filename{font-family:"' . $file . '"}' : '')
- . 'line{font-family:' . $line . '}}';
- break;
- }
-
- $this->scope->children[] = $annotation;
- }
-
$this->scope->children[] = $out;
if (\count($block->children)) {
$buffer = $this->collapseSelectors($selectors);
$parser = $this->parserFactory(__METHOD__);
- if ($parser->parseSelector($buffer, $newSelectors)) {
+ if ($parser->parseSelector($buffer, $newSelectors, true)) {
$selectors = array_map([$this, 'evalSelector'], $newSelectors);
}
}
if (\is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) {
$p = $this->compileValue($p);
- // force re-evaluation
- if (strpos($p, '&') !== false || strpos($p, ',') !== false) {
+ // force re-evaluation if self char or non standard char
+ if (preg_match(',[^\w-],', $p)) {
$this->shouldEvaluate = true;
}
} elseif (
$divider = $this->reduce($divider, true);
}
- if (\intval($divider->dimension) && ! \count($divider->units)) {
+ if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) {
$revert = false;
}
}
$divider = $this->reduce($divider, true);
}
- if (\intval($divider->dimension) && ! \count($divider->units)) {
+ if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) {
$revert = false;
}
}
$ret = $this->compileChildren($each->children, $out);
if ($ret) {
- if ($ret[0] !== Type::T_CONTROL) {
- $store = $this->env->store;
- $this->popEnv();
- $this->backPropagateEnv($store, $each->vars);
+ $store = $this->env->store;
+ $this->popEnv();
+ $this->backPropagateEnv($store, $each->vars);
- return $ret;
- }
-
- if ($ret[1]) {
- break;
- }
+ return $ret;
}
}
$store = $this->env->store;
$ret = $this->compileChildren($while->children, $out);
if ($ret) {
- if ($ret[0] !== Type::T_CONTROL) {
- return $ret;
- }
-
- if ($ret[1]) {
- break;
- }
+ return $ret;
}
}
break;
$start = $this->reduce($for->start, true);
$end = $this->reduce($for->end, true);
- if (! $start instanceof Node\Number) {
+ if (! $start instanceof Number) {
throw $this->error('%s is not a number', $start[0]);
}
- if (! $end instanceof Node\Number) {
+ if (! $end instanceof Number) {
throw $this->error('%s is not a number', $end[0]);
}
- if (! ($start[2] == $end[2] || $end->unitless())) {
- throw $this->error('Incompatible units: "%s" && "%s".', $start->unitStr(), $end->unitStr());
- }
+ $start->assertSameUnitOrUnitless($end);
- $unit = $start[2];
- $start = $start[1];
- $end = $end[1];
+ $numeratorUnits = $start->getNumeratorUnits();
+ $denominatorUnits = $start->getDenominatorUnits();
+
+ $start = $start->getDimension();
+ $end = $end->getDimension();
$d = $start < $end ? 1 : -1;
break;
}
- $this->set($for->var, new Node\Number($start, $unit));
+ $this->set($for->var, new Number($start, $numeratorUnits, $denominatorUnits));
$start += $d;
$ret = $this->compileChildren($for->children, $out);
if ($ret) {
- if ($ret[0] !== Type::T_CONTROL) {
- $store = $this->env->store;
- $this->popEnv();
- $this->backPropagateEnv($store, [$for->var]);
-
- return $ret;
- }
+ $store = $this->env->store;
+ $this->popEnv();
+ $this->backPropagateEnv($store, [$for->var]);
- if ($ret[1]) {
- break;
- }
+ return $ret;
}
}
break;
- case Type::T_BREAK:
- return [Type::T_CONTROL, true];
-
- case Type::T_CONTINUE:
- return [Type::T_CONTROL, false];
-
case Type::T_RETURN:
return $this->reduce($child[1], true);
throw $this->error("File $fname on line $line ERROR: $value\n");
- case Type::T_CONTROL:
- throw $this->error('@break/@continue not permitted in this scope');
-
default:
throw $this->error("unknown child type: $child[0]");
}
* @param array $value
* @param boolean $inExp
*
- * @return null|string|array|\ScssPhp\ScssPhp\Node\Number
+ * @return null|string|array|Number
*/
protected function reduce($value, $inExp = false)
{
// special case: looks like css shorthand
if (
- $opName == 'div' && ! $inParens && ! $inExp && isset($right[2]) &&
- (($right[0] !== Type::T_NUMBER && $right[2] != '') ||
+ $opName == 'div' && ! $inParens && ! $inExp &&
+ (($right[0] !== Type::T_NUMBER && isset($right[2]) && $right[2] != '') ||
($right[0] === Type::T_NUMBER && ! $right->unitless()))
) {
return $this->expToString($value);
\is_callable([$this, $fn]) &&
$genOp = true)
) {
- $coerceUnit = false;
-
- if (
- ! isset($genOp) &&
- $left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
- ) {
- $coerceUnit = true;
-
- switch ($opName) {
- case 'mul':
- $targetUnit = $left[2];
-
- foreach ($right[2] as $unit => $exp) {
- $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) + $exp;
- }
- break;
-
- case 'div':
- $targetUnit = $left[2];
-
- foreach ($right[2] as $unit => $exp) {
- $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) - $exp;
- }
- break;
-
- case 'mod':
- $targetUnit = $left[2];
- break;
-
- default:
- $targetUnit = $left->unitless() ? $right[2] : $left[2];
- }
-
- $baseUnitLeft = $left->isNormalizable();
- $baseUnitRight = $right->isNormalizable();
-
- if ($baseUnitLeft && $baseUnitRight && $baseUnitLeft === $baseUnitRight) {
- $left = $left->normalize();
- $right = $right->normalize();
- } elseif ($coerceUnit) {
- $left = new Node\Number($left[1], []);
- }
- }
-
$shouldEval = $inParens || $inExp;
if (isset($passOp)) {
}
if (isset($out)) {
- if ($coerceUnit && $out[0] === Type::T_NUMBER) {
- $out = $out->coerce($targetUnit);
- }
-
return $out;
}
}
$inExp = $inExp || $this->shouldEval($exp);
$exp = $this->reduce($exp);
- if ($exp[0] === Type::T_NUMBER) {
+ if ($exp instanceof Number) {
switch ($op) {
case '+':
- return new Node\Number($exp[1], $exp[2]);
+ return $exp;
case '-':
- return new Node\Number(-$exp[1], $exp[2]);
+ return $exp->unaryMinus();
}
}
/**
* Reformat fncall arguments to proper css function output
+ *
* @param $arg
- * @return array|\ArrayAccess|Node\Number|string|null
+ *
+ * @return array|\ArrayAccess|Number|string|null
*/
protected function stringifyFncallArgs($arg)
{
case Type::T_STRING:
return [$value[0], '"', [$this->compileStringContent($value)]];
- case Type::T_NUMBER:
- return $value->normalize();
-
case Type::T_INTERPOLATE:
return [Type::T_KEYWORD, $this->compileValue($value)];
/**
* Add numbers
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return Number
*/
- protected function opAddNumberNumber($left, $right)
+ protected function opAddNumberNumber(Number $left, Number $right)
{
- return new Node\Number($left[1] + $right[1], $left[2]);
+ return $left->plus($right);
}
/**
* Multiply numbers
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return Number
*/
- protected function opMulNumberNumber($left, $right)
+ protected function opMulNumberNumber(Number $left, Number $right)
{
- return new Node\Number($left[1] * $right[1], $left[2]);
+ return $left->times($right);
}
/**
* Subtract numbers
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return Number
*/
- protected function opSubNumberNumber($left, $right)
+ protected function opSubNumberNumber(Number $left, Number $right)
{
- return new Node\Number($left[1] - $right[1], $left[2]);
+ return $left->minus($right);
}
/**
* Divide numbers
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
- * @return array|\ScssPhp\ScssPhp\Node\Number
+ * @return Number
*/
- protected function opDivNumberNumber($left, $right)
+ protected function opDivNumberNumber(Number $left, Number $right)
{
- if ($right[1] == 0) {
- return ($left[1] == 0) ? static::$NaN : static::$Infinity;
- }
-
- return new Node\Number($left[1] / $right[1], $left[2]);
+ return $left->dividedBy($right);
}
/**
* Mod numbers
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return Number
*/
- protected function opModNumberNumber($left, $right)
+ protected function opModNumberNumber(Number $left, Number $right)
{
- if ($right[1] == 0) {
- return static::$NaN;
- }
-
- return new Node\Number($left[1] % $right[1], $left[2]);
+ return $left->modulo($right);
}
/**
*
* @param string $op
* @param array $left
- * @param array $right
+ * @param Number $right
*
* @return array
*/
- protected function opColorNumber($op, $left, $right)
+ protected function opColorNumber($op, $left, Number $right)
{
- $value = $right[1];
+ $value = $right->getDimension();
return $this->opColorColor(
$op,
* Compare number and color
*
* @param string $op
- * @param array $left
+ * @param Number $left
* @param array $right
*
* @return array
*/
- protected function opNumberColor($op, $left, $right)
+ protected function opNumberColor($op, Number $left, $right)
{
- $value = $left[1];
+ $value = $left->getDimension();
return $this->opColorColor(
$op,
}
/**
- * Compare number1 >= number2
+ * Compare number1 == number2
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
* @return array
*/
- protected function opGteNumberNumber($left, $right)
+ protected function opEqNumberNumber(Number $left, Number $right)
{
- return $this->toBool($left[1] >= $right[1]);
+ return $this->toBool($left->equals($right));
}
/**
- * Compare number1 > number2
+ * Compare number1 != number2
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
* @return array
*/
- protected function opGtNumberNumber($left, $right)
+ protected function opNeqNumberNumber(Number $left, Number $right)
{
- return $this->toBool($left[1] > $right[1]);
+ return $this->toBool(!$left->equals($right));
}
/**
- * Compare number1 <= number2
+ * Compare number1 >= number2
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
* @return array
*/
- protected function opLteNumberNumber($left, $right)
+ protected function opGteNumberNumber(Number $left, Number $right)
{
- return $this->toBool($left[1] <= $right[1]);
+ return $this->toBool($left->greaterThanOrEqual($right));
}
/**
- * Compare number1 < number2
+ * Compare number1 > number2
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
* @return array
*/
- protected function opLtNumberNumber($left, $right)
+ protected function opGtNumberNumber(Number $left, Number $right)
{
- return $this->toBool($left[1] < $right[1]);
+ return $this->toBool($left->greaterThan($right));
}
/**
- * Three-way comparison, aka spaceship operator
+ * Compare number1 <= number2
*
- * @param array $left
- * @param array $right
+ * @param Number $left
+ * @param Number $right
*
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return array
*/
- protected function opCmpNumberNumber($left, $right)
+ protected function opLteNumberNumber(Number $left, Number $right)
{
- $n = $left[1] - $right[1];
+ return $this->toBool($left->lessThanOrEqual($right));
+ }
- return new Node\Number($n ? $n / abs($n) : 0, '');
+ /**
+ * Compare number1 < number2
+ *
+ * @param Number $left
+ * @param Number $right
+ *
+ * @return array
+ */
+ protected function opLtNumberNumber(Number $left, Number $right)
+ {
+ return $this->toBool($left->lessThan($right));
}
/**
return $thing ? static::$true : static::$false;
}
+ /**
+ * Escape non printable chars in strings output as in dart-sass
+ * @param $string
+ * @return string|string[]
+ */
+ public function escapeNonPrintableChars($string, $inKeyword = false)
+ {
+ static $replacement = [];
+ if (empty($replacement[$inKeyword])) {
+ for ($i = 0; $i < 32; $i++) {
+ if ($i !== 9 || $inKeyword) {
+ $replacement[$inKeyword][chr($i)] = '\\' . dechex($i) . ($inKeyword ? ' ' : chr(0));
+ }
+ }
+ }
+ $string = str_replace(array_keys($replacement[$inKeyword]), array_values($replacement[$inKeyword]), $string);
+ // chr(0) is not a possible char from the input, so any chr(0) comes from our escaping replacement
+ if (strpos($string, chr(0)) !== false) {
+ if (substr($string, -1) === chr(0)) {
+ $string = substr($string, 0, -1);
+ }
+ $string = str_replace(
+ [chr(0) . '\\',chr(0) . ' '],
+ [ '\\', ' '],
+ $string
+ );
+ if (strpos($string, chr(0)) !== false) {
+ $parts = explode(chr(0), $string);
+ $string = array_shift($parts);
+ while (count($parts)) {
+ $next = array_shift($parts);
+ if (strpos("0123456789abcdefABCDEF" . chr(9), $next[0]) !== false) {
+ $string .= " ";
+ }
+ $string .= $next;
+ }
+ }
+ }
+
+ return $string;
+ }
+
/**
* Compiles a primitive value into a CSS property value.
*
switch ($value[0]) {
case Type::T_KEYWORD:
+ if (is_string($value[1])) {
+ $value[1] = $this->escapeNonPrintableChars($value[1], true);
+ }
return $value[1];
case Type::T_COLOR:
}
if (is_numeric($alpha)) {
- $a = new Node\Number($alpha, '');
+ $a = new Number($alpha, '');
} else {
$a = $alpha;
}
$content = $this->compileStringContent($value);
if ($value[1]) {
+ $content = str_replace('\\', '\\\\', $content);
+
+ $content = $this->escapeNonPrintableChars($content);
+
// force double quote as string quote for the output in certain cases
if (
$value[1] === "'" &&
- strpos($content, '"') === false &&
- strpbrk($content, '{}') !== false
+ (strpos($content, '"') === false or strpos($content, "'") !== false) &&
+ strpbrk($content, '{}\\\'') !== false
) {
$value[1] = '"';
+ } elseif (
+ $value[1] === '"' &&
+ (strpos($content, '"') !== false and strpos($content, "'") === false)
+ ) {
+ $value[1] = "'";
}
- $content = str_replace(
- array('\\a', "\n", "\f" , '\\' , "\r" , $value[1]),
- array("\r" , ' ' , '\\f', '\\\\', '\\a', '\\' . $value[1]),
- $content
- );
+
+ $content = str_replace($value[1], '\\' . $value[1], $content);
}
return $value[1] . $content . $value[1];
$filtered = [];
+ $same_string_quote = null;
foreach ($items as $item) {
+ if (\is_null($same_string_quote)) {
+ $same_string_quote = false;
+ if ($item[0] === Type::T_STRING) {
+ $same_string_quote = $item[1];
+ foreach ($items as $ii) {
+ if ($ii[0] !== Type::T_STRING) {
+ $same_string_quote = false;
+ break;
+ }
+ }
+ }
+ }
if ($item[0] === Type::T_NULL) {
continue;
}
+ if ($same_string_quote === '"' && $item[0] === Type::T_STRING && $item[1]) {
+ $item[1] = $same_string_quote;
+ }
$compiled = $this->compileValue($item);
break;
case Type::T_STRING:
- $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)];
+ $reduced = [Type::T_STRING, '', [$this->compileStringContent($reduced)]];
break;
case Type::T_NULL:
* @api
*
* @param string $lineNumberStyle
+ *
+ * @deprecated The line number output is not supported anymore. Use source maps instead.
*/
public function setLineNumberStyle($lineNumberStyle)
{
- $this->lineNumberStyle = $lineNumberStyle;
+ @trigger_error('The line number output is not supported anymore. '
+ . 'Use source maps instead.', E_USER_DEPRECATED);
}
/**
* @api
*
* @param string $name
+ *
+ * @deprecated Registering additional features is deprecated.
*/
public function addFeature($name)
{
+ @trigger_error('Registering additional features is deprecated.', E_USER_DEPRECATED);
+
$this->registeredFeatures[$name] = true;
}
*
* @param mixed $value
*
- * @return array|\ScssPhp\ScssPhp\Node\Number
+ * @return array|Number
*/
protected function coerceValue($value)
{
}
if (is_numeric($value)) {
- return new Node\Number($value, '');
+ return new Number($value, '');
}
if ($value === '') {
if ($color[3] === 255) {
$color[3] = 1; // fully opaque
} else {
- $color[3] = round($color[3] / 255, Node\Number::PRECISION);
+ $color[3] = round($color[3] / 255, Number::PRECISION);
}
}
}
/**
- * @param integer|\ScssPhp\ScssPhp\Node\Number $value
- * @param boolean $isAlpha
+ * @param integer|Number $value
+ * @param boolean $isAlpha
*
* @return integer|mixed
*/
* @param integer|float $min
* @param integer|float $max
* @param boolean $isInt
- * @param boolean $clamp
- * @param boolean $modulo
*
* @return integer|mixed
*/
- protected function compileColorPartValue($value, $min, $max, $isInt = true, $clamp = true, $modulo = false)
+ protected function compileColorPartValue($value, $min, $max, $isInt = true)
{
if (! is_numeric($value)) {
if (\is_array($value)) {
$reduced = $this->reduce($value);
- if (\is_object($reduced) && $value->type === Type::T_NUMBER) {
+ if ($reduced instanceof Number) {
$value = $reduced;
}
}
- if (\is_object($value) && $value->type === Type::T_NUMBER) {
- $num = $value->dimension;
-
- if (\count($value->units)) {
- $unit = array_keys($value->units);
- $unit = reset($unit);
-
- switch ($unit) {
- case '%':
- $num *= $max / 100;
- break;
- default:
- break;
- }
+ if ($value instanceof Number) {
+ if ($value->unitless()) {
+ $num = $value->getDimension();
+ } elseif ($value->hasUnit('%')) {
+ $num = $max * $value->getDimension() / 100;
+ } else {
+ throw $this->error('Expected %s to have no units or "%%".', $value);
}
$value = $num;
$value = round($value);
}
- if ($clamp) {
- $value = min($max, max($min, $value));
- }
-
- if ($modulo) {
- $value = $value % $max;
-
- // still negative?
- while ($value < $min) {
- $value += $max;
- }
- }
+ $value = min($max, max($min, $value));
return $value;
}
*/
protected function coercePercent($value)
{
- if ($value[0] === Type::T_NUMBER) {
- if (! empty($value[2]['%'])) {
- return $value[1] / 100;
+ if ($value instanceof Number) {
+ if ($value->hasUnit('%')) {
+ return $value->getDimension() / 100;
}
- return $value[1];
+ return $value->getDimension();
}
return 0;
*
* @api
*
- * @param array $value
+ * @param mixed $value
* @param string $varName
*
- * @return integer|float
+ * @return Number
*
* @throws \Exception
*/
public function assertNumber($value, $varName = null)
{
- if ($value[0] !== Type::T_NUMBER) {
+ if (!$value instanceof Number) {
$value = $this->compileValue($value);
$var_display = ($varName ? " \${$varName}:" : '');
throw $this->error("Error:{$var_display} $value is not a number.");
}
- return $value[1];
+ return $value;
}
/**
public function assertInteger($value, $varName = null)
{
- $value = $this->assertNumber($value, $varName);
- if (round($value - \intval($value), Node\Number::PRECISION) > 0) {
+ $value = $this->assertNumber($value, $varName)->getDimension();
+ if (round($value - \intval($value), Number::PRECISION) > 0) {
$var_display = ($varName ? " \${$varName}:" : '');
throw $this->error("Error:{$var_display} $value is not an integer.");
}
return static::$null;
}
+ // Numbers are represented with value objects, for which the PHP equality operator does not
+ // match the Sass rules (and we cannot overload it). As they are the only type of values
+ // represented with a value object for now, they require a special case.
+ if ($value instanceof Number) {
+ $key = 0;
+ foreach ($list[2] as $item) {
+ $key++;
+ $itemValue = $this->normalizeValue($item);
+
+ if ($itemValue instanceof Number && $value->equals($itemValue)) {
+ return new Number($key, '');
+ }
+ }
+ return static::$null;
+ }
+
$values = [];
+
foreach ($list[2] as $item) {
$values[] = $this->normalizeValue($item);
}
foreach ([1 => 1, 2 => 2, 3 => 3, 7 => 4] as $iarg => $irgba) {
if (isset($args[$iarg])) {
- $val = $this->assertNumber($args[$iarg]);
+ $val = $this->assertNumber($args[$iarg])->getDimension();
if (! isset($color[$irgba])) {
$color[$irgba] = (($irgba < 4) ? 0 : 1);
foreach ([4 => 1, 5 => 2, 6 => 3] as $iarg => $ihsl) {
if (! empty($args[$iarg])) {
- $val = $this->assertNumber($args[$iarg]);
+ $val = $this->assertNumber($args[$iarg])->getDimension();
$hsl[$ihsl] = \call_user_func($fn, $hsl[$ihsl], $val, $iarg);
}
}
{
$value = $args[0];
- if ($value[0] === Type::T_NUMBER) {
+ if ($value instanceof Number) {
return null;
}
$args_to_check = $kwargs['channels'][2];
}
- $hue = $this->compileColorPartValue($args[0], 0, 360, false, false, true);
- $saturation = $this->compileColorPartValue($args[1], 0, 100, false);
- $lightness = $this->compileColorPartValue($args[2], 0, 100, false);
-
foreach ($kwargs as $k => $arg) {
if (in_array($arg[0], [Type::T_FUNCTION_CALL]) && in_array($arg[1], ['min', 'max'])) {
return null;
}
$args[$k] = $this->stringifyFncallArgs($arg);
- $hue = '';
}
if (
}
}
+ $hue = $this->reduce($args[0]);
+ $saturation = $this->reduce($args[1]);
+ $lightness = $this->reduce($args[2]);
$alpha = null;
if (\count($args) === 4) {
$alpha = $this->compileColorPartValue($args[3], 0, 100, false);
- if (! is_numeric($hue) || ! is_numeric($saturation) || ! is_numeric($lightness) || ! is_numeric($alpha)) {
+ if (!$hue instanceof Number || !$saturation instanceof Number || ! $lightness instanceof Number || ! is_numeric($alpha)) {
return [Type::T_STRING, '',
[$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ', ', $args[3], ')']];
}
} else {
- if (! is_numeric($hue) || ! is_numeric($saturation) || ! is_numeric($lightness)) {
+ if (!$hue instanceof Number || !$saturation instanceof Number || ! $lightness instanceof Number) {
return [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ')']];
}
}
- $color = $this->toRGB($hue, $saturation, $lightness);
+ $hueValue = $hue->getDimension() % 360;
+
+ while ($hueValue < 0) {
+ $hueValue += 360;
+ }
+
+ $color = $this->toRGB($hueValue, max(0, min($saturation->getDimension(), 100)), max(0, min($lightness->getDimension(), 100)));
if (! \is_null($alpha)) {
$color[4] = $alpha;
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return new Node\Number($hsl[1], 'deg');
+ return new Number($hsl[1], 'deg');
}
protected static $libSaturation = ['color'];
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return new Node\Number($hsl[2], '%');
+ return new Number($hsl[2], '%');
}
protected static $libLightness = ['color'];
$color = $this->assertColor($args[0]);
$hsl = $this->toHSL($color[1], $color[2], $color[3]);
- return new Node\Number($hsl[3], '%');
+ return new Number($hsl[3], '%');
}
protected function adjustHsl($color, $idx, $amount)
protected function libAdjustHue($args)
{
$color = $this->assertColor($args[0]);
- $degrees = $this->assertNumber($args[1]);
+ $degrees = $this->assertNumber($args[1])->getDimension();
return $this->adjustHsl($color, 1, $degrees);
}
{
$value = $args[0];
- if ($value[0] === Type::T_NUMBER) {
+ if ($value instanceof Number) {
return null;
}
{
$value = $args[0];
- if ($value[0] === Type::T_NUMBER) {
+ if ($value instanceof Number) {
return null;
}
$weight = $this->coercePercent($weight);
}
- if ($value[0] === Type::T_NUMBER) {
+ if ($value instanceof Number) {
return null;
}
$inverted[3] = 255 - $inverted[3];
if ($weight < 1) {
- return $this->libMix([$inverted, $color, [Type::T_NUMBER, $weight]]);
+ return $this->libMix([$inverted, $color, new Number($weight, '')]);
}
return $inverted;
$value = $args[0];
if ($value[0] === Type::T_STRING && ! empty($value[1])) {
+ $value[1] = '"';
return $value;
}
protected static $libPercentage = ['number'];
protected function libPercentage($args)
{
- return new Node\Number($this->coercePercent($args[0]) * 100, '%');
+ $num = $this->assertNumber($args[0], 'number');
+ $num->assertNoUnits('number');
+
+ return new Number($num->getDimension() * 100, '%');
}
protected static $libRound = ['number'];
protected function libRound($args)
{
- $num = $args[0];
+ $num = $this->assertNumber($args[0], 'number');
- return new Node\Number(round($num[1]), $num[2]);
+ return new Number(round($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits());
}
protected static $libFloor = ['number'];
protected function libFloor($args)
{
- $num = $args[0];
+ $num = $this->assertNumber($args[0], 'number');
- return new Node\Number(floor($num[1]), $num[2]);
+ return new Number(floor($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits());
}
protected static $libCeil = ['number'];
protected function libCeil($args)
{
- $num = $args[0];
+ $num = $this->assertNumber($args[0], 'number');
- return new Node\Number(ceil($num[1]), $num[2]);
+ return new Number(ceil($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits());
}
protected static $libAbs = ['number'];
protected function libAbs($args)
{
- $num = $args[0];
+ $num = $this->assertNumber($args[0], 'number');
- return new Node\Number(abs($num[1]), $num[2]);
+ return new Number(abs($num->getDimension()), $num->getNumeratorUnits(), $num->getDenominatorUnits());
}
protected function libMin($args)
{
- $numbers = $this->getNormalizedNumbers($args);
- $minOriginal = null;
- $minNormalized = null;
+ /**
+ * @var Number|null
+ */
+ $min = null;
- foreach ($numbers as $key => $pair) {
- list($original, $normalized) = $pair;
+ foreach ($args as $arg) {
+ $number = $this->assertNumber($arg);
- if (\is_null($normalized) || \is_null($minNormalized)) {
- if (\is_null($minOriginal) || $original[1] <= $minOriginal[1]) {
- $minOriginal = $original;
- $minNormalized = $normalized;
- }
- } elseif ($normalized[1] <= $minNormalized[1]) {
- $minOriginal = $original;
- $minNormalized = $normalized;
+ if (\is_null($min) || $min->greaterThan($number)) {
+ $min = $number;
}
}
- return $minOriginal;
- }
-
- protected function libMax($args)
- {
- $numbers = $this->getNormalizedNumbers($args);
- $maxOriginal = null;
- $maxNormalized = null;
-
- foreach ($numbers as $key => $pair) {
- list($original, $normalized) = $pair;
-
- if (\is_null($normalized) || \is_null($maxNormalized)) {
- if (\is_null($maxOriginal) || $original[1] >= $maxOriginal[1]) {
- $maxOriginal = $original;
- $maxNormalized = $normalized;
- }
- } elseif ($normalized[1] >= $maxNormalized[1]) {
- $maxOriginal = $original;
- $maxNormalized = $normalized;
- }
+ if (!\is_null($min)) {
+ return $min;
}
- return $maxOriginal;
+ throw $this->error('At least one argument must be passed.');
}
- /**
- * Helper to normalize args containing numbers
- *
- * @param array $args
- *
- * @return array
- */
- protected function getNormalizedNumbers($args)
+ protected function libMax($args)
{
- $unit = null;
- $originalUnit = null;
- $numbers = [];
-
- foreach ($args as $key => $item) {
- $this->assertNumber($item);
+ /**
+ * @var Number|null
+ */
+ $max = null;
- $number = $item->normalize();
+ foreach ($args as $arg) {
+ $number = $this->assertNumber($arg);
- if (empty($unit)) {
- $unit = $number[2];
- $originalUnit = $item->unitStr();
- } elseif ($number[1] && $unit !== $number[2] && ! empty($number[2])) {
- throw $this->error('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr());
+ if (\is_null($max) || $max->lessThan($number)) {
+ $max = $number;
}
+ }
- $numbers[$key] = [$args[$key], empty($number[2]) ? null : $number];
+ if (!\is_null($max)) {
+ return $max;
}
- return $numbers;
+ throw $this->error('At least one argument must be passed.');
}
protected static $libLength = ['list'];
protected function libNth($args)
{
$list = $this->coerceList($args[0], ',', false);
- $n = $this->assertNumber($args[1]);
+ $n = $this->assertNumber($args[1])->getDimension();
if ($n > 0) {
$n--;
protected function libSetNth($args)
{
$list = $this->coerceList($args[0]);
- $n = $this->assertNumber($args[1]);
+ $n = $this->assertNumber($args[1])->getDimension();
if ($n > 0) {
$n--;
{
$num = $args[0];
- if ($num[0] === Type::T_NUMBER) {
+ if ($num instanceof Number) {
return [Type::T_STRING, '"', [$num->unitStr()]];
}
{
$value = $args[0];
- return $value[0] === Type::T_NUMBER && $value->unitless();
+ return $value instanceof Number && $value->unitless();
}
protected static $libComparable = [
list($number1, $number2) = $args;
if (
- ! isset($number1[0]) || $number1[0] !== Type::T_NUMBER ||
- ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER
+ ! $number1 instanceof Number ||
+ ! $number2 instanceof Number
) {
throw $this->error('Invalid argument(s) for "comparable"');
}
- $number1 = $number1->normalize();
- $number2 = $number2->normalize();
-
- return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless();
+ return $number1->isComparableTo($number2);
}
protected static $libStrIndex = ['string', 'substring'];
$result = strpos($stringContent, $substringContent);
}
- return $result === false ? static::$null : new Node\Number($result + 1, '');
+ return $result === false ? static::$null : new Number($result + 1, '');
}
protected static $libStrInsert = ['string', 'insert', 'index'];
$string = $this->assertString($args[0], 'string');
$stringContent = $this->compileStringContent($string);
- return new Node\Number(Util::mbStrlen($stringContent), '');
+ return new Number(Util::mbStrlen($stringContent), '');
}
protected static $libStrSlice = ['string', 'start-at', 'end-at:-1'];
protected function libRandom($args)
{
if (isset($args[0]) & $args[0] !== static::$null) {
- $n = $this->assertNumber($args[0]);
+ $n = $this->assertNumber($args[0])->getDimension();
if ($n < 1) {
throw $this->error("\$limit must be greater than or equal to 1");
}
- if (round($n - \intval($n), Node\Number::PRECISION) > 0) {
+ if (round($n - \intval($n), Number::PRECISION) > 0) {
throw $this->error("Expected \$limit to be an integer but got $n for `random`");
}
- return new Node\Number(mt_rand(1, \intval($n)), '');
+ return new Number(mt_rand(1, \intval($n)), '');
}
$max = mt_getrandmax();
- return new Node\Number(mt_rand(0, $max - 1) / $max, '');
+ return new Number(mt_rand(0, $max - 1) / $max, '');
}
protected function libUniqueId()
$parsedSelector = [];
- if ($parser->parseSelector($arg, $parsedSelector)) {
+ if ($parser->parseSelector($arg, $parsedSelector, true)) {
$selector = $this->evalSelectors($parsedSelector);
$gluedSelector = $this->glueFunctionSelectors($selector);
namespace ScssPhp\ScssPhp\Node;
use ScssPhp\ScssPhp\Compiler;
+use ScssPhp\ScssPhp\Exception\SassScriptException;
use ScssPhp\ScssPhp\Node;
use ScssPhp\ScssPhp\Type;
/**
* @var integer|float
*/
- public $dimension;
+ private $dimension;
- /**
- * @var array
- */
- public $units;
+ private $numeratorUnits;
+ private $denominatorUnits;
/**
* Initialize number
*
- * @param mixed $dimension
- * @param mixed $initialUnit
+ * @param integer|float $dimension
+ * @param string[]|string $numeratorUnits
+ * @param string[] $denominatorUnits
*/
- public function __construct($dimension, $initialUnit)
+ public function __construct($dimension, $numeratorUnits, array $denominatorUnits = [])
{
- $this->type = Type::T_NUMBER;
+ if (is_string($numeratorUnits)) {
+ $numeratorUnits = $numeratorUnits ? [$numeratorUnits] : [];
+ } elseif (isset($numeratorUnits['numerator_units'], $numeratorUnits['denominator_units'])) {
+ // TODO get rid of this once `$number[2]` is not used anymore
+ $denominatorUnits = $numeratorUnits['denominator_units'];
+ $numeratorUnits = $numeratorUnits['numerator_units'];
+ }
+
$this->dimension = $dimension;
- $this->units = \is_array($initialUnit)
- ? $initialUnit
- : ($initialUnit ? [$initialUnit => 1]
- : []);
+ $this->numeratorUnits = $numeratorUnits;
+ $this->denominatorUnits = $denominatorUnits;
}
/**
- * Coerce number to target units
- *
- * @param array $units
- *
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return float|int
*/
- public function coerce($units)
+ public function getDimension()
{
- if ($this->unitless()) {
- return new Number($this->dimension, $units);
- }
-
- $dimension = $this->dimension;
-
- if (\count($units)) {
- $baseUnit = array_keys($units);
- $baseUnit = reset($baseUnit);
- $baseUnit = $this->findBaseUnit($baseUnit);
- if ($baseUnit && isset(static::$unitTable[$baseUnit])) {
- foreach (static::$unitTable[$baseUnit] as $unit => $conv) {
- $from = isset($this->units[$unit]) ? $this->units[$unit] : 0;
- $to = isset($units[$unit]) ? $units[$unit] : 0;
- $factor = pow($conv, $from - $to);
- $dimension /= $factor;
- }
- }
- }
-
- return new Number($dimension, $units);
+ return $this->dimension;
}
/**
- * Normalize number
- *
- * @return \ScssPhp\ScssPhp\Node\Number
+ * @return string[]
*/
- public function normalize()
+ public function getNumeratorUnits()
{
- $dimension = $this->dimension;
- $units = [];
-
- $this->normalizeUnits($dimension, $units);
+ return $this->numeratorUnits;
+ }
- return new Number($dimension, $units);
+ /**
+ * @return string[]
+ */
+ public function getDenominatorUnits()
+ {
+ return $this->denominatorUnits;
}
/**
return $this->sourceIndex;
case 0:
- return $this->type;
+ return Type::T_NUMBER;
case 1:
return $this->dimension;
case 2:
- return $this->units;
+ return array('numerator_units' => $this->numeratorUnits, 'denominator_units' => $this->denominatorUnits);
}
}
*/
public function offsetSet($offset, $value)
{
- if ($offset === 1) {
- $this->dimension = $value;
- } elseif ($offset === 2) {
- $this->units = $value;
- } elseif ($offset == -1) {
- $this->sourceIndex = $value;
- } elseif ($offset == -2) {
- $this->sourceLine = $value;
- } elseif ($offset == -3) {
- $this->sourceColumn = $value;
- }
+ throw new \BadMethodCallException('Number is immutable');
}
/**
*/
public function offsetUnset($offset)
{
- if ($offset === 1) {
- $this->dimension = null;
- } elseif ($offset === 2) {
- $this->units = null;
- } elseif ($offset === -1) {
- $this->sourceIndex = null;
- } elseif ($offset === -2) {
- $this->sourceLine = null;
- } elseif ($offset === -3) {
- $this->sourceColumn = null;
- }
+ throw new \BadMethodCallException('Number is immutable');
}
/**
*/
public function unitless()
{
- return ! array_sum($this->units);
+ return \count($this->numeratorUnits) === 0 && \count($this->denominatorUnits) === 0;
}
/**
- * Test if a number can be normalized in a base unit
- * ie if its units are homogeneous
+ * Checks whether the number has exactly this unit
*
- * @return boolean
+ * @param string $unit
+ *
+ * @return bool
+ */
+ public function hasUnit($unit)
+ {
+ return \count($this->numeratorUnits) === 1 && \count($this->denominatorUnits) === 0 && $this->numeratorUnits[0] === $unit;
+ }
+
+ /**
+ * Returns unit(s) as the product of numerator units divided by the product of denominator units
+ *
+ * @return string
*/
- public function isNormalizable()
+ public function unitStr()
+ {
+ if ($this->unitless()) {
+ return '';
+ }
+
+ return self::getUnitString($this->numeratorUnits, $this->denominatorUnits);
+ }
+
+ public function assertNoUnits($varName = null)
{
if ($this->unitless()) {
+ return;
+ }
+
+ $varDisplay = !\is_null($varName) ? "\${$varName}: " : '';
+
+ throw new SassScriptException(sprintf('%sExpected %s to have no units', $varDisplay, $this));
+ }
+
+ public function assertSameUnitOrUnitless(Number $other)
+ {
+ if ($other->unitless()) {
+ return;
+ }
+
+ if ($this->numeratorUnits === $other->numeratorUnits && $this->denominatorUnits === $other->denominatorUnits) {
+ return;
+ }
+
+ throw new SassScriptException(sprintf(
+ 'Incompatible units %s and %s.',
+ self::getUnitString($this->numeratorUnits, $this->denominatorUnits),
+ self::getUnitString($other->numeratorUnits, $other->denominatorUnits)
+ ));
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return bool
+ */
+ public function isComparableTo(Number $other)
+ {
+ if ($this->unitless() || $other->unitless()) {
+ return true;
+ }
+
+ try {
+ $this->greaterThan($other);
+ return true;
+ } catch (SassScriptException $e) {
return false;
}
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return bool
+ */
+ public function lessThan(Number $other)
+ {
+ return $this->coerceUnits($other, function ($num1, $num2) {
+ return $num1 < $num2;
+ });
+ }
- $baseUnit = null;
+ /**
+ * @param Number $other
+ *
+ * @return bool
+ */
+ public function lessThanOrEqual(Number $other)
+ {
+ return $this->coerceUnits($other, function ($num1, $num2) {
+ return $num1 <= $num2;
+ });
+ }
- foreach ($this->units as $unit => $exp) {
- $b = $this->findBaseUnit($unit);
+ /**
+ * @param Number $other
+ *
+ * @return bool
+ */
+ public function greaterThan(Number $other)
+ {
+ return $this->coerceUnits($other, function ($num1, $num2) {
+ return $num1 > $num2;
+ });
+ }
- if (\is_null($baseUnit)) {
- $baseUnit = $b;
+ /**
+ * @param Number $other
+ *
+ * @return bool
+ */
+ public function greaterThanOrEqual(Number $other)
+ {
+ return $this->coerceUnits($other, function ($num1, $num2) {
+ return $num1 >= $num2;
+ });
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return Number
+ */
+ public function plus(Number $other)
+ {
+ return $this->coerceNumber($other, function ($num1, $num2) {
+ return $num1 + $num2;
+ });
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return Number
+ */
+ public function minus(Number $other)
+ {
+ return $this->coerceNumber($other, function ($num1, $num2) {
+ return $num1 - $num2;
+ });
+ }
+
+ /**
+ * @return Number
+ */
+ public function unaryMinus()
+ {
+ return new Number(-$this->dimension, $this->numeratorUnits, $this->denominatorUnits);
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return Number
+ */
+ public function modulo(Number $other)
+ {
+ return $this->coerceNumber($other, function ($num1, $num2) {
+ if ($num2 == 0) {
+ return NAN;
}
- if (\is_null($b) or $b !== $baseUnit) {
- return false;
+ return $num1 % $num2;
+ });
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return Number
+ */
+ public function times(Number $other)
+ {
+ return $this->multiplyUnits($this->dimension * $other->dimension, $this->numeratorUnits, $this->denominatorUnits, $other->numeratorUnits, $other->denominatorUnits);
+ }
+
+ /**
+ * @param Number $other
+ *
+ * @return Number
+ */
+ public function dividedBy(Number $other)
+ {
+ if ($other->dimension == 0) {
+ if ($this->dimension == 0) {
+ $value = NAN;
+ } elseif ($this->dimension > 0) {
+ $value = INF;
+ } else {
+ $value = -INF;
}
+ } else {
+ $value = $this->dimension / $other->dimension;
}
- return $baseUnit;
+ return $this->multiplyUnits($value, $this->numeratorUnits, $this->denominatorUnits, $other->denominatorUnits, $other->numeratorUnits);
}
/**
- * Returns unit(s) as the product of numerator units divided by the product of denominator units
+ * @param Number $other
*
- * @return string
+ * @return bool
*/
- public function unitStr()
+ public function equals(Number $other)
{
- $numerators = [];
- $denominators = [];
+ // Unitless numbers are convertable to unit numbers, but not equal, so we special-case unitless here.
+ if ($this->unitless() !== $other->unitless()) {
+ return false;
+ }
- foreach ($this->units as $unit => $unitSize) {
- if ($unitSize > 0) {
- $numerators = array_pad($numerators, \count($numerators) + $unitSize, $unit);
- continue;
- }
+ // In Sass, neither NaN nor Infinity are equal to themselves, while PHP defines INF==INF
+ if (is_nan($this->dimension) || is_nan($other->dimension) || !is_finite($this->dimension) || !is_finite($other->dimension)) {
+ return false;
+ }
- if ($unitSize < 0) {
- $denominators = array_pad($denominators, \count($denominators) - $unitSize, $unit);
- continue;
- }
+ if ($this->unitless()) {
+ return round($this->dimension, self::PRECISION) == round($other->dimension, self::PRECISION);
}
- return implode('*', $numerators) . (\count($denominators) ? '/' . implode('*', $denominators) : '');
+ try {
+ return $this->coerceUnits($other, function ($num1, $num2) {
+ return round($num1,self::PRECISION) == round($num2, self::PRECISION);
+ });
+ } catch (SassScriptException $e) {
+ return false;
+ }
}
/**
{
$dimension = round($this->dimension, self::PRECISION);
- $units = array_filter($this->units, function ($unitSize) {
- return $unitSize;
- });
-
- if (\count($units) > 1 && array_sum($units) === 0) {
- $dimension = $this->dimension;
- $units = [];
-
- $this->normalizeUnits($dimension, $units);
+ if (is_nan($dimension)) {
+ return 'NaN';
+ }
- $dimension = round($dimension, self::PRECISION);
- $units = array_filter($units, function ($unitSize) {
- return $unitSize;
- });
+ if ($dimension === INF) {
+ return 'Infinity';
}
- $unitSize = array_sum($units);
+ if ($dimension === -INF) {
+ return '-Infinity';
+ }
- if ($compiler && ($unitSize > 1 || $unitSize < 0 || \count($units) > 1)) {
- $this->units = $units;
+ if ($compiler) {
$unit = $this->unitStr();
+ } elseif (isset($this->numeratorUnits[0])) {
+ $unit = $this->numeratorUnits[0];
} else {
- reset($units);
- $unit = key($units);
+ $unit = '';
}
$dimension = number_format($dimension, self::PRECISION, '.', '');
- return (self::PRECISION ? rtrim(rtrim($dimension, '0'), '.') : $dimension) . $unit;
+ return rtrim(rtrim($dimension, '0'), '.') . $unit;
}
/**
}
/**
- * Normalize units
+ * @param Number $other
+ * @param callable $operation
+ *
+ * @return Number
+ *
+ * @phpstan-param callable(int|float, int|float): int|float $operation
+ */
+ private function coerceNumber(Number $other, $operation)
+ {
+ $result = $this->coerceUnits($other, $operation);
+
+ if (!$this->unitless()) {
+ return new Number($result, $this->numeratorUnits, $this->denominatorUnits);
+ }
+
+ return new Number($result, $other->numeratorUnits, $other->denominatorUnits);
+ }
+
+ /**
+ * @param Number $other
+ * @param callable $operation
+ *
+ * @return mixed
+ *
+ * @phpstan-template T
+ * @phpstan-param callable(int|float, int|float): T $operation
+ * @phpstan-return T
+ */
+ private function coerceUnits(Number $other, $operation)
+ {
+ if (!$this->unitless()) {
+ $num1 = $this->dimension;
+ $num2 = $other->valueInUnits($this->numeratorUnits, $this->denominatorUnits);
+ } else {
+ $num1 = $this->valueInUnits($other->numeratorUnits, $other->denominatorUnits);
+ $num2 = $other->dimension;
+ }
+
+ return \call_user_func($operation, $num1, $num2);
+ }
+
+ /**
+ * @param string[] $numeratorUnits
+ * @param string[] $denominatorUnits
+ *
+ * @return int|float
+ */
+ private function valueInUnits(array $numeratorUnits, array $denominatorUnits)
+ {
+ if (
+ $this->unitless()
+ || (\count($numeratorUnits) === 0 && \count($denominatorUnits) === 0)
+ || ($this->numeratorUnits === $numeratorUnits && $this->denominatorUnits === $denominatorUnits)
+ ) {
+ return $this->dimension;
+ }
+
+ $value = $this->dimension;
+ $oldNumerators = $this->numeratorUnits;
+
+ foreach ($numeratorUnits as $newNumerator) {
+ foreach ($oldNumerators as $key => $oldNumerator) {
+ $conversionFactor = self::getConversionFactor($newNumerator, $oldNumerator);
+
+ if (\is_null($conversionFactor)) {
+ continue;
+ }
+
+ $value *= $conversionFactor;
+ unset($oldNumerators[$key]);
+ continue 2;
+ }
+
+ throw new SassScriptException(sprintf(
+ 'Incompatible units %s and %s.',
+ self::getUnitString($this->numeratorUnits, $this->denominatorUnits),
+ self::getUnitString($numeratorUnits, $denominatorUnits)
+ ));
+ }
+
+ $oldDenominators = $this->denominatorUnits;
+
+ foreach ($denominatorUnits as $newDenominator) {
+ foreach ($oldDenominators as $key => $oldDenominator) {
+ $conversionFactor = self::getConversionFactor($newDenominator, $oldDenominator);
+
+ if (\is_null($conversionFactor)) {
+ continue;
+ }
+
+ $value /= $conversionFactor;
+ unset($oldDenominators[$key]);
+ continue 2;
+ }
+
+ throw new SassScriptException(sprintf(
+ 'Incompatible units %s and %s.',
+ self::getUnitString($this->numeratorUnits, $this->denominatorUnits),
+ self::getUnitString($numeratorUnits, $denominatorUnits)
+ ));
+ }
+
+ if (\count($oldNumerators) || \count($oldDenominators)) {
+ throw new SassScriptException(sprintf(
+ 'Incompatible units %s and %s.',
+ self::getUnitString($this->numeratorUnits, $this->denominatorUnits),
+ self::getUnitString($numeratorUnits, $denominatorUnits)
+ ));
+ }
+
+ return $value;
+ }
+
+ /**
+ * @param int|float $value
+ * @param string[] $numerators1
+ * @param string[] $denominators1
+ * @param string[] $numerators2
+ * @param string[] $denominators2
*
- * @param integer|float $dimension
- * @param array $units
- * @param string $baseUnit
+ * @return Number
*/
- private function normalizeUnits(&$dimension, &$units, $baseUnit = null)
+ private function multiplyUnits($value, array $numerators1, array $denominators1, array $numerators2, array $denominators2)
{
- $dimension = $this->dimension;
- $units = [];
+ $newNumerators = array();
+
+ foreach ($numerators1 as $numerator) {
+ foreach ($denominators2 as $key => $denominator) {
+ $conversionFactor = self::getConversionFactor($numerator, $denominator);
- foreach ($this->units as $unit => $exp) {
- if (! $baseUnit) {
- $baseUnit = $this->findBaseUnit($unit);
+ if (\is_null($conversionFactor)) {
+ continue;
+ }
+
+ $value /= $conversionFactor;
+ unset($denominators2[$key]);
+ continue 2;
}
- if ($baseUnit && isset(static::$unitTable[$baseUnit][$unit])) {
- $factor = pow(static::$unitTable[$baseUnit][$unit], $exp);
+ $newNumerators[] = $numerator;
+ }
+
+ foreach ($numerators2 as $numerator) {
+ foreach ($denominators1 as $key => $denominator) {
+ $conversionFactor = self::getConversionFactor($numerator, $denominator);
- $unit = $baseUnit;
- $dimension /= $factor;
+ if (\is_null($conversionFactor)) {
+ continue;
+ }
+
+ $value /= $conversionFactor;
+ unset($denominators1[$key]);
+ continue 2;
}
- $units[$unit] = $exp + (isset($units[$unit]) ? $units[$unit] : 0);
+ $newNumerators[] = $numerator;
}
+
+ $newDenominators = array_values(array_merge($denominators1, $denominators2));
+
+ return new Number($value, $newNumerators, $newDenominators);
}
/**
- * Find the base unit family for a given unit
+ * Returns the number of [unit1]s per [unit2].
*
- * @param string $unit
+ * Equivalently, `1unit1 * conversionFactor(unit1, unit2) = 1unit2`.
+ *
+ * @param string $unit1
+ * @param string $unit2
*
- * @return string|null
+ * @return float|int|null
*/
- private function findBaseUnit($unit)
+ private static function getConversionFactor($unit1, $unit2)
{
- foreach (static::$unitTable as $baseUnit => $unitVariants) {
- if (isset($unitVariants[$unit])) {
- return $baseUnit;
+ if ($unit1 === $unit2) {
+ return 1;
+ }
+
+ foreach (static::$unitTable as $unitVariants) {
+ if (isset($unitVariants[$unit1]) && isset($unitVariants[$unit2])) {
+ return $unitVariants[$unit1] / $unitVariants[$unit2];
}
}
return null;
}
+
+ /**
+ * Returns unit(s) as the product of numerator units divided by the product of denominator units
+ *
+ * @param string[] $numerators
+ * @param string[] $denominators
+ *
+ * @return string
+ */
+ private static function getUnitString(array $numerators, array $denominators)
+ {
+ if (!\count($numerators)) {
+ if (\count($denominators) === 0) {
+ return 'no units';
+ }
+
+ if (\count($denominators) === 1) {
+ return $denominators[0] . '^-1';
+ }
+
+ return '(' . implode('*', $denominators) . ')^-1';
+ }
+
+ return implode('*', $numerators) . (\count($denominators) ? '/' . implode('*', $denominators) : '');
+ }
}
'and' => 2,
'==' => 3,
'!=' => 3,
- '<=>' => 3,
'<=' => 4,
'>=' => 4,
'<' => 4,
$this->cssOnly = $cssOnly;
if (empty(static::$operatorPattern)) {
- static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)';
+ static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=?|and|or)';
$commentSingle = '\/\/';
$commentMultiLeft = '\/\*';
* @param string $msg
*
* @throws \ScssPhp\ScssPhp\Exception\ParserException
+ *
+ * @deprecated use "parseError" and throw the exception in the caller instead.
*/
public function throwParseError($msg = 'parse error')
+ {
+ @trigger_error(
+ 'The method "throwParseError" is deprecated. Use "parseError" and throw the exception in the caller instead',
+ E_USER_DEPRECATED
+ );
+
+ throw $this->parseError($msg);
+ }
+
+ /**
+ * Creates a parser error
+ *
+ * @api
+ *
+ * @param string $msg
+ *
+ * @return ParserException
+ */
+ public function parseError($msg = 'parse error')
{
list($line, $column) = $this->getSourcePosition($this->count);
$e = new ParserException("$msg: failed at `$m[1]` $loc");
$e->setSourcePosition([$this->sourceName, $line, $column]);
- throw $e;
+ return $e;
}
$this->restoreEncoding();
$e = new ParserException("$msg: $loc");
$e->setSourcePosition([$this->sourceName, $line, $column]);
- throw $e;
+ return $e;
}
/**
}
if ($this->count !== \strlen($this->buffer)) {
- $this->throwParseError();
+ throw $this->parseError();
}
if (! empty($this->env->parent)) {
- $this->throwParseError('unclosed block');
+ throw $this->parseError('unclosed block');
}
if ($this->charset) {
$this->buffer = (string) $buffer;
$this->saveEncoding();
+ $this->extractLineNumbers($this->buffer);
$list = $this->valueList($out);
*
* @param string $buffer
* @param string|array $out
+ * @param bool $shouldValidate
*
* @return boolean
*/
- public function parseSelector($buffer, &$out)
+ public function parseSelector($buffer, &$out, $shouldValidate = true)
{
$this->count = 0;
$this->env = null;
$this->buffer = (string) $buffer;
$this->saveEncoding();
+ $this->extractLineNumbers($this->buffer);
$selector = $this->selectors($out);
$this->restoreEncoding();
+ if ($shouldValidate && $this->count !== strlen($buffer)) {
+ throw $this->parseError("`" . substr($buffer, $this->count) . "` is not a valid Selector in `$buffer`");
+ }
+
return $selector;
}
$this->buffer = (string) $buffer;
$this->saveEncoding();
+ $this->extractLineNumbers($this->buffer);
$isMediaQuery = $this->mediaQueryList($out);
$this->end()
) {
if ($this->cssOnly) {
- $this->assertPlainCssValid($importPath, $s);
+ $this->assertPlainCssValid([Type::T_IMPORT, $importPath], $s);
$this->append([Type::T_COMMENT, rtrim(substr($this->buffer, $s, $this->count - $s))]);
return true;
}
$this->end()
) {
if ($this->cssOnly) {
- $this->assertPlainCssValid($importPath, $s);
+ $this->assertPlainCssValid([Type::T_IMPORT, $importPath], $s);
$this->append([Type::T_COMMENT, rtrim(substr($this->buffer, $s, $this->count - $s))]);
return true;
}
$this->seek($s);
- if (
- $this->literal('@break', 6) &&
- $this->end()
- ) {
- ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
-
- $this->append([Type::T_BREAK], $s);
-
- return true;
- }
-
- $this->seek($s);
-
- if (
- $this->literal('@continue', 9) &&
- $this->end()
- ) {
- ! $this->cssOnly || $this->assertPlainCssValid(false, $s);
-
- $this->append([Type::T_CONTINUE], $s);
-
- return true;
- }
-
- $this->seek($s);
-
if (
$this->literal('@return', 7) &&
($this->valueList($retVal) || true) &&
$else = $this->pushSpecialBlock(Type::T_ELSE, $s);
} elseif (
$this->literal('if', 2) &&
- $this->valueList($cond) &&
- $this->matchChar('{', false)
+ $this->functionCallArgumentsList($cond, false, '{', false)
) {
$else = $this->pushSpecialBlock(Type::T_ELSEIF, $s);
$else->cond = $cond;
! \in_array($this->env->type, [Type::T_DIRECTIVE, Type::T_MEDIA])
) {
$plain = \trim(\substr($this->buffer, $s, $this->count - $s));
- $this->throwParseError(
+ throw $this->parseError(
"Unknown directive `{$plain}` not allowed in `" . $this->env->type . "` block"
);
}
if ($this->valueList($value)) {
if (empty($this->env->parent)) {
- $this->throwParseError('expected "{"');
+ throw $this->parseError('expected "{"');
}
$this->append([Type::T_ASSIGN, $name, $value], $s);
$block = $this->env;
if (empty($block->parent)) {
- $this->throwParseError('unexpected }');
+ throw $this->parseError('unexpected }');
}
if ($block->type == Type::T_AT_ROOT) {
if ($type) {
$message .= " ($type)";
}
- $this->throwParseError($message);
+ throw $this->parseError($message);
}
return $parsed;
*/
protected function isPlainCssValidElement($parsed, $allowExpression = false)
{
+ // keep string as is
+ if (is_string($parsed)) {
+ return $parsed;
+ }
+
if (
\in_array($parsed[0], [Type::T_FUNCTION, Type::T_FUNCTION_CALL]) &&
!\in_array($parsed[1], [
case Type::T_KEYWORD:
case Type::T_NULL:
case Type::T_NUMBER:
+ case Type::T_MEDIA:
return $parsed;
case Type::T_COMMENT:
return $parsed;
+ case Type::T_IMPORT:
+ if ($parsed[1][0] === Type::T_LIST) {
+ return false;
+ }
+ $parsed[1] = $this->isPlainCssValidElement($parsed[1]);
+ if ($parsed[1] === false) {
+ return false;
+ }
+ return $parsed;
+
case Type::T_STRING:
foreach ($parsed[2] as $k => $substr) {
if (\is_array($substr)) {
}
return $parsed;
+ case Type::T_LIST:
+ if (!empty($parsed['enclosing'])) {
+ return false;
+ }
+ foreach ($parsed[2] as $k => $listElement) {
+ $parsed[2][$k] = $this->isPlainCssValidElement($listElement);
+ if (! $parsed[2][$k]) {
+ return false;
+ }
+ }
+ return $parsed;
+
case Type::T_ASSIGN:
foreach ([1, 2, 3] as $k) {
if (! empty($parsed[$k])) {
$sss = $this->count;
if (! $this->matchChar(')')) {
- $this->throwParseError('... has to be after the final argument');
+ throw $this->parseError('... has to be after the final argument');
}
$arg[2] = true;
$content[] = '#{'; // ignore it
}
} elseif ($m[2] === "\r") {
- $content[] = '\\a';
+ $content[] = chr(10);
// TODO : warning
# DEPRECATION WARNING on line x, column y of zzz:
# Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
} elseif ($this->matchEscapeCharacter($c)) {
$content[] = $c;
} else {
- $this->throwParseError('Unterminated escape sequence');
+ throw $this->parseError('Unterminated escape sequence');
}
} else {
$this->count -= \strlen($delim);
return false;
}
- protected function matchEscapeCharacter(&$out)
+ protected function matchEscapeCharacter(&$out, $inKeywords = false)
{
+ $s = $this->count;
if ($this->match('[a-f0-9]', $m, false)) {
$hex = $m[0];
$value = hexdec($hex);
- if ($value == 0 || ($value >= 0xD800 && $value <= 0xDFFF) || $value >= 0x10FFFF) {
- $out = "\u{FFFD}";
+ if (!$inKeywords && ($value == 0 || ($value >= 0xD800 && $value <= 0xDFFF) || $value >= 0x10FFFF)) {
+ $out = "\xEF\xBF\xBD"; // "\u{FFFD}" but with a syntax supported on PHP 5
+ } elseif ($value < 0x20) {
+ $out = Util::mbChr($value);
} else {
$out = Util::mbChr($value);
}
}
if ($this->match('.', $m, false)) {
+ if ($inKeywords && in_array($m[0], ["'",'"','@','&',' ','\\',':','/','%'])) {
+ $this->seek($s);
+ return false;
+ }
$out = $m[0];
return true;
{
$selector = [];
+ $discardComments = $this->discardComments;
+ $this->discardComments = true;
+
for (;;) {
$s = $this->count;
if ($this->selectorSingle($part, $subSelector)) {
$selector[] = $part;
- $this->match('\s+', $m);
- continue;
- }
-
- if ($this->match('\/[^\/]+\/', $m, true)) {
- $selector[] = [$m[0]];
+ $this->whitespace();
continue;
}
break;
}
+ $this->discardComments = $discardComments;
+
if (! $selector) {
return false;
}
$this->seek($ss);
}
} elseif (
- $this->matchChar('(') &&
+ $this->matchChar('(', true) &&
($this->openString(')', $str, '(') || true) &&
$this->matchChar(')')
) {
*/
protected function keyword(&$word, $eatWhitespace = null)
{
+ $s = $this->count;
$match = $this->match(
$this->utf8
? '(([\pL\w\x{00A0}-\x{10FFFF}_\-\*!"\']|[\\\\].)([\pL\w\x{00A0}-\x{10FFFF}\-_"\']|[\\\\].)*)'
: '(([\w_\-\*!"\']|[\\\\].)([\w\-_"\']|[\\\\].)*)',
$m,
- $eatWhitespace
+ false
);
if ($match) {
$word = $m[1];
+ // handling of escaping in keyword : get the escaped char
+ if (strpos($word, '\\') !== false) {
+ $send = $this->count;
+ $escapedWord = [];
+ $this->seek($s);
+ $previousEscape = false;
+ while ($this->count < $send) {
+ $char = $this->buffer[$this->count];
+ $this->count++;
+ if (
+ $this->count < $send
+ && $char === '\\'
+ && !$previousEscape
+ && $this->matchEscapeCharacter($out, true)
+ ) {
+ $escapedWord[] = $out;
+ } else {
+ if ($previousEscape) {
+ $previousEscape = false;
+ } elseif ($char === '\\') {
+ $previousEscape = true;
+ }
+ $escapedWord[] = $char;
+ }
+ }
+
+ $word = implode('', $escapedWord);
+ }
+
+ if (is_null($eatWhitespace) ? $this->eatWhiteDefault : $eatWhitespace) {
+ $this->whitespace();
+ }
+
return true;
}
*/
public static function mbChr($code)
{
- // Use the native implementation if available.
- if (\function_exists('mb_chr')) {
+ // Use the native implementation if available, but not on PHP 7.2 as mb_chr(0) is buggy there
+ if (\PHP_VERSION_ID > 70300 && \function_exists('mb_chr')) {
return mb_chr($code, 'UTF-8');
}
*/
class Version
{
- const VERSION = '1.2.1';
+ const VERSION = '1.3';
}