From 5cf43544a43c3146d24f20b078fd18102868f8a6 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Tue, 3 Nov 2020 19:45:45 +0100 Subject: [PATCH] Upgrade scssphp/scssphp to v1.3 --- .../install/files/lib/system/api/bin/pscss | 15 +- .../files/lib/system/api/bin/pscss.bat | 4 + .../files/lib/system/api/composer.lock | 18 +- .../lib/system/api/composer/ClassLoader.php | 4 +- .../system/api/composer/InstalledVersions.php | 367 ++++ .../system/api/composer/autoload_classmap.php | 1 + .../lib/system/api/composer/autoload_real.php | 4 +- .../system/api/composer/autoload_static.php | 1 + .../lib/system/api/composer/installed.json | 1945 +++++++++-------- .../lib/system/api/composer/installed.php | 182 ++ .../system/api/composer/platform_check.php | 26 + .../lib/system/api/scssphp/scssphp/README.md | 2 +- .../lib/system/api/scssphp/scssphp/bin/pscss | 20 +- .../system/api/scssphp/scssphp/composer.json | 14 +- .../system/api/scssphp/scssphp/scss.inc.php | 1 + .../api/scssphp/scssphp/src/Compiler.php | 780 ++++--- .../api/scssphp/scssphp/src/Node/Number.php | 585 +++-- .../system/api/scssphp/scssphp/src/Parser.php | 180 +- .../system/api/scssphp/scssphp/src/Util.php | 4 +- .../api/scssphp/scssphp/src/Version.php | 2 +- 20 files changed, 2545 insertions(+), 1610 deletions(-) create mode 100644 wcfsetup/install/files/lib/system/api/bin/pscss.bat create mode 100644 wcfsetup/install/files/lib/system/api/composer/InstalledVersions.php create mode 100644 wcfsetup/install/files/lib/system/api/composer/installed.php create mode 100644 wcfsetup/install/files/lib/system/api/composer/platform_check.php diff --git a/wcfsetup/install/files/lib/system/api/bin/pscss b/wcfsetup/install/files/lib/system/api/bin/pscss index d08fca2ff6..2879dcb977 120000 --- a/wcfsetup/install/files/lib/system/api/bin/pscss +++ b/wcfsetup/install/files/lib/system/api/bin/pscss @@ -1 +1,14 @@ -../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" "$@" diff --git a/wcfsetup/install/files/lib/system/api/bin/pscss.bat b/wcfsetup/install/files/lib/system/api/bin/pscss.bat new file mode 100644 index 0000000000..1e368dc923 --- /dev/null +++ b/wcfsetup/install/files/lib/system/api/bin/pscss.bat @@ -0,0 +1,4 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/../scssphp/scssphp/bin/pscss +php "%BIN_TARGET%" %* diff --git a/wcfsetup/install/files/lib/system/api/composer.lock b/wcfsetup/install/files/lib/system/api/composer.lock index d5f14700d7..d822884061 100644 --- a/wcfsetup/install/files/lib/system/api/composer.lock +++ b/wcfsetup/install/files/lib/system/api/composer.lock @@ -683,16 +683,16 @@ }, { "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": { @@ -701,7 +701,7 @@ "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", @@ -741,7 +741,11 @@ "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", @@ -946,5 +950,5 @@ "php": "7.2.24", "ext-gd": "0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/wcfsetup/install/files/lib/system/api/composer/ClassLoader.php b/wcfsetup/install/files/lib/system/api/composer/ClassLoader.php index 03b9bb9c40..1a58957d25 100644 --- a/wcfsetup/install/files/lib/system/api/composer/ClassLoader.php +++ b/wcfsetup/install/files/lib/system/api/composer/ClassLoader.php @@ -37,8 +37,8 @@ namespace Composer\Autoload; * * @author Fabien Potencier * @author Jordi Boggiano - * @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 { diff --git a/wcfsetup/install/files/lib/system/api/composer/InstalledVersions.php b/wcfsetup/install/files/lib/system/api/composer/InstalledVersions.php new file mode 100644 index 0000000000..03cf0aee77 --- /dev/null +++ b/wcfsetup/install/files/lib/system/api/composer/InstalledVersions.php @@ -0,0 +1,367 @@ + + 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; +} +} diff --git a/wcfsetup/install/files/lib/system/api/composer/autoload_classmap.php b/wcfsetup/install/files/lib/system/api/composer/autoload_classmap.php index cedefd86a7..33a49c649b 100644 --- a/wcfsetup/install/files/lib/system/api/composer/autoload_classmap.php +++ b/wcfsetup/install/files/lib/system/api/composer/autoload_classmap.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $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', ); diff --git a/wcfsetup/install/files/lib/system/api/composer/autoload_real.php b/wcfsetup/install/files/lib/system/api/composer/autoload_real.php index 9e0a9611c8..d61e79adfc 100644 --- a/wcfsetup/install/files/lib/system/api/composer/autoload_real.php +++ b/wcfsetup/install/files/lib/system/api/composer/autoload_real.php @@ -22,6 +22,8 @@ class ComposerAutoloaderInita1f5f7c74275d47a45049a2936db1d0d 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')); @@ -32,7 +34,7 @@ class ComposerAutoloaderInita1f5f7c74275d47a45049a2936db1d0d $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 { diff --git a/wcfsetup/install/files/lib/system/api/composer/autoload_static.php b/wcfsetup/install/files/lib/system/api/composer/autoload_static.php index 9bca0fb94c..9c790a6ca1 100644 --- a/wcfsetup/install/files/lib/system/api/composer/autoload_static.php +++ b/wcfsetup/install/files/lib/system/api/composer/autoload_static.php @@ -108,6 +108,7 @@ class ComposerStaticInita1f5f7c74275d47a45049a2936db1d0d ); 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', ); diff --git a/wcfsetup/install/files/lib/system/api/composer/installed.json b/wcfsetup/install/files/lib/system/api/composer/installed.json index b09fe39c3e..0b1d5a1565 100644 --- a/wcfsetup/install/files/lib/system/api/composer/installed.json +++ b/wcfsetup/install/files/lib/system/api/composer/installed.json @@ -1,961 +1,984 @@ -[ - { - "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 +} diff --git a/wcfsetup/install/files/lib/system/api/composer/installed.php b/wcfsetup/install/files/lib/system/api/composer/installed.php new file mode 100644 index 0000000000..e234b2eb94 --- /dev/null +++ b/wcfsetup/install/files/lib/system/api/composer/installed.php @@ -0,0 +1,182 @@ + + 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', + ), + ), +); diff --git a/wcfsetup/install/files/lib/system/api/composer/platform_check.php b/wcfsetup/install/files/lib/system/api/composer/platform_check.php new file mode 100644 index 0000000000..1e56f6ecbc --- /dev/null +++ b/wcfsetup/install/files/lib/system/api/composer/platform_check.php @@ -0,0 +1,26 @@ += 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); +} diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/README.md b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/README.md index cd5fce1de2..0b485195e3 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/README.md +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/README.md @@ -1,7 +1,7 @@ # 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. diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/bin/pscss b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/bin/pscss index d48af2f878..b3c8a735d6 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/bin/pscss +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/bin/pscss @@ -28,8 +28,6 @@ $loadPaths = null; $dumpTree = false; $inputFile = null; $changeDir = false; -$debugInfo = false; -$lineNumbers = false; $encoding = false; $sourceMap = false; @@ -71,10 +69,10 @@ Options include: --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 @@ -95,8 +93,9 @@ EOT; 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; } @@ -105,8 +104,9 @@ EOT; 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; } @@ -177,14 +177,6 @@ if ($dumpTree) { $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)); } diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/composer.json b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/composer.json index 7f420edf3d..6ac13125a8 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/composer.json +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/composer.json @@ -31,9 +31,9 @@ "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" }, @@ -57,16 +57,8 @@ } } ], - "minimum-stability": "dev", "bin": ["bin/pscss"], - "archive": { - "exclude": [ - "/Makefile", - "/.gitattributes", - "/.gitignore", - "/.travis.yml", - "/phpunit.xml.dist", - "/tests" - ] + "config": { + "sort-packages": true } } diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/scss.inc.php b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/scss.inc.php index abbd9d21a6..96532aa6f4 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/scss.inc.php +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/scss.inc.php @@ -12,6 +12,7 @@ if (! class_exists('ScssPhp\ScssPhp\Version', false)) { 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'; diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Compiler.php b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Compiler.php index 9eb8dec17a..2840cd5db4 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Compiler.php +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Compiler.php @@ -18,8 +18,10 @@ use ScssPhp\ScssPhp\Cache; 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; @@ -59,12 +61,30 @@ use ScssPhp\ScssPhp\Util; */ 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; @@ -88,7 +108,6 @@ class Compiler '<=' => 'lte', '>=' => 'gte', - '<=>' => 'cmp', ]; /** @@ -102,7 +121,9 @@ class Compiler 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, '', []]; @@ -127,6 +148,9 @@ class Compiler ]; protected $encoding = null; + /** + * @deprecated + */ protected $lineNumberStyle = null; protected $sourceMap = self::SOURCE_MAP_NONE; @@ -259,46 +283,50 @@ class Compiler $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)) { @@ -310,6 +338,12 @@ class Compiler $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; } @@ -796,7 +830,7 @@ class Compiler $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); @@ -1003,30 +1037,6 @@ class Compiler $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); @@ -1403,7 +1413,7 @@ class Compiler $s = reset($s); } - if (\is_object($s) && $s instanceof Node\Number) { + if (\is_object($s) && $s instanceof Number) { return $this->testWithWithout('keyframes', $with, $without); } } @@ -1572,30 +1582,6 @@ class Compiler $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)) { @@ -1689,7 +1675,7 @@ class Compiler $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); } } @@ -1722,8 +1708,8 @@ class Compiler 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 ( @@ -2653,7 +2639,7 @@ class Compiler $divider = $this->reduce($divider, true); } - if (\intval($divider->dimension) && ! \count($divider->units)) { + if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) { $revert = false; } } @@ -2677,7 +2663,7 @@ class Compiler $divider = $this->reduce($divider, true); } - if (\intval($divider->dimension) && ! \count($divider->units)) { + if ($divider instanceof Number && \intval($divider->getDimension()) && $divider->unitless()) { $revert = false; } } @@ -2790,17 +2776,11 @@ class Compiler $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; @@ -2816,13 +2796,7 @@ class Compiler $ret = $this->compileChildren($while->children, $out); if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - return $ret; - } - - if ($ret[1]) { - break; - } + return $ret; } } break; @@ -2833,21 +2807,21 @@ class Compiler $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; @@ -2861,23 +2835,17 @@ class Compiler 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; } } @@ -2887,12 +2855,6 @@ class Compiler 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); @@ -3033,9 +2995,6 @@ class Compiler 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]"); } @@ -3134,7 +3093,7 @@ class Compiler * @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) { @@ -3157,8 +3116,8 @@ class Compiler // 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); @@ -3188,50 +3147,6 @@ class Compiler \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)) { @@ -3241,10 +3156,6 @@ class Compiler } if (isset($out)) { - if ($coerceUnit && $out[0] === Type::T_NUMBER) { - $out = $out->coerce($targetUnit); - } - return $out; } } @@ -3257,13 +3168,13 @@ class Compiler $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(); } } @@ -3494,8 +3405,10 @@ class Compiler /** * 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) { @@ -3614,9 +3527,6 @@ class Compiler 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)]; @@ -3628,74 +3538,66 @@ class Compiler /** * 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); } /** @@ -3858,13 +3760,13 @@ class Compiler * * @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, @@ -3877,14 +3779,14 @@ class Compiler * 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, @@ -3936,70 +3838,81 @@ class Compiler } /** - * 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)); } /** @@ -4016,6 +3929,48 @@ class Compiler 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. * @@ -4039,6 +3994,9 @@ class Compiler 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: @@ -4063,7 +4021,7 @@ class Compiler } if (is_numeric($alpha)) { - $a = new Node\Number($alpha, ''); + $a = new Number($alpha, ''); } else { $a = $alpha; } @@ -4098,19 +4056,25 @@ class Compiler $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]; @@ -4161,10 +4125,26 @@ class Compiler $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); @@ -4258,7 +4238,7 @@ class Compiler break; case Type::T_STRING: - $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)]; + $reduced = [Type::T_STRING, '', [$this->compileStringContent($reduced)]]; break; case Type::T_NULL: @@ -4947,10 +4927,13 @@ class Compiler * @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); } /** @@ -5009,9 +4992,13 @@ class Compiler * @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; } @@ -5815,7 +5802,7 @@ class Compiler * * @param mixed $value * - * @return array|\ScssPhp\ScssPhp\Node\Number + * @return array|Number */ protected function coerceValue($value) { @@ -5832,7 +5819,7 @@ class Compiler } if (is_numeric($value)) { - return new Node\Number($value, ''); + return new Number($value, ''); } if ($value === '') { @@ -6037,7 +6024,7 @@ class Compiler 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); } } @@ -6060,8 +6047,8 @@ class Compiler } /** - * @param integer|\ScssPhp\ScssPhp\Node\Number $value - * @param boolean $isAlpha + * @param integer|Number $value + * @param boolean $isAlpha * * @return integer|mixed */ @@ -6079,36 +6066,27 @@ class Compiler * @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; @@ -6122,18 +6100,7 @@ class Compiler $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; } @@ -6196,12 +6163,12 @@ class Compiler */ 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; @@ -6274,22 +6241,22 @@ class Compiler * * @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; } /** @@ -6307,8 +6274,8 @@ class Compiler 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."); } @@ -6535,8 +6502,25 @@ class Compiler 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); } @@ -6617,7 +6601,7 @@ class Compiler 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); @@ -6632,7 +6616,7 @@ class Compiler 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); } } @@ -6776,7 +6760,7 @@ class Compiler { $value = $args[0]; - if ($value[0] === Type::T_NUMBER) { + if ($value instanceof Number) { return null; } @@ -6840,10 +6824,6 @@ class Compiler $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; @@ -6857,7 +6837,6 @@ class Compiler } $args[$k] = $this->stringifyFncallArgs($arg); - $hue = ''; } if ( @@ -6869,22 +6848,31 @@ class Compiler } } + $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; @@ -6908,7 +6896,7 @@ class Compiler $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']; @@ -6917,7 +6905,7 @@ class Compiler $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']; @@ -6926,7 +6914,7 @@ class Compiler $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) @@ -6946,7 +6934,7 @@ class Compiler 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); } @@ -6974,7 +6962,7 @@ class Compiler { $value = $args[0]; - if ($value[0] === Type::T_NUMBER) { + if ($value instanceof Number) { return null; } @@ -7003,7 +6991,7 @@ class Compiler { $value = $args[0]; - if ($value[0] === Type::T_NUMBER) { + if ($value instanceof Number) { return null; } @@ -7027,7 +7015,7 @@ class Compiler $weight = $this->coercePercent($weight); } - if ($value[0] === Type::T_NUMBER) { + if ($value instanceof Number) { return null; } @@ -7038,7 +7026,7 @@ class Compiler $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; @@ -7100,6 +7088,7 @@ class Compiler $value = $args[0]; if ($value[0] === Type::T_STRING && ! empty($value[1])) { + $value[1] = '"'; return $value; } @@ -7109,116 +7098,86 @@ class Compiler 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']; @@ -7257,7 +7216,7 @@ class Compiler 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--; @@ -7272,7 +7231,7 @@ class Compiler protected function libSetNth($args) { $list = $this->coerceList($args[0]); - $n = $this->assertNumber($args[1]); + $n = $this->assertNumber($args[1])->getDimension(); if ($n > 0) { $n--; @@ -7570,7 +7529,7 @@ class Compiler { $num = $args[0]; - if ($num[0] === Type::T_NUMBER) { + if ($num instanceof Number) { return [Type::T_STRING, '"', [$num->unitStr()]]; } @@ -7582,7 +7541,7 @@ class Compiler { $value = $args[0]; - return $value[0] === Type::T_NUMBER && $value->unitless(); + return $value instanceof Number && $value->unitless(); } protected static $libComparable = [ @@ -7594,16 +7553,13 @@ class Compiler 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']; @@ -7621,7 +7577,7 @@ class Compiler $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']; @@ -7656,7 +7612,7 @@ class Compiler $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']; @@ -7786,21 +7742,21 @@ class Compiler 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() @@ -7888,7 +7844,7 @@ class Compiler $parsedSelector = []; - if ($parser->parseSelector($arg, $parsedSelector)) { + if ($parser->parseSelector($arg, $parsedSelector, true)) { $selector = $this->evalSelectors($parsedSelector); $gluedSelector = $this->glueFunctionSelectors($selector); diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Node/Number.php b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Node/Number.php index 0f2099f58f..1ebd30d7ab 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Node/Number.php +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Node/Number.php @@ -13,6 +13,7 @@ namespace ScssPhp\ScssPhp\Node; use ScssPhp\ScssPhp\Compiler; +use ScssPhp\ScssPhp\Exception\SassScriptException; use ScssPhp\ScssPhp\Node; use ScssPhp\ScssPhp\Type; @@ -76,74 +77,55 @@ class Number extends Node implements \ArrayAccess /** * @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; } /** @@ -187,13 +169,13 @@ class Number extends Node implements \ArrayAccess 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); } } @@ -202,17 +184,7 @@ class Number extends Node implements \ArrayAccess */ 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'); } /** @@ -220,17 +192,7 @@ class Number extends Node implements \ArrayAccess */ 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'); } /** @@ -240,61 +202,238 @@ class Number extends Node implements \ArrayAccess */ 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; + } } /** @@ -308,35 +447,29 @@ class Number extends Node implements \ArrayAccess { $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; } /** @@ -348,48 +481,216 @@ class Number extends Node implements \ArrayAccess } /** - * 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) : ''); + } } diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Parser.php b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Parser.php index 7b47f15330..55371e53a3 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Parser.php +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Parser.php @@ -39,7 +39,6 @@ class Parser 'and' => 2, '==' => 3, '!=' => 3, - '<=>' => 3, '<=' => 4, '>=' => 4, '<' => 4, @@ -98,7 +97,7 @@ class Parser $this->cssOnly = $cssOnly; if (empty(static::$operatorPattern)) { - static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)'; + static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=?|and|or)'; $commentSingle = '\/\/'; $commentMultiLeft = '\/\*'; @@ -135,8 +134,29 @@ class Parser * @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); @@ -150,7 +170,7 @@ class Parser $e = new ParserException("$msg: failed at `$m[1]` $loc"); $e->setSourcePosition([$this->sourceName, $line, $column]); - throw $e; + return $e; } $this->restoreEncoding(); @@ -158,7 +178,7 @@ class Parser $e = new ParserException("$msg: $loc"); $e->setSourcePosition([$this->sourceName, $line, $column]); - throw $e; + return $e; } /** @@ -209,11 +229,11 @@ class Parser } 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) { @@ -248,6 +268,7 @@ class Parser $this->buffer = (string) $buffer; $this->saveEncoding(); + $this->extractLineNumbers($this->buffer); $list = $this->valueList($out); @@ -263,10 +284,11 @@ class Parser * * @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; @@ -275,11 +297,16 @@ class Parser $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; } @@ -302,6 +329,7 @@ class Parser $this->buffer = (string) $buffer; $this->saveEncoding(); + $this->extractLineNumbers($this->buffer); $isMediaQuery = $this->mediaQueryList($out); @@ -460,7 +488,7 @@ class Parser $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; } @@ -478,7 +506,7 @@ class Parser $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; } @@ -523,32 +551,6 @@ class Parser $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) && @@ -723,8 +725,7 @@ class Parser $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; @@ -824,7 +825,7 @@ class Parser ! \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" ); } @@ -965,7 +966,7 @@ class Parser if ($this->valueList($value)) { if (empty($this->env->parent)) { - $this->throwParseError('expected "{"'); + throw $this->parseError('expected "{"'); } $this->append([Type::T_ASSIGN, $name, $value], $s); @@ -1115,7 +1116,7 @@ class Parser $block = $this->env; if (empty($block->parent)) { - $this->throwParseError('unexpected }'); + throw $this->parseError('unexpected }'); } if ($block->type == Type::T_AT_ROOT) { @@ -1185,7 +1186,7 @@ class Parser if ($type) { $message .= " ($type)"; } - $this->throwParseError($message); + throw $this->parseError($message); } return $parsed; @@ -1198,6 +1199,11 @@ class Parser */ 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], [ @@ -1232,6 +1238,7 @@ class Parser case Type::T_KEYWORD: case Type::T_NULL: case Type::T_NUMBER: + case Type::T_MEDIA: return $parsed; case Type::T_COMMENT: @@ -1250,6 +1257,16 @@ class Parser 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)) { @@ -1261,6 +1278,18 @@ class Parser } 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])) { @@ -2755,7 +2784,7 @@ class Parser $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; @@ -2917,7 +2946,7 @@ class Parser $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. @@ -2936,7 +2965,7 @@ class Parser } elseif ($this->matchEscapeCharacter($c)) { $content[] = $c; } else { - $this->throwParseError('Unterminated escape sequence'); + throw $this->parseError('Unterminated escape sequence'); } } else { $this->count -= \strlen($delim); @@ -2961,8 +2990,9 @@ class Parser 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]; @@ -2976,8 +3006,10 @@ class Parser $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); } @@ -2986,6 +3018,10 @@ class Parser } if ($this->match('.', $m, false)) { + if ($inKeywords && in_array($m[0], ["'",'"','@','&',' ','\\',':','/','%'])) { + $this->seek($s); + return false; + } $out = $m[0]; return true; @@ -3338,6 +3374,9 @@ class Parser { $selector = []; + $discardComments = $this->discardComments; + $this->discardComments = true; + for (;;) { $s = $this->count; @@ -3355,18 +3394,15 @@ class Parser 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; } @@ -3524,7 +3560,7 @@ class Parser $this->seek($ss); } } elseif ( - $this->matchChar('(') && + $this->matchChar('(', true) && ($this->openString(')', $str, '(') || true) && $this->matchChar(')') ) { @@ -3639,17 +3675,51 @@ class Parser */ 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; } diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Util.php b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Util.php index 124aa82043..980f570af4 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Util.php +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Util.php @@ -82,8 +82,8 @@ class Util */ 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'); } diff --git a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Version.php b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Version.php index 8445434c5c..cd3e190f15 100644 --- a/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Version.php +++ b/wcfsetup/install/files/lib/system/api/scssphp/scssphp/src/Version.php @@ -19,5 +19,5 @@ namespace ScssPhp\ScssPhp; */ class Version { - const VERSION = '1.2.1'; + const VERSION = '1.3'; } -- 2.20.1