mirror of
https://github.com/gtbu/Typesetter-5.3-p8.git
synced 2025-02-05 19:33:15 +01:00
update less 4.4 - bootswatch 3 fadein depr.
This commit is contained in:
parent
b7ba17e987
commit
a5f378de80
206 changed files with 2704 additions and 13761 deletions
|
@ -1,2 +0,0 @@
|
|||
.easymin
|
||||
Autoloader.php
|
2
include/thirdparty/less.php/API.md
vendored
2
include/thirdparty/less.php/API.md
vendored
|
@ -59,7 +59,7 @@ file(s) and any direct and indirect imports.
|
|||
$parser = new Less_Parser();
|
||||
$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' );
|
||||
$css = $parser->getCss();
|
||||
$files = $parser->AllParsedFiles();
|
||||
$files = $parser->getParsedFiles();
|
||||
```
|
||||
|
||||
#### Compress output
|
||||
|
|
97
include/thirdparty/less.php/CHANGES.md
vendored
97
include/thirdparty/less.php/CHANGES.md
vendored
|
@ -1,6 +1,69 @@
|
|||
# Changelog
|
||||
|
||||
## 4.2.0
|
||||
## v4.4.1
|
||||
|
||||
Fixed:
|
||||
* Update `Less_Version::version` and bump `Less_Version::cache_version` (Timo Tijhof)
|
||||
|
||||
## v4.4.0
|
||||
|
||||
Added:
|
||||
* Add `image-size()` function, disable base64 for SVG `data-uri()` (Hannah Okwelum) [T353147](https://phabricator.wikimedia.org/T353147)
|
||||
* Improve support for preserving `!important` via variables (Piotr Miazga) [T362341](https://phabricator.wikimedia.org/T362341)
|
||||
* Add support for include path inside `data-uri()` (Hannah Okwelum) [T364871](https://phabricator.wikimedia.org/T364871)
|
||||
|
||||
Changed, to match Less.js 2.5.3:
|
||||
* Fix multiplication of mixed units to preserve the first unit (Piotr Miazga) [T362341](https://phabricator.wikimedia.org/T362341)
|
||||
|
||||
Fixed:
|
||||
* Fix checking of guard conditions in nested mixins (Hannah Okwelum) [T352867](https://phabricator.wikimedia.org/T352867)
|
||||
* Less_Functions: Avoid clobbering `clamp()` with internal helper (Timo Tijhof) [T363728](https://phabricator.wikimedia.org/T363728)
|
||||
|
||||
## v4.3.0
|
||||
|
||||
Added:
|
||||
* Support interpolated variable imports, via ImportVisitor (Hannah Okwelum) [T353133](https://phabricator.wikimedia.org/T353133)
|
||||
* Support rulesets as default values of a mixin parameter (Hannah Okwelum) [T353143](https://phabricator.wikimedia.org/T353143)
|
||||
* Support `...` expand operator in mixin calls (Piotr Miazga) [T352897](https://phabricator.wikimedia.org/T352897)
|
||||
* Improve support for `@import (reference)` matching Less.js 2.x (Hannah Okwelum) [T362647](https://phabricator.wikimedia.org/T362647)
|
||||
|
||||
Changed:
|
||||
* Improve `mix()` argument exception message to mention given arg type (Timo Tijhof)
|
||||
* The `Less_Tree_Import->getPath()` method now reflects the path as written in the source code,
|
||||
without auto-appended `.less` suffix, matching upstream Less.js 2.5.3 behaviour.
|
||||
This internal detail is exposed via the deprecated `import_callback` parser option.
|
||||
It is recommended to migrate to `Less_Parser->SetImportDirs`, which doesn't expose internals,
|
||||
and is unaffected by this change.
|
||||
|
||||
Deprecated:
|
||||
* Deprecate `import_callback` Less_Parser option. Use `Less_Parser->SetImportDirs` with callback instead.
|
||||
* Deprecate `Less_Parser->SetInput()` as public method. Use `Less_Parser->parseFile()` instead.
|
||||
* Deprecate `Less_Parser->CacheFile()` as public method. Use `Less_Cache` API instead.
|
||||
* Deprecate `Less_Parser::AllParsedFiles()` as static method. Use `Less_Parser->getParsedFiles()` instead.
|
||||
* Deprecate `Less_Parser->UnsetInput()` as public method, considered internal.
|
||||
* Deprecate `Less_Parser->save()` as public method, considered internal.
|
||||
|
||||
Fixed:
|
||||
* Fix `replace()` when passed multiple replacements (Roan Kattouw) [T358631](https://phabricator.wikimedia.org/T358631)
|
||||
* Fix unexpected duplicating of uncalled mixin rules (Hannah Okwelum) [T363076](https://phabricator.wikimedia.org/T363076)
|
||||
* Fix ParseError for comments after rule name or in `@keyframes` (Piotr Miazga) [T353131](https://phabricator.wikimedia.org/T353131)
|
||||
* Fix ParseError for comments in more places and preserve them (Piotr Miazga) [T353132](https://phabricator.wikimedia.org/T353132)
|
||||
* Fix ParseError effecting pseudo classes with `when` guards (Piotr Miazga) [T353144](https://phabricator.wikimedia.org/T353144)
|
||||
* Fix preservation of units in some cases (Timo Tijhof) [T360065](https://phabricator.wikimedia.org/T360065)
|
||||
* Less_Parser: Faster matching by inlining `matcher()` chains (Timo Tijhof)
|
||||
* Less_Parser: Faster matching with `matchStr()` method (Timo Tijhof)
|
||||
|
||||
## v4.2.1
|
||||
|
||||
Added:
|
||||
* Add support for `/deep/` selectors (Hannah Okwelum) [T352862](https://phabricator.wikimedia.org/T352862)
|
||||
|
||||
Fixed:
|
||||
* Fix ParseError in some division expressions (Hannah Okwelum) [T358256](https://phabricator.wikimedia.org/T358256)
|
||||
* Fix `when()` matching between string and non-string (Timo Tijhof) [T358159](https://phabricator.wikimedia.org/T358159)
|
||||
* Preserve whitespace before `;` or `!` in simple rules (Hannah Okwelum) [T352911](https://phabricator.wikimedia.org/T352911)
|
||||
|
||||
## v4.2.0
|
||||
|
||||
Added:
|
||||
* Add `isruleset()` function (Hannah Okwelum) [T354895](https://phabricator.wikimedia.org/T354895)
|
||||
|
@ -25,7 +88,7 @@ Fixed:
|
|||
* Fix string comparison to ignore quote type (Timo Tijhof) [T357160](https://phabricator.wikimedia.org/T357160)
|
||||
* Fix string interpolation in selectors (Hannah Okwelum) [T353142](https://phabricator.wikimedia.org/T353142)
|
||||
|
||||
## 4.1.1
|
||||
## v4.1.1
|
||||
|
||||
* Less_Parser: Faster `MatchQuoted` by using native `strcspn`. (Thiemo Kreuz)
|
||||
* Less_Parser: Faster `parseEntitiesQuoted` by inlining `MatchQuoted`. (Thiemo Kreuz)
|
||||
|
@ -33,12 +96,12 @@ Fixed:
|
|||
* Less_Tree_Mixin_Call: Include mixin name in error message (Jeremy P)
|
||||
* Fix mismatched casing in class names to fix autoloading on case-sensitive filesystems (Jeremy P)
|
||||
|
||||
## 4.1.0
|
||||
## v4.1.0
|
||||
|
||||
* Add support for `@supports` blocks. (Anne Tomasevich) [T332923](http://phabricator.wikimedia.org/T332923)
|
||||
* Less_Parser: Returning a URI from `SetImportDirs()` callbacks is now optional. (Timo Tijhof)
|
||||
|
||||
## 4.0.0
|
||||
## v4.0.0
|
||||
|
||||
* Remove support for PHP 7.2 and 7.3. Raise requirement to PHP 7.4+.
|
||||
* Remove support for `cache_method=php` and `cache_method=var_export`, only the faster and more secure `cache_method=serialize` is now available. The built-in cache remains disabled by default.
|
||||
|
@ -46,14 +109,14 @@ Fixed:
|
|||
* Fix "Undefined property" PHP 8.1 warning when `calc()` is used with CSS `var()`. [T331688](https://phabricator.wikimedia.org/T331688)
|
||||
* Less_Parser: Improve performance by removing MatchFuncs and NewObj overhead. (Timo Tijhof)
|
||||
|
||||
## 3.2.1
|
||||
## v3.2.1
|
||||
|
||||
* Tree_Ruleset: Fix support for nested parent selectors (Timo Tijhof) [T204816](https://phabricator.wikimedia.org/T204816)
|
||||
* Fix ParseError when interpolating variable after colon in selector (Timo Tijhof) [T327163](https://phabricator.wikimedia.org/T327163)
|
||||
* Functions: Fix "Undefined property" warning on bad minmax arg
|
||||
* Tree_Call: Include previous exception when catching functions (Robert Frunzke)
|
||||
|
||||
## 3.2.0
|
||||
## v3.2.0
|
||||
|
||||
* Fix "Implicit conversion" PHP 8.1 warnings (Ayokunle Odusan)
|
||||
* Fix "Creation of dynamic property" PHP 8.2 warnings (Bas Couwenberg)
|
||||
|
@ -61,33 +124,33 @@ Fixed:
|
|||
* Tree_Url: Add support for "Url" type to `Parser::getVariables()` (ciroarcadio) [#51](https://github.com/wikimedia/less.php/pull/51)
|
||||
* Tree_Import: Add support for importing URLs without file extension (Timo Tijhof) [#27](https://github.com/wikimedia/less.php/issues/27)
|
||||
|
||||
## 3.1.0
|
||||
## v3.1.0
|
||||
|
||||
* Add PHP 8.0 support: Drop use of curly braces for sub-string eval (James D. Forrester)
|
||||
* Make `Directive::__construct` $rules arg optional (fix PHP 7.4 warning) (Sam Reed)
|
||||
* ProcessExtends: Improve performance by using a map for selectors and parents (Andrey Legayev)
|
||||
|
||||
## 3.0.0
|
||||
## v3.0.0
|
||||
|
||||
* Raise PHP requirement from 7.1 to 7.2.9 (James Forrester)
|
||||
|
||||
## 2.0.0
|
||||
## v2.0.0
|
||||
|
||||
* Relax PHP requirement down to 7.1, from 7.2.9 (Franz Liedke)
|
||||
* Reflect recent breaking changes properly with the semantic versioning (James Forrester)
|
||||
|
||||
## 1.8.2
|
||||
## v1.8.2
|
||||
|
||||
* Require PHP 7.2.9+, up from 5.3+ (James Forrester)
|
||||
* release: Update Version.php with the current release ID (COBadger)
|
||||
* Fix access array offset on value of type null (Michele Locati)
|
||||
* Fix test suite on PHP 7.4 (Sergei Morozov)
|
||||
|
||||
## 1.8.1
|
||||
## v1.8.1
|
||||
|
||||
* Another PHP 7.3 compatibility tweak
|
||||
|
||||
## 1.8.0
|
||||
## v1.8.0
|
||||
|
||||
Library forked by Wikimedia, from [oyejorge/less.php](https://github.com/oyejorge/less.php).
|
||||
|
||||
|
@ -95,21 +158,21 @@ Library forked by Wikimedia, from [oyejorge/less.php](https://github.com/oyejorg
|
|||
* No longer tested against PHP 5, though it's still remains allowed in `composer.json` for HHVM compatibility
|
||||
* Switched to [semantic versioning](https://semver.org/), hence version numbers now use 3 digits
|
||||
|
||||
## 1.7.0.13
|
||||
## v1.7.0.13
|
||||
|
||||
* Fix composer.json (PSR-4 was invalid)
|
||||
|
||||
## 1.7.0.12
|
||||
## v1.7.0.12
|
||||
|
||||
* set bin/lessc bit executable
|
||||
* Add `gettingVariables` method to `Less_Parser`
|
||||
|
||||
## 1.7.0.11
|
||||
## v1.7.0.11
|
||||
|
||||
* Fix realpath issue (windows)
|
||||
* Set Less_Tree_Call property back to public ( Fix 258 266 267 issues from oyejorge/less.php)
|
||||
|
||||
## 1.7.0.10
|
||||
## v1.7.0.10
|
||||
|
||||
* Add indentation option
|
||||
* Add `optional` modifier for `@import`
|
||||
|
@ -118,7 +181,7 @@ Library forked by Wikimedia, from [oyejorge/less.php](https://github.com/oyejorg
|
|||
* urlArgs should be string no array()
|
||||
* fix missing on NameValue type [#269](https://github.com/oyejorge/less.php/issues/269)
|
||||
|
||||
## 1.7.0.9
|
||||
## v1.7.0.9
|
||||
|
||||
* Remove space at beginning of Version.php
|
||||
* Revert require() paths in test interface
|
||||
|
|
78
include/thirdparty/less.php/CONTRIBUTING.md
vendored
Normal file
78
include/thirdparty/less.php/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
# Maintainers guide
|
||||
|
||||
## Release process
|
||||
|
||||
1. **Changelog.** Add a new section to the top of `CHANGES.md` with the output from `composer changelog`.
|
||||
|
||||
Edit your new section by following the [Keep a changelog](https://keepachangelog.com/en/1.0.0/) conventions, where by bullet points are under one of the "Added", "Changed", "Fixed", "Deprecated", or "Removed" labels.
|
||||
|
||||
Review each point and make sure it is phrased in a way that explains the impact on end-users of the library. If the change does not affect the public API or CSS output, remove the bullet point.
|
||||
|
||||
2. **Version bump.** Update `/lib/Less/Version.php` and set `version` to the version that you're about to release. Also increase `cache_version` to increment the last number.
|
||||
|
||||
3. **Commit.** Stage and commit your changes with the message `Tag vX.Y.Z`, and then push the commit for review.
|
||||
|
||||
4. **Tag.** After the above release commit is merged, checkout the master branch and pull down the latest changes. Then create a `vX.Y.Z` tag and push the tag.
|
||||
|
||||
Remember to, after the commit is merged, first checkout the master branch and pull down the latest changes. This is to make sure you have the merged version and not the draft commit that you pushed for review.
|
||||
|
||||
## Internal overview
|
||||
|
||||
This is an overview of the high-level steps during the transformation
|
||||
from Less to CSS, and how they compare between Less.js and Less.php.
|
||||
|
||||
Less.js:
|
||||
|
||||
* `less.render(input, { paths: … })`
|
||||
* `Parser.parse` normalizes input
|
||||
* `Parser.parse` parses input into rules via `parsers.primary`
|
||||
* `Parser.parse` creates the "root" ruleset object
|
||||
* `Parser.parse` applies ImportVisitor
|
||||
* `ImportVisitor` applies these steps to each `Import` node:
|
||||
* `ImportVisitor#processImportNode`
|
||||
* `Import#evalForImport`
|
||||
* `ImportVisitor` ends with `ImporVisitor#tryRun` loop (async, after last call to `ImportVisitor#onImported`.
|
||||
* `less.render` callback
|
||||
* `ParseTree.prototype.toCSS`
|
||||
* `transformTree` applies pre-visitors, compiles all rules, and applies post-visitors.
|
||||
* `ParseTree.prototype.toCSS` runs toCSS transform on the "root" ruleset.
|
||||
* CSS result ready!
|
||||
|
||||
Less.php
|
||||
|
||||
* `Less_Parser->parseFile`
|
||||
* `Less_Parser->_parse`
|
||||
* `Less_Parser->GetRules` normalizes input (via `Less_Parser->SetInput`)
|
||||
* `Less_Parser->GetRules` parses input into rules via `Less_Parser->parsePrimary`
|
||||
* `Less_Parser->getCss`
|
||||
* `Less_Parser->getCss` creates the "root" ruleset object
|
||||
* `Less_Parser->getCss` applies Less_ImportVisitor
|
||||
* `Less_ImportVisitor` applies these steps to each `Import` node:
|
||||
* `ImportVisitor->processImportNode`
|
||||
* `Less_Tree_Import->compileForImport`
|
||||
* `ImportVisitor` ends with `ImporVisitor#tryRun` loop (all sync, no async needed).
|
||||
* `Less_Parser->getCss` applies pre-visitors, compiles all rules, and applies post-visitors.
|
||||
* `Less_Parser->getCss` runs toCSS transform on the "root" ruleset.
|
||||
* CSS result ready!
|
||||
|
||||
## Compatibility
|
||||
|
||||
The `wikimedia/less.php` package inherits a long history of loosely compatible
|
||||
and interchangable Less compilers written in PHP.
|
||||
|
||||
Starting with less.php v3.2.1 (released in 2023), the public API is more clearly
|
||||
documented, and internal code is now consistently marked `@private`.
|
||||
|
||||
The public API includes the `Less_Parser` class and several of its public methods.
|
||||
For legacy reasons, some of its internal methods remain public. Maintainers must
|
||||
take care to search the following downstream applications when changing or
|
||||
removing public methods. If a method has one or more references in the below
|
||||
codebases, treat it as a breaking change and document a migration path in the
|
||||
commit message (and later in CHANGES.md), even if the method was undocumented
|
||||
or feels like it is for internal use only.
|
||||
|
||||
* [MediaWiki (source code)](https://codesearch.wmcloud.org/core/?q=Less_Parser&files=php%24)
|
||||
* [Matomo (source code)](https://github.com/matomo-org/matomo/blob/5.0.2/core/AssetManager/UIAssetMerger/StylesheetUIAssetMerger.php)
|
||||
* [Adobe Magento (source code)](https://github.com/magento/magento2/blob/2.4.6/lib/internal/Magento/Framework/Css/PreProcessor/Adapter/Less/Processor.php)
|
||||
* [Shopware 5 (source code)](https://github.com/shopware5/shopware/blob/5.7/engine/Shopware/Components/Theme/LessCompiler/Oyejorge.php)
|
||||
* [Winter CMS Assetic (source code)](https://github.com/assetic-php/assetic/tree/v3.1.0/src/Assetic/Filter)
|
2
include/thirdparty/less.php/Cache.php
vendored
2
include/thirdparty/less.php/Cache.php
vendored
|
@ -149,7 +149,7 @@ class Less_Cache {
|
|||
|
||||
$compiled = $parser->getCss();
|
||||
|
||||
$less_files = $parser->AllParsedFiles();
|
||||
$less_files = $parser->getParsedFiles();
|
||||
|
||||
return $compiled;
|
||||
}
|
||||
|
|
101
include/thirdparty/less.php/Environment.php
vendored
101
include/thirdparty/less.php/Environment.php
vendored
|
@ -26,17 +26,34 @@ class Less_Environment {
|
|||
/** @var Less_Tree_Media[] */
|
||||
public $mediaPath = [];
|
||||
|
||||
/** @var string[] */
|
||||
public $imports = [];
|
||||
|
||||
/** @var array */
|
||||
public $importantScope = [];
|
||||
|
||||
/**
|
||||
* This is the equivalent of `importVisitor.onceFileDetectionMap`
|
||||
* as used by the dynamic `importNode.skip` function.
|
||||
*
|
||||
* @see less-2.5.3.js#ImportVisitor.prototype.onImported
|
||||
* @var array<string,true>
|
||||
*/
|
||||
public $importVisitorOnceMap = [];
|
||||
|
||||
public static $parensStack = 0;
|
||||
|
||||
public static $tabLevel = 0;
|
||||
|
||||
public static $lastRule = false;
|
||||
|
||||
public static $_outputMap;
|
||||
public static $_noSpaceCombinators;
|
||||
|
||||
public static $mixin_stack = 0;
|
||||
|
||||
public static $mathOn = true;
|
||||
public $strictMath = false;
|
||||
|
||||
public $importCallback = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
|
@ -49,44 +66,42 @@ class Less_Environment {
|
|||
self::$lastRule = false;
|
||||
self::$mixin_stack = 0;
|
||||
|
||||
if ( Less_Parser::$options['compress'] ) {
|
||||
self::$_noSpaceCombinators = [
|
||||
'' => true,
|
||||
' ' => true,
|
||||
'|' => true
|
||||
];
|
||||
}
|
||||
|
||||
self::$_outputMap = [
|
||||
',' => ',',
|
||||
': ' => ':',
|
||||
'' => '',
|
||||
' ' => ' ',
|
||||
':' => ' :',
|
||||
'+' => '+',
|
||||
'~' => '~',
|
||||
'>' => '>',
|
||||
'|' => '|',
|
||||
'^' => '^',
|
||||
'^^' => '^^'
|
||||
];
|
||||
/**
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
public function addParsedFile( $file ) {
|
||||
$this->imports[] = $file;
|
||||
}
|
||||
|
||||
} else {
|
||||
public function clone() {
|
||||
$new_env = clone $this;
|
||||
// NOTE: Match JavaScript by-ref behaviour for arrays
|
||||
$new_env->imports =& $this->imports;
|
||||
$new_env->importVisitorOnceMap =& $this->importVisitorOnceMap;
|
||||
return $new_env;
|
||||
}
|
||||
|
||||
self::$_outputMap = [
|
||||
',' => ', ',
|
||||
': ' => ': ',
|
||||
'' => '',
|
||||
' ' => ' ',
|
||||
':' => ' :',
|
||||
'+' => ' + ',
|
||||
'~' => ' ~ ',
|
||||
'>' => ' > ',
|
||||
'|' => '|',
|
||||
'^' => ' ^ ',
|
||||
'^^' => ' ^^ '
|
||||
];
|
||||
|
||||
}
|
||||
/**
|
||||
* @param string $file
|
||||
* @return bool
|
||||
*/
|
||||
public function isFileParsed( $file ) {
|
||||
return in_array( $file, $this->imports );
|
||||
}
|
||||
|
||||
public function copyEvalEnv( $frames = [] ) {
|
||||
$new_env = new self();
|
||||
$new_env->frames = $frames;
|
||||
$new_env->importantScope = $this->importantScope;
|
||||
$new_env->strictMath = $this->strictMath;
|
||||
return $new_env;
|
||||
}
|
||||
|
||||
|
@ -94,11 +109,8 @@ class Less_Environment {
|
|||
* @return bool
|
||||
* @see Eval.prototype.isMathOn in less.js 3.0.0 https://github.com/less/less.js/blob/v3.0.0/dist/less.js#L1007
|
||||
*/
|
||||
public static function isMathOn() {
|
||||
if ( !self::$mathOn ) {
|
||||
return false;
|
||||
}
|
||||
return !Less_Parser::$options['strictMath'] || self::$parensStack;
|
||||
public function isMathOn() {
|
||||
return $this->strictMath ? (bool)self::$parensStack : true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,6 +122,21 @@ class Less_Environment {
|
|||
return !preg_match( '/^(?:[a-z-]+:|\/|#)/', $path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply legacy 'import_callback' option.
|
||||
*
|
||||
* See Less_Parser::$default_options to learn more about the 'import_callback' option.
|
||||
* This option is deprecated in favour of Less_Parser::SetImportDirs.
|
||||
*
|
||||
* @param Less_Tree_Import $importNode
|
||||
* @return array{0:string,1:string|null}|null Array containing path and (optional) uri or null
|
||||
*/
|
||||
public function callImportCallback( Less_Tree_Import $importNode ) {
|
||||
if ( is_callable( $this->importCallback ) ) {
|
||||
return ( $this->importCallback )( $importNode );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize a path by resolving references to '/./', '/../'
|
||||
* Does not remove leading "../"
|
||||
|
|
65
include/thirdparty/less.php/FileManager.php
vendored
Normal file
65
include/thirdparty/less.php/FileManager.php
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_FileManager {
|
||||
/**
|
||||
* Get the full absolute path and uri of the import
|
||||
* @see less-node/FileManager.getPath https://github.com/less/less.js/blob/v2.5.3/lib/less-node/file-manager.js#L70
|
||||
* @param string $filename
|
||||
* @param null|array $currentFileInfo
|
||||
* @return null|array
|
||||
*/
|
||||
public static function getFilePath( $filename, $currentFileInfo ) {
|
||||
if ( !$filename ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$import_dirs = [];
|
||||
|
||||
if ( Less_Environment::isPathRelative( $filename ) ) {
|
||||
// if the path is relative, the file should be in the current directory
|
||||
if ( $currentFileInfo ) {
|
||||
$import_dirs[ $currentFileInfo['currentDirectory'] ] = $currentFileInfo['uri_root'];
|
||||
}
|
||||
|
||||
} else {
|
||||
// otherwise, the file should be relative to the server root
|
||||
if ( $currentFileInfo ) {
|
||||
$import_dirs[ $currentFileInfo['entryPath'] ] = $currentFileInfo['entryUri'];
|
||||
}
|
||||
// if the user supplied entryPath isn't the actual root
|
||||
$import_dirs[ $_SERVER['DOCUMENT_ROOT'] ] = '';
|
||||
|
||||
}
|
||||
|
||||
// always look in user supplied import directories
|
||||
$import_dirs = array_merge( $import_dirs, Less_Parser::$options['import_dirs'] );
|
||||
|
||||
foreach ( $import_dirs as $rootpath => $rooturi ) {
|
||||
if ( is_callable( $rooturi ) ) {
|
||||
$res = $rooturi( $filename );
|
||||
if ( $res && is_string( $res[0] ) ) {
|
||||
return [
|
||||
Less_Environment::normalizePath( $res[0] ),
|
||||
Less_Environment::normalizePath( $res[1] ?? dirname( $filename ) )
|
||||
];
|
||||
}
|
||||
} elseif ( !empty( $rootpath ) ) {
|
||||
$path = rtrim( $rootpath, '/\\' ) . '/' . ltrim( $filename, '/\\' );
|
||||
if ( file_exists( $path ) ) {
|
||||
return [
|
||||
Less_Environment::normalizePath( $path ),
|
||||
Less_Environment::normalizePath( dirname( $rooturi . $filename ) )
|
||||
];
|
||||
}
|
||||
if ( file_exists( $path . '.less' ) ) {
|
||||
return [
|
||||
Less_Environment::normalizePath( $path . '.less' ),
|
||||
Less_Environment::normalizePath( dirname( $rooturi . $filename . '.less' ) )
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
259
include/thirdparty/less.php/Functions.php
vendored
259
include/thirdparty/less.php/Functions.php
vendored
|
@ -14,41 +14,11 @@ class Less_Functions {
|
|||
$this->currentFileInfo = $currentFileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $op
|
||||
* @param float $a
|
||||
* @param float $b
|
||||
*/
|
||||
public static function operate( $op, $a, $b ) {
|
||||
switch ( $op ) {
|
||||
case '+':
|
||||
return $a + $b;
|
||||
case '-':
|
||||
return $a - $b;
|
||||
case '*':
|
||||
return $a * $b;
|
||||
case '/':
|
||||
return $a / $b;
|
||||
}
|
||||
}
|
||||
|
||||
public static function clamp( $val, $max = 1 ) {
|
||||
private static function _clamp( $val, $max = 1 ) {
|
||||
return min( max( $val, 0 ), $max );
|
||||
}
|
||||
|
||||
public static function fround( $value ) {
|
||||
if ( $value === 0 ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( Less_Parser::$options['numPrecision'] ) {
|
||||
$p = pow( 10, Less_Parser::$options['numPrecision'] );
|
||||
return round( $value * $p ) / $p;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function number( $n ) {
|
||||
private static function _number( $n ) {
|
||||
if ( $n instanceof Less_Tree_Dimension ) {
|
||||
return floatval( $n->unit->is( '%' ) ? $n->value / 100 : $n->value );
|
||||
} elseif ( is_numeric( $n ) ) {
|
||||
|
@ -58,11 +28,11 @@ class Less_Functions {
|
|||
}
|
||||
}
|
||||
|
||||
public static function scaled( $n, $size = 255 ) {
|
||||
private static function _scaled( $n, $size = 255 ) {
|
||||
if ( $n instanceof Less_Tree_Dimension && $n->unit->is( '%' ) ) {
|
||||
return (float)$n->value * $size / 100;
|
||||
} else {
|
||||
return self::number( $n );
|
||||
return self::_number( $n );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,10 +44,13 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
public function rgba( $r = null, $g = null, $b = null, $a = null ) {
|
||||
$rgb = [ $r, $g, $b ];
|
||||
$rgb = array_map( [ __CLASS__, 'scaled' ], $rgb );
|
||||
$rgb = [
|
||||
self::_scaled( $r ),
|
||||
self::_scaled( $g ),
|
||||
self::_scaled( $b )
|
||||
];
|
||||
|
||||
$a = self::number( $a );
|
||||
$a = self::_number( $a );
|
||||
return new Less_Tree_Color( $rgb, $a );
|
||||
}
|
||||
|
||||
|
@ -86,10 +59,10 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
public function hsla( $h, $s, $l, $a ) {
|
||||
$h = fmod( self::number( $h ), 360 ) / 360; // Classic % operator will change float to int
|
||||
$s = self::clamp( self::number( $s ) );
|
||||
$l = self::clamp( self::number( $l ) );
|
||||
$a = self::clamp( self::number( $a ) );
|
||||
$h = fmod( self::_number( $h ), 360 ) / 360; // Classic % operator will change float to int
|
||||
$s = self::_clamp( self::_number( $s ) );
|
||||
$l = self::_clamp( self::_number( $l ) );
|
||||
$a = self::_clamp( self::_number( $a ) );
|
||||
|
||||
$m2 = $l <= 0.5 ? $l * ( $s + 1 ) : $l + $s - $l * $s;
|
||||
|
||||
|
@ -132,10 +105,10 @@ class Less_Functions {
|
|||
* @param float $a
|
||||
*/
|
||||
public function hsva( $h, $s, $v, $a ) {
|
||||
$h = ( ( self::number( $h ) % 360 ) / 360 ) * 360;
|
||||
$s = self::number( $s );
|
||||
$v = self::number( $v );
|
||||
$a = self::number( $a );
|
||||
$h = ( ( self::_number( $h ) % 360 ) / 360 ) * 360;
|
||||
$s = self::_number( $s );
|
||||
$v = self::_number( $v );
|
||||
$a = self::_number( $a );
|
||||
|
||||
$i = (int)floor( (int)( $h / 60 ) % 6 );
|
||||
$f = ( $h / 60 ) - $i;
|
||||
|
@ -292,7 +265,7 @@ class Less_Functions {
|
|||
$hsl['s'] += $hsl['s'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['s'] += $amount->value / 100;
|
||||
} $hsl['s'] = self::clamp( $hsl['s'] );
|
||||
} $hsl['s'] = self::_clamp( $hsl['s'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
@ -317,7 +290,7 @@ class Less_Functions {
|
|||
$hsl['s'] -= $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['s'] = self::clamp( $hsl['s'] );
|
||||
$hsl['s'] = self::_clamp( $hsl['s'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
@ -338,7 +311,7 @@ class Less_Functions {
|
|||
$hsl['l'] += $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['l'] = self::clamp( $hsl['l'] );
|
||||
$hsl['l'] = self::_clamp( $hsl['l'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
@ -357,7 +330,7 @@ class Less_Functions {
|
|||
} else {
|
||||
$hsl['l'] -= $amount->value / 100;
|
||||
}
|
||||
$hsl['l'] = self::clamp( $hsl['l'] );
|
||||
$hsl['l'] = self::_clamp( $hsl['l'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
@ -378,7 +351,7 @@ class Less_Functions {
|
|||
$hsl['a'] += $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['a'] = self::clamp( $hsl['a'] );
|
||||
$hsl['a'] = self::_clamp( $hsl['a'] );
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
|
@ -398,7 +371,7 @@ class Less_Functions {
|
|||
$hsl['a'] -= $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['a'] = self::clamp( $hsl['a'] );
|
||||
$hsl['a'] = self::_clamp( $hsl['a'] );
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
|
@ -413,7 +386,7 @@ class Less_Functions {
|
|||
$hsl = $color->toHSL();
|
||||
|
||||
$hsl['a'] = $amount->value / 100;
|
||||
$hsl['a'] = self::clamp( $hsl['a'] );
|
||||
$hsl['a'] = self::_clamp( $hsl['a'] );
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
|
@ -445,16 +418,19 @@ class Less_Functions {
|
|||
*/
|
||||
public function mix( $color1 = null, $color2 = null, $weight = null ) {
|
||||
if ( !$color1 instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The first argument to mix must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
$type = is_object( $color1 ) ? get_class( $color1 ) : gettype( $color1 );
|
||||
throw new Less_Exception_Compiler( "The first argument must be a color, $type given" . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
if ( !$color2 instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The second argument to mix must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
$type = is_object( $color2 ) ? get_class( $color2 ) : gettype( $color2 );
|
||||
throw new Less_Exception_Compiler( "The second argument must be a color, $type given" . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
if ( !$weight ) {
|
||||
$weight = new Less_Tree_Dimension( '50', '%' );
|
||||
}
|
||||
if ( !$weight instanceof Less_Tree_Dimension ) {
|
||||
throw new Less_Exception_Compiler( 'The third argument to contrast must be a percentage' . ( $weight instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
$type = is_object( $weight ) ? get_class( $weight ) : gettype( $weight );
|
||||
throw new Less_Exception_Compiler( "The third argument must be a percentage, $type given" . ( $weight instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
$p = $weight->value / 100.0;
|
||||
|
@ -510,7 +486,7 @@ class Less_Functions {
|
|||
if ( !$threshold ) {
|
||||
$threshold = 0.43;
|
||||
} else {
|
||||
$threshold = self::number( $threshold );
|
||||
$threshold = self::_number( $threshold );
|
||||
}
|
||||
|
||||
if ( $color->luma() < $threshold ) {
|
||||
|
@ -547,10 +523,10 @@ class Less_Functions {
|
|||
$replacement = ( $replacement instanceof Less_Tree_Quoted ) ?
|
||||
$replacement->value : $replacement->toCSS();
|
||||
|
||||
$result = preg_replace( $expr, $replacement, $result, 1 );
|
||||
|
||||
if ( $flags && $flags->value && preg_match( '/g/', $flags->value ) ) {
|
||||
$result = preg_replace( $expr, $replacement, $result );
|
||||
} else {
|
||||
$result = preg_replace( $expr, $replacement, $result, 1 );
|
||||
}
|
||||
|
||||
if ( $string instanceof Less_Tree_Quoted ) {
|
||||
|
@ -559,7 +535,7 @@ class Less_Functions {
|
|||
return new Less_Tree_Quoted( '', $result );
|
||||
}
|
||||
|
||||
public static function replace_flags( $flags ) {
|
||||
private static function replace_flags( $flags ) {
|
||||
return str_replace( [ 'e', 'g' ], '', $flags );
|
||||
}
|
||||
|
||||
|
@ -693,8 +669,9 @@ class Less_Functions {
|
|||
/**
|
||||
* @param bool $isMin
|
||||
* @param array<Less_Tree> $args
|
||||
* @see less-2.5.3.js#minMax
|
||||
*/
|
||||
private function _minmax( $isMin, $args ) {
|
||||
private function _minMax( $isMin, $args ) {
|
||||
$arg_count = count( $args );
|
||||
|
||||
if ( $arg_count < 1 ) {
|
||||
|
@ -775,15 +752,15 @@ class Less_Functions {
|
|||
foreach ( $order as $a ) {
|
||||
$args[] = $a->toCSS();
|
||||
}
|
||||
return new Less_Tree_Anonymous( ( $isMin ? 'min(' : 'max(' ) . implode( Less_Environment::$_outputMap[','], $args ) . ')' );
|
||||
return new Less_Tree_Anonymous( ( $isMin ? 'min(' : 'max(' ) . implode( ( Less_Parser::$options['compress'] ? ',' : ', ' ), $args ) . ')' );
|
||||
}
|
||||
|
||||
public function min( ...$args ) {
|
||||
return $this->_minmax( true, $args );
|
||||
return $this->_minMax( true, $args );
|
||||
}
|
||||
|
||||
public function max( ...$args ) {
|
||||
return $this->_minmax( false, $args );
|
||||
return $this->_minMax( false, $args );
|
||||
}
|
||||
|
||||
public function getunit( $n ) {
|
||||
|
@ -814,6 +791,7 @@ class Less_Functions {
|
|||
return new Less_Tree_Color( substr( $c->value, 1 ) );
|
||||
}
|
||||
|
||||
// phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition
|
||||
if ( ( $c instanceof Less_Tree_Color ) || ( $c = Less_Tree_Color::fromKeyword( $c->value ) ) ) {
|
||||
$c->value = null;
|
||||
return $c;
|
||||
|
@ -901,49 +879,39 @@ class Less_Functions {
|
|||
return new Less_Tree_Dimension( $n );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#data-uri
|
||||
*/
|
||||
public function datauri( $mimetypeNode, $filePathNode = null ) {
|
||||
$filePath = ( $filePathNode ? $filePathNode->value : null );
|
||||
$mimetype = $mimetypeNode->value;
|
||||
|
||||
$args = 2;
|
||||
if ( !$filePath ) {
|
||||
$filePath = $mimetype;
|
||||
$args = 1;
|
||||
if ( !$filePathNode ) {
|
||||
$filePathNode = $mimetypeNode;
|
||||
$mimetypeNode = null;
|
||||
}
|
||||
|
||||
$filePath = $filePathNode->value;
|
||||
$mimetype = ( $mimetypeNode ? $mimetypeNode->value : null );
|
||||
|
||||
$filePath = str_replace( '\\', '/', $filePath );
|
||||
if ( Less_Environment::isPathRelative( $filePath ) ) {
|
||||
$currentFileInfo = $this->currentFileInfo;
|
||||
'@phan-var array $currentFileInfo';
|
||||
if ( Less_Parser::$options['relativeUrls'] ) {
|
||||
$temp = $currentFileInfo['currentDirectory'];
|
||||
} else {
|
||||
$temp = $currentFileInfo['entryPath'];
|
||||
}
|
||||
|
||||
if ( !empty( $temp ) ) {
|
||||
$filePath = Less_Environment::normalizePath( rtrim( $temp, '/' ) . '/' . $filePath );
|
||||
}
|
||||
|
||||
$fragmentStart = strpos( $filePath, '#' );
|
||||
$fragment = '';
|
||||
if ( $fragmentStart !== false ) {
|
||||
$fragment = substr( $filePath, $fragmentStart );
|
||||
$filePath = substr( $filePath, 0, $fragmentStart );
|
||||
}
|
||||
|
||||
[ $filePath ] = Less_FileManager::getFilePath( $filePath, $this->currentFileInfo );
|
||||
|
||||
// detect the mimetype if not given
|
||||
if ( $args < 2 ) {
|
||||
|
||||
/* incomplete
|
||||
$mime = require('mime');
|
||||
mimetype = mime.lookup(path);
|
||||
|
||||
// use base 64 unless it's an ASCII or UTF-8 format
|
||||
var charset = mime.charsets.lookup(mimetype);
|
||||
useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
|
||||
if (useBase64) mimetype += ';base64';
|
||||
*/
|
||||
if ( !$mimetype ) {
|
||||
|
||||
$mimetype = Less_Mime::lookup( $filePath );
|
||||
|
||||
$charset = Less_Mime::charsets_lookup( $mimetype );
|
||||
$useBase64 = !in_array( $charset, [ 'US-ASCII', 'UTF-8' ] );
|
||||
if ( $mimetype === "image/svg+xml" ) {
|
||||
$useBase64 = false;
|
||||
} else {
|
||||
$charset = Less_Mime::charsets_lookup( $mimetype );
|
||||
$useBase64 = !in_array( $charset, [ 'US-ASCII', 'UTF-8' ] );
|
||||
}
|
||||
if ( $useBase64 ) {
|
||||
$mimetype .= ';base64';
|
||||
}
|
||||
|
@ -952,27 +920,26 @@ class Less_Functions {
|
|||
$useBase64 = preg_match( '/;base64$/', $mimetype );
|
||||
}
|
||||
|
||||
if ( file_exists( $filePath ) ) {
|
||||
$buf = @file_get_contents( $filePath );
|
||||
} else {
|
||||
$buf = false;
|
||||
if ( !file_exists( $filePath ) ) {
|
||||
$fallback = new Less_Tree_Url( ( $filePathNode ?: $mimetypeNode ), $this->currentFileInfo );
|
||||
return $fallback->compile( $this->env );
|
||||
}
|
||||
$buf = @file_get_contents( $filePath );
|
||||
|
||||
$buf = $useBase64 ? base64_encode( $buf ) : rawurlencode( $buf );
|
||||
$url = "data:" . $mimetype . ',' . $buf . $fragment;
|
||||
|
||||
// IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
|
||||
// and the --ieCompat flag is enabled, return a normal url() instead.
|
||||
$DATA_URI_MAX_KB = 32;
|
||||
$fileSizeInKB = round( strlen( $buf ) / 1024 );
|
||||
if ( $fileSizeInKB >= $DATA_URI_MAX_KB ) {
|
||||
$url = new Less_Tree_Url( ( $filePathNode ?: $mimetypeNode ), $this->currentFileInfo );
|
||||
return $url->compile( $this->env );
|
||||
$DATA_URI_MAX_KB = 32768;
|
||||
if ( strlen( $buf ) >= $DATA_URI_MAX_KB ) {
|
||||
// NOTE: Less.js checks for ieCompat here (true by default).
|
||||
// For Less.php, ieCompat is not configurable, and always true.
|
||||
$fallback = new Less_Tree_Url( ( $filePathNode ?: $mimetypeNode ), $this->currentFileInfo );
|
||||
return $fallback->compile( $this->env );
|
||||
}
|
||||
|
||||
if ( $buf ) {
|
||||
$buf = $useBase64 ? base64_encode( $buf ) : rawurlencode( $buf );
|
||||
$filePath = '"data:' . $mimetype . ',' . $buf . '"';
|
||||
}
|
||||
|
||||
return new Less_Tree_Url( new Less_Tree_Anonymous( $filePath ) );
|
||||
return new Less_Tree_Url( new Less_Tree_Quoted( '"' . $url . '"', $url, false ) );
|
||||
}
|
||||
|
||||
// svg-gradient
|
||||
|
@ -985,7 +952,6 @@ class Less_Functions {
|
|||
|
||||
$gradientType = 'linear';
|
||||
$rectangleDimension = 'x="0" y="0" width="1" height="1"';
|
||||
$useBase64 = true;
|
||||
$directionValue = $direction->toCSS();
|
||||
|
||||
switch ( $directionValue ) {
|
||||
|
@ -1041,24 +1007,63 @@ class Less_Functions {
|
|||
|
||||
$returner .= '</' . $gradientType . 'Gradient><rect ' . $rectangleDimension . ' fill="url(#gradient)" /></svg>';
|
||||
|
||||
if ( $useBase64 ) {
|
||||
$returner = "'data:image/svg+xml;base64," . base64_encode( $returner ) . "'";
|
||||
} else {
|
||||
$returner = "'data:image/svg+xml," . $returner . "'";
|
||||
}
|
||||
$revert = [ '%21' => '!', '%2A' => '*', '%27' => "'", '%26' => '&', '%2C' => ',', '%40' => '@', '%2B' => '+', '%24' => '$', '%28' => '(', '%29' => ')' ];
|
||||
$returner = strtr( rawurlencode( $returner ), $revert );
|
||||
|
||||
return new Less_Tree_Url( new Less_Tree_Anonymous( $returner ) );
|
||||
$returner = "data:image/svg+xml," . $returner;
|
||||
|
||||
return new Less_Tree_Url( new Less_Tree_Quoted( "'" . $returner . "'", $returner, false ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Php version of javascript's `encodeURIComponent` function
|
||||
*
|
||||
* @param string $string The string to encode
|
||||
* @return string The encoded string
|
||||
* @see https://github.com/less/less.js/blob/v2.5.3/lib/less-node/image-size.js
|
||||
*/
|
||||
public static function encodeURIComponent( $string ) {
|
||||
$revert = [ '%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')' ];
|
||||
return strtr( rawurlencode( $string ), $revert );
|
||||
private function getImageSize( $filePathNode ) {
|
||||
$filePath = $filePathNode->value;
|
||||
|
||||
$filePath = str_replace( '\\', '/', $filePath );
|
||||
|
||||
[ $filePath ] = Less_FileManager::getFilePath( $filePath, $this->currentFileInfo );
|
||||
|
||||
$mimetype = Less_Mime::lookup( $filePath );
|
||||
|
||||
if ( $mimetype === "image/svg+xml" ) {
|
||||
return $this->getSvgSize( $filePath );
|
||||
}
|
||||
|
||||
[ $imagewidth, $imageheight ] = getimagesize( $filePath );
|
||||
|
||||
return [ "width" => $imagewidth, "height" => $imageheight ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/image-size/image-size/blob/main/lib/types/svg.ts
|
||||
*/
|
||||
private function getSvgSize( string $filePathNode ) {
|
||||
$xml = simplexml_load_string( file_get_contents( $filePathNode ) );
|
||||
$attributes = $xml->attributes();
|
||||
$width = (string)$attributes->width;
|
||||
$height = (string)$attributes->height;
|
||||
|
||||
return [ "width" => $width, "height" => $height ];
|
||||
}
|
||||
|
||||
public function imagesize( $filePathNode = null ) {
|
||||
$imagesize = $this->getImageSize( $filePathNode );
|
||||
return new Less_Tree_Expression( [
|
||||
new Less_Tree_Dimension( $imagesize["width"], "px" ),
|
||||
new Less_Tree_Dimension( $imagesize["height"], "px" )
|
||||
] );
|
||||
}
|
||||
|
||||
public function imagewidth( $filePathNode = null ) {
|
||||
$imagesize = $this->getImageSize( $filePathNode );
|
||||
return new Less_Tree_Dimension( $imagesize["width"], "px" );
|
||||
}
|
||||
|
||||
public function imageheight( $filePathNode = null ) {
|
||||
$imagesize = $this->getImageSize( $filePathNode );
|
||||
return new Less_Tree_Dimension( $imagesize["height"], "px" );
|
||||
}
|
||||
|
||||
// Color Blending
|
||||
|
@ -1211,7 +1216,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
// non-w3c functions:
|
||||
public function colorBlendAverage( $cb, $cs ) {
|
||||
private function colorBlendAverage( $cb, $cs ) {
|
||||
return ( $cb + $cs ) / 2;
|
||||
}
|
||||
|
||||
|
@ -1226,7 +1231,7 @@ class Less_Functions {
|
|||
return $this->colorBlend( [ $this, 'colorBlendNegation' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
public function colorBlendNegation( $cb, $cs ) {
|
||||
private function colorBlendNegation( $cb, $cs ) {
|
||||
return 1 - abs( $cb + $cs - 1 );
|
||||
}
|
||||
|
||||
|
|
267
include/thirdparty/less.php/ImportVisitor.php
vendored
Normal file
267
include/thirdparty/less.php/ImportVisitor.php
vendored
Normal file
|
@ -0,0 +1,267 @@
|
|||
<?php
|
||||
|
||||
class Less_ImportVisitor extends Less_Visitor {
|
||||
|
||||
public $env;
|
||||
public $variableImports = [];
|
||||
public $recursionDetector = [];
|
||||
|
||||
public $_currentDepth = 0;
|
||||
public $importItem;
|
||||
|
||||
public function __construct( $env ) {
|
||||
parent::__construct();
|
||||
// NOTE: Upstream creates a new environment/context here. We re-use the main one instead.
|
||||
// This makes Less_Environment->addParsedFile() easier to support (which is custom to Less.php)
|
||||
$this->env = $env;
|
||||
// NOTE: Upstream `importCount` is not here, appears unused.
|
||||
// NOTE: Upstream `isFinished` is not here, we simply call tryRun() once at the end.
|
||||
// NOTE: Upstream `onceFileDetectionMap` is instead Less_Environment->isFileParsed.
|
||||
// NOTE: Upstream `ImportSequencer` logic is directly inside ImportVisitor for simplicity.
|
||||
}
|
||||
|
||||
public function run( $root ) {
|
||||
$this->visitObj( $root );
|
||||
$this->tryRun();
|
||||
}
|
||||
|
||||
public function visitImport( $importNode, &$visitDeeper ) {
|
||||
$inlineCSS = $importNode->options['inline'];
|
||||
|
||||
if ( !$importNode->css || $inlineCSS ) {
|
||||
|
||||
$env = $this->env->clone();
|
||||
$importParent = $env->frames[0];
|
||||
if ( $importNode->isVariableImport() ) {
|
||||
$this->addVariableImport( [
|
||||
'function' => 'processImportNode',
|
||||
'args' => [ $importNode, $env, $importParent ]
|
||||
] );
|
||||
} else {
|
||||
$this->processImportNode( $importNode, $env, $importParent );
|
||||
}
|
||||
}
|
||||
$visitDeeper = false;
|
||||
}
|
||||
|
||||
public function processImportNode( $importNode, $env, &$importParent ) {
|
||||
$evaldImportNode = $inlineCSS = $importNode->options['inline'];
|
||||
|
||||
try {
|
||||
$evaldImportNode = $importNode->compileForImport( $env );
|
||||
} catch ( Exception $e ) {
|
||||
$importNode->css = true;
|
||||
}
|
||||
|
||||
if ( $evaldImportNode && ( !$evaldImportNode->css || $inlineCSS ) ) {
|
||||
|
||||
if ( $importNode->options['multiple'] ) {
|
||||
$env->importMultiple = true;
|
||||
}
|
||||
|
||||
$tryAppendLessExtension = $evaldImportNode->css === null;
|
||||
|
||||
for ( $i = 0; $i < count( $importParent->rules ); $i++ ) {
|
||||
if ( $importParent->rules[$i] === $importNode ) {
|
||||
$importParent->rules[$i] = $evaldImportNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Rename $evaldImportNode to $importNode here so that we avoid avoid mistaken use
|
||||
// of not-yet-compiled $importNode after this point, which upstream's code doesn't
|
||||
// have access to after this point, either.
|
||||
$importNode = $evaldImportNode;
|
||||
unset( $evaldImportNode );
|
||||
|
||||
// NOTE: Upstream Less.js's ImportVisitor puts the rest of the processImportNode logic
|
||||
// into a separate ImportVisitor.prototype.onImported function, because file loading
|
||||
// is async there. They implement and call:
|
||||
//
|
||||
// - ImportSequencer.prototype.addImport:
|
||||
// remembers what processImportNode() was doing, and will call onImported
|
||||
// once the async file load is finished.
|
||||
// - ImportManager.prototype.push:
|
||||
// resolves the import path to full path and uri,
|
||||
// then parses the file content into a root Ruleset for that file.
|
||||
// - ImportVisitor.prototype.onImported:
|
||||
// marks the file as parsed (for skipping duplicates, to avoid recursion),
|
||||
// and calls tryRun() if this is the last remaining import.
|
||||
//
|
||||
// In PHP we load files synchronously, so we can put a simpler version of this
|
||||
// logic directly here.
|
||||
|
||||
// @see less-2.5.3.js#ImportManager.prototype.push
|
||||
|
||||
// NOTE: This is the equivalent to upstream `newFileInfo` and `fileManager.getPath()`
|
||||
|
||||
$path = $importNode->getPath();
|
||||
|
||||
if ( $tryAppendLessExtension ) {
|
||||
$path = preg_match( '/(\.[a-z]*$)|([\?;].*)$/', $path ) ? $path : $path . '.less';
|
||||
}
|
||||
|
||||
$path_and_uri = $env->callImportCallback( $importNode );
|
||||
if ( !$path_and_uri ) {
|
||||
$path_and_uri = Less_FileManager::getFilePath( $path, $importNode->currentFileInfo );
|
||||
}
|
||||
if ( $path_and_uri ) {
|
||||
[ $full_path, $uri ] = $path_and_uri;
|
||||
} else {
|
||||
$full_path = $uri = $importNode->getPath();
|
||||
}
|
||||
'@phan-var string $full_path';
|
||||
|
||||
// @see less-2.5.3.js#ImportManager.prototype.push/loadFileCallback
|
||||
|
||||
// NOTE: Upstream creates the next `currentFileInfo` here as `newFileInfo`
|
||||
// We instead let Less_Parser::SetFileInfo() do that later via Less_Parser::parseFile().
|
||||
// This means that instead of setting `newFileInfo.reference` we modify the $env,
|
||||
// and Less_Parser::SetFileInfo will inherit that.
|
||||
if ( $importNode->options['reference'] ?? false ) {
|
||||
$env->currentFileInfo['reference'] = true;
|
||||
}
|
||||
|
||||
$e = null;
|
||||
try {
|
||||
if ( $importNode->options['inline'] ) {
|
||||
if ( !file_exists( $full_path ) ) {
|
||||
throw new Less_Exception_Parser(
|
||||
sprintf( 'File `%s` not found.', $full_path ),
|
||||
null,
|
||||
$importNode->index,
|
||||
$importNode->currentFileInfo
|
||||
);
|
||||
}
|
||||
$root = file_get_contents( $full_path );
|
||||
} else {
|
||||
$parser = new Less_Parser( $env );
|
||||
// NOTE: Upstream sets `env->processImports = false` here to avoid
|
||||
// running ImportVisitor again (infinite loop). We instead separate
|
||||
// Less_Parser->parseFile() from Less_Parser->getCss(),
|
||||
// and only getCss() runs ImportVisitor.
|
||||
$root = $parser->parseFile( $full_path, $uri, true );
|
||||
}
|
||||
} catch ( Less_Exception_Parser $err ) {
|
||||
$e = $err;
|
||||
}
|
||||
|
||||
// @see less-2.5.3.js#ImportManager.prototype.push/fileParsedFunc
|
||||
|
||||
if ( $importNode->options['optional'] && $e ) {
|
||||
$e = null;
|
||||
$root = new Less_Tree_Ruleset( null, [] );
|
||||
$full_path = null;
|
||||
}
|
||||
|
||||
// @see less-2.5.3.js#ImportVisitor.prototype.onImported
|
||||
|
||||
if ( $e instanceof Less_Exception_Parser ) {
|
||||
if ( !is_numeric( $e->index ) ) {
|
||||
$e->index = $importNode->index;
|
||||
$e->currentFile = $importNode->currentFileInfo;
|
||||
$e->genMessage();
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$duplicateImport = isset( $this->recursionDetector[$full_path] );
|
||||
|
||||
if ( !$env->importMultiple ) {
|
||||
if ( $duplicateImport ) {
|
||||
$importNode->doSkip = true;
|
||||
} else {
|
||||
// NOTE: Upstream implements skip() as dynamic function.
|
||||
// We instead have a regular Less_Tree_Import::skip() method,
|
||||
// and in cases where skip() would be re-defined here we set doSkip=null.
|
||||
$importNode->doSkip = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$full_path && $importNode->options['optional'] ) {
|
||||
$importNode->doSkip = true;
|
||||
}
|
||||
|
||||
if ( $root ) {
|
||||
$importNode->root = $root;
|
||||
$importNode->importedFilename = $full_path;
|
||||
|
||||
if ( !$inlineCSS && ( $env->importMultiple || !$duplicateImport ) && $full_path ) {
|
||||
$this->recursionDetector[$full_path] = true;
|
||||
$oldContext = $this->env;
|
||||
$this->env = $env;
|
||||
$this->visitObj( $root );
|
||||
$this->env = $oldContext;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->tryRun();
|
||||
}
|
||||
}
|
||||
|
||||
public function addVariableImport( $callback ) {
|
||||
$this->variableImports[] = $callback;
|
||||
}
|
||||
|
||||
public function tryRun() {
|
||||
while ( true ) {
|
||||
// NOTE: Upstream keeps a `this.imports` queue here that resumes
|
||||
// processImportNode() logic by calling onImported() after a file
|
||||
// is finished loading. We don't need that since we load and parse
|
||||
// synchronously within processImportNode() instead.
|
||||
|
||||
if ( count( $this->variableImports ) === 0 ) {
|
||||
break;
|
||||
}
|
||||
$variableImport = $this->variableImports[0];
|
||||
|
||||
$this->variableImports = array_slice( $this->variableImports, 1 );
|
||||
$function = $variableImport['function'];
|
||||
|
||||
$this->$function( ...$variableImport["args"] );
|
||||
}
|
||||
}
|
||||
|
||||
public function visitRule( $ruleNode, $visitDeeper ) {
|
||||
// TODO: We might need upstream's `if (… DetachedRuleset) { this.context.frames.unshift(ruleNode); }`
|
||||
$visitDeeper = false;
|
||||
}
|
||||
|
||||
// TODO: We might need upstream's visitRuleOut()
|
||||
// if (… DetachedRuleset) { this.context.frames.shift(); }
|
||||
|
||||
public function visitDirective( $directiveNode, $visitArgs ) {
|
||||
array_unshift( $this->env->frames, $directiveNode );
|
||||
}
|
||||
|
||||
public function visitDirectiveOut( $directiveNode ) {
|
||||
array_shift( $this->env->frames );
|
||||
}
|
||||
|
||||
public function visitMixinDefinition( $mixinDefinitionNode, $visitArgs ) {
|
||||
array_unshift( $this->env->frames, $mixinDefinitionNode );
|
||||
}
|
||||
|
||||
public function visitMixinDefinitionOut( $mixinDefinitionNode ) {
|
||||
array_shift( $this->env->frames );
|
||||
}
|
||||
|
||||
public function visitRuleset( $rulesetNode, $visitArgs ) {
|
||||
array_unshift( $this->env->frames, $rulesetNode );
|
||||
}
|
||||
|
||||
public function visitRulesetOut( $rulesetNode ) {
|
||||
array_shift( $this->env->frames );
|
||||
}
|
||||
|
||||
public function visitMedia( $mediaNode, $visitArgs ) {
|
||||
// TODO: Upsteam does not modify $mediaNode here. Why do we?
|
||||
$mediaNode->allExtends = [];
|
||||
array_unshift( $this->env->frames, $mediaNode->allExtends );
|
||||
}
|
||||
|
||||
public function visitMediaOut( $mediaNode ) {
|
||||
array_shift( $this->env->frames );
|
||||
}
|
||||
|
||||
}
|
734
include/thirdparty/less.php/Parser.php
vendored
734
include/thirdparty/less.php/Parser.php
vendored
File diff suppressed because it is too large
Load diff
5
include/thirdparty/less.php/README.md
vendored
5
include/thirdparty/less.php/README.md
vendored
|
@ -43,10 +43,11 @@ _See also [SECURITY](./SECURITY.md)._
|
|||
## Who uses Less.php?
|
||||
|
||||
* **[Wikipedia](https://en.wikipedia.org/wiki/MediaWiki)** and the MediaWiki platform ([docs](https://www.mediawiki.org/wiki/ResourceLoader/Architecture#Resource:_Styles)).
|
||||
* **[Matomo](https://en.wikipedia.org/wiki/Matomo_(software))** ([docs](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/css-topics/custom_preprocess.html)).
|
||||
* **[Magento](https://en.wikipedia.org/wiki/Magento)** as part of Adobe Commerce ([docs](https://developer.matomo.org/guides/asset-pipeline#vanilla-javascript-css-and-less-files)).
|
||||
* **[Matomo](https://en.wikipedia.org/wiki/Matomo_(software))** ([docs](https://developer.matomo.org/guides/asset-pipeline#vanilla-javascript-css-and-less-files)).
|
||||
* **[Magento](https://en.wikipedia.org/wiki/Magento)** as part of Adobe Commerce ([docs](https://developer.adobe.com/commerce/frontend-core/guide/css/preprocess/)).
|
||||
* **[Icinga](https://en.wikipedia.org/wiki/Icinga)** in Icinga Web ([docs](https://github.com/Icinga/icingaweb2)).
|
||||
* **[Shopware](https://de.wikipedia.org/wiki/Shopware)** ([docs](https://developers.shopware.com/designers-guide/less/)).
|
||||
* **[Winter CMS](https://wintercms.com/)** ([docs](https://wintercms.com/docs/v1.2/docs/themes/development))
|
||||
|
||||
## Integrations
|
||||
|
||||
|
|
|
@ -95,6 +95,17 @@ class Less_SourceMap_Generator extends Less_Configurable {
|
|||
$this->options['sourceMapBasepath'] = $this->fixWindowsPath( $this->options['sourceMapBasepath'], true );
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP version of JavaScript's `encodeURIComponent` function
|
||||
*
|
||||
* @param string $string The string to encode
|
||||
* @return string The encoded string
|
||||
*/
|
||||
private static function encodeURIComponent( $string ) {
|
||||
$revert = [ '%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')' ];
|
||||
return strtr( rawurlencode( $string ), $revert );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the CSS
|
||||
*
|
||||
|
@ -122,7 +133,7 @@ class Less_SourceMap_Generator extends Less_Configurable {
|
|||
|
||||
// inline the map
|
||||
if ( !$sourceMapUrl ) {
|
||||
$sourceMapUrl = sprintf( 'data:application/json,%s', Less_Functions::encodeURIComponent( $sourceMapContent ) );
|
||||
$sourceMapUrl = sprintf( 'data:application/json,%s', self::encodeURIComponent( $sourceMapContent ) );
|
||||
}
|
||||
|
||||
if ( $sourceMapUrl ) {
|
||||
|
|
67
include/thirdparty/less.php/Tree.php
vendored
67
include/thirdparty/less.php/Tree.php
vendored
|
@ -9,6 +9,9 @@ class Less_Tree {
|
|||
public $extendOnEveryPath;
|
||||
public $allExtends;
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#Node.prototype.toCSS
|
||||
*/
|
||||
public function toCSS() {
|
||||
$output = new Less_Output();
|
||||
$this->genCSS( $output );
|
||||
|
@ -28,6 +31,41 @@ class Less_Tree {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $op
|
||||
* @param float $a
|
||||
* @param float $b
|
||||
* @see less-2.5.3.js#Node.prototype._operate
|
||||
*/
|
||||
protected function _operate( $op, $a, $b ) {
|
||||
switch ( $op ) {
|
||||
case '+':
|
||||
return $a + $b;
|
||||
case '-':
|
||||
return $a - $b;
|
||||
case '*':
|
||||
return $a * $b;
|
||||
case '/':
|
||||
return $a / $b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#Node.prototype.fround
|
||||
*/
|
||||
protected function fround( $value ) {
|
||||
if ( $value === 0 ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// TODO: Migrate to passing $env.
|
||||
if ( Less_Parser::$options['numPrecision'] ) {
|
||||
$p = pow( 10, Less_Parser::$options['numPrecision'] );
|
||||
return round( $value * $p ) / $p;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Output $output
|
||||
* @param Less_Tree_Ruleset[] $rules
|
||||
|
@ -72,16 +110,27 @@ class Less_Tree {
|
|||
*/
|
||||
public static function nodeCompare( $a, $b ) {
|
||||
// Less_Tree subclasses that implement compare() are:
|
||||
// Anonymous, Color, Dimension, Keyword, Quoted, Unit
|
||||
if ( $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Anonymous ) {
|
||||
// Anonymous, Color, Dimension, Quoted, Unit
|
||||
$aHasCompare = ( $a instanceof Less_Tree_Anonymous || $a instanceof Less_Tree_Color
|
||||
|| $a instanceof Less_Tree_Dimension || $a instanceof Less_Tree_Quoted || $a instanceof Less_Tree_Unit
|
||||
);
|
||||
$bHasCompare = ( $b instanceof Less_Tree_Anonymous || $b instanceof Less_Tree_Color
|
||||
|| $b instanceof Less_Tree_Dimension || $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Unit
|
||||
);
|
||||
|
||||
if ( $aHasCompare &&
|
||||
!( $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Anonymous )
|
||||
) {
|
||||
// for "symmetric results" force toCSS-based comparison via b.compare()
|
||||
// of Quoted or Anonymous if either value is one of those
|
||||
return -$b->compare( $a );
|
||||
} elseif ( $a instanceof Less_Tree_Anonymous || $a instanceof Less_Tree_Color
|
||||
|| $a instanceof Less_Tree_Dimension || $a instanceof Less_Tree_Keyword
|
||||
|| $a instanceof Less_Tree_Quoted || $a instanceof Less_Tree_Unit
|
||||
) {
|
||||
// @phan-suppress-next-line PhanUndeclaredMethod
|
||||
return $a->compare( $b );
|
||||
} elseif ( $bHasCompare ) {
|
||||
$res = $b->compare( $a );
|
||||
// In JS, `-undefined` produces NAN, which, just like undefined
|
||||
// will enter the the default/false branch of Less_Tree_Condition#compile.
|
||||
// In PHP, `-null` is 0. To ensure parity, preserve the null.
|
||||
return $res !== null ? -$res : null;
|
||||
} elseif ( get_class( $a ) !== get_class( $b ) ) {
|
||||
return null;
|
||||
}
|
||||
|
@ -89,11 +138,12 @@ class Less_Tree {
|
|||
// Less_Tree subclasses that have an array value: Less_Tree_Expression, Less_Tree_Value
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty
|
||||
$aval = $a->value ?? [];
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty
|
||||
$bval = $b->value ?? [];
|
||||
if ( !( $a instanceof Less_Tree_Expression || $a instanceof Less_Tree_Value ) ) {
|
||||
return $aval === $bval ? 0 : null;
|
||||
}
|
||||
'@phan-var Less_Tree[] $aval';
|
||||
'@phan-var Less_Tree[] $bval';
|
||||
if ( count( $aval ) !== count( $bval ) ) {
|
||||
return null;
|
||||
}
|
||||
|
@ -124,7 +174,6 @@ class Less_Tree {
|
|||
public static function ReferencedArray( $rules ) {
|
||||
foreach ( $rules as $rule ) {
|
||||
if ( method_exists( $rule, 'markReferenced' ) ) {
|
||||
// @phan-suppress-next-line PhanUndeclaredMethod
|
||||
$rule->markReferenced();
|
||||
}
|
||||
}
|
||||
|
|
32
include/thirdparty/less.php/Tree/Alpha.php
vendored
32
include/thirdparty/less.php/Tree/Alpha.php
vendored
|
@ -1,43 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Alpha.prototype
|
||||
*/
|
||||
class Less_Tree_Alpha extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* @param string|Less_Tree $val This receives string or Less_Tree_Variable
|
||||
* from Less_Parser. In compile(), Less_Tree_Variable is replaced with a
|
||||
* different node (e.g. Less_Tree_Quoted).
|
||||
*/
|
||||
public function __construct( $val ) {
|
||||
$this->value = $val;
|
||||
}
|
||||
|
||||
// function accept( $visitor ){
|
||||
// $this->value = $visitor->visit( $this->value );
|
||||
//}
|
||||
public function accept( $visitor ) {
|
||||
if ( $this->value instanceof Less_Tree ) {
|
||||
$this->value = $visitor->visitObj( $this->value );
|
||||
}
|
||||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
if ( is_object( $this->value ) ) {
|
||||
$this->value = $this->value->compile( $env );
|
||||
if ( $this->value instanceof Less_Tree ) {
|
||||
return new self( $this->value->compile( $env ) );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( "alpha(opacity=" );
|
||||
|
||||
if ( is_string( $this->value ) ) {
|
||||
$output->add( $this->value );
|
||||
} else {
|
||||
if ( $this->value instanceof Less_Tree ) {
|
||||
$this->value->genCSS( $output );
|
||||
} else {
|
||||
$output->add( $this->value );
|
||||
}
|
||||
|
||||
$output->add( ')' );
|
||||
}
|
||||
|
||||
public function toCSS() {
|
||||
return "alpha(opacity=" . ( is_string( $this->value ) ? $this->value : $this->value->toCSS() ) . ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
17
include/thirdparty/less.php/Tree/Anonymous.php
vendored
17
include/thirdparty/less.php/Tree/Anonymous.php
vendored
|
@ -11,6 +11,7 @@ class Less_Tree_Anonymous extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
public $currentFileInfo;
|
||||
/** @var bool */
|
||||
public $rulesetLike;
|
||||
public $isReferenced;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
|
@ -18,17 +19,19 @@ class Less_Tree_Anonymous extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
* @param array|null $currentFileInfo
|
||||
* @param bool|null $mapLines
|
||||
* @param bool $rulesetLike
|
||||
* @param bool $referenced
|
||||
*/
|
||||
public function __construct( $value, $index = null, $currentFileInfo = null, $mapLines = null, $rulesetLike = false ) {
|
||||
public function __construct( $value, $index = null, $currentFileInfo = null, $mapLines = null, $rulesetLike = false, $referenced = false ) {
|
||||
$this->value = $value;
|
||||
$this->index = $index;
|
||||
$this->mapLines = $mapLines;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
$this->rulesetLike = $rulesetLike;
|
||||
$this->isReferenced = $referenced;
|
||||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
return new self( $this->value, $this->index, $this->currentFileInfo, $this->mapLines );
|
||||
return new self( $this->value, $this->index, $this->currentFileInfo, $this->mapLines, $this->rulesetLike, $this->isReferenced );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,15 +47,15 @@ class Less_Tree_Anonymous extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
return $this->rulesetLike;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( $this->value, $this->currentFileInfo, $this->index, $this->mapLines );
|
||||
}
|
||||
|
||||
public function toCSS() {
|
||||
return $this->value;
|
||||
public function markReferenced() {
|
||||
$this->isReferenced = true;
|
||||
}
|
||||
|
||||
public function getIsReferenced() {
|
||||
return !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] || $this->isReferenced;
|
||||
}
|
||||
}
|
||||
|
|
13
include/thirdparty/less.php/Tree/Assignment.php
vendored
13
include/thirdparty/less.php/Tree/Assignment.php
vendored
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Assignment.prototype
|
||||
*/
|
||||
class Less_Tree_Assignment extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $key;
|
||||
public $value;
|
||||
|
||||
public function __construct( $key, $val ) {
|
||||
public function __construct( string $key, Less_Tree $val ) {
|
||||
$this->key = $key;
|
||||
$this->value = $val;
|
||||
}
|
||||
|
@ -17,18 +17,13 @@ class Less_Tree_Assignment extends Less_Tree implements Less_Tree_HasValueProper
|
|||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
// NOTE: Less.js has a conditional for $this->value,
|
||||
// but this appears unreachable ($val is not optional).
|
||||
return new self( $this->key, $this->value->compile( $env ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( $this->key . '=' );
|
||||
$this->value->genCSS( $output );
|
||||
}
|
||||
|
||||
public function toCss() {
|
||||
return $this->key . '=' . $this->value->toCSS();
|
||||
}
|
||||
}
|
||||
|
|
21
include/thirdparty/less.php/Tree/Attribute.php
vendored
21
include/thirdparty/less.php/Tree/Attribute.php
vendored
|
@ -1,13 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Attribute.prototype
|
||||
*/
|
||||
class Less_Tree_Attribute extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $key;
|
||||
public $op;
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param null|string $op
|
||||
* @param null|string|Less_Tree $value
|
||||
*/
|
||||
public function __construct( $key, $op, $value ) {
|
||||
$this->key = $key;
|
||||
$this->op = $op;
|
||||
|
@ -15,22 +20,18 @@ class Less_Tree_Attribute extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
$key_obj = is_object( $this->key );
|
||||
$val_obj = is_object( $this->value );
|
||||
|
||||
if ( !$key_obj && !$val_obj ) {
|
||||
// Optimization: Avoid object churn for the common case.
|
||||
// Attributes are very common in CSS/LESS input, but rarely involve dynamic values.
|
||||
if ( !$this->key instanceof Less_Tree && !$this->value instanceof Less_Tree ) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return new self(
|
||||
$key_obj ? $this->key->compile( $env ) : $this->key,
|
||||
$this->key instanceof Less_Tree ? $this->key->compile( $env ) : $this->key,
|
||||
$this->op,
|
||||
$val_obj ? $this->value->compile( $env ) : $this->value );
|
||||
$this->value instanceof Less_Tree ? $this->value->compile( $env ) : $this->value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( $this->toCSS() );
|
||||
}
|
||||
|
|
63
include/thirdparty/less.php/Tree/Call.php
vendored
63
include/thirdparty/less.php/Tree/Call.php
vendored
|
@ -25,6 +25,27 @@ class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
$this->args = $visitor->visitArray( $this->args );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#functionCaller.prototype.call
|
||||
*/
|
||||
private function functionCaller( $function, array $arguments ) {
|
||||
// This code is terrible and should be replaced as per this issue...
|
||||
// https://github.com/less/less.js/issues/2477
|
||||
$filtered = [];
|
||||
foreach ( $arguments as $argument ) {
|
||||
if ( $argument instanceof Less_Tree_Comment ) {
|
||||
continue;
|
||||
}
|
||||
$filtered[] = $argument;
|
||||
}
|
||||
foreach ( $filtered as $index => $argument ) {
|
||||
if ( $argument instanceof Less_Tree_Expression ) {
|
||||
$filtered[$index] = $argument->mapToFunctionCallArgument();
|
||||
}
|
||||
}
|
||||
return $function( ...$filtered );
|
||||
}
|
||||
|
||||
//
|
||||
// When evaluating a function call,
|
||||
// we either find the function in Less_Functions,
|
||||
|
@ -36,28 +57,17 @@ class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
// like: `saturate(@mycolor)`.
|
||||
// The function should receive the value, not the variable.
|
||||
//
|
||||
public function compile( $env = null ) {
|
||||
public function compile( $env ) {
|
||||
// Turn off math for calc(). https://phabricator.wikimedia.org/T331688
|
||||
$currentMathContext = Less_Environment::$mathOn;
|
||||
Less_Environment::$mathOn = $this->mathOn;
|
||||
$currentMathContext = $env->strictMath;
|
||||
$env->strictMath = !$this->mathOn;
|
||||
|
||||
$args = [];
|
||||
foreach ( $this->args as $a ) {
|
||||
$args[] = $a->compile( $env );
|
||||
}
|
||||
|
||||
foreach ( $args as $key => $arg ) {
|
||||
if ( $arg instanceof Less_Tree_Expression ) {
|
||||
$arg->throwAwayComments();
|
||||
|
||||
if ( count( $arg->value ) === 1 ) {
|
||||
$subNode = $arg->value[0];
|
||||
array_splice( $args, $key, 1, [ $subNode ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Less_Environment::$mathOn = $currentMathContext;
|
||||
$env->strictMath = $currentMathContext;
|
||||
|
||||
$nameLC = strtolower( $this->name );
|
||||
switch ( $nameLC ) {
|
||||
|
@ -76,6 +86,15 @@ class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
case 'svg-gradient':
|
||||
$nameLC = 'svggradient';
|
||||
break;
|
||||
case 'image-size':
|
||||
$nameLC = 'imagesize';
|
||||
break;
|
||||
case 'image-width':
|
||||
$nameLC = 'imagewidth';
|
||||
break;
|
||||
case 'image-height':
|
||||
$nameLC = 'imageheight';
|
||||
break;
|
||||
}
|
||||
|
||||
$result = null;
|
||||
|
@ -83,16 +102,18 @@ class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
$result = Less_Tree_DefaultFunc::compile();
|
||||
} else {
|
||||
$func = null;
|
||||
if ( method_exists( Less_Functions::class, $nameLC ) ) {
|
||||
$functions = new Less_Functions( $env, $this->currentFileInfo );
|
||||
$func = [ $functions, $nameLC ];
|
||||
$functions = new Less_Functions( $env, $this->currentFileInfo );
|
||||
$funcBuiltin = [ $functions, $nameLC ];
|
||||
// Avoid method_exists() as that considers private utility functions too
|
||||
if ( is_callable( $funcBuiltin ) ) {
|
||||
$func = $funcBuiltin;
|
||||
} elseif ( isset( $env->functions[$nameLC] ) && is_callable( $env->functions[$nameLC] ) ) {
|
||||
$func = $env->functions[$nameLC];
|
||||
}
|
||||
// If the function name isn't known to LESS, output it unchanged as CSS.
|
||||
if ( $func ) {
|
||||
try {
|
||||
$result = $func( ...$args );
|
||||
$result = $this->functionCaller( $func, $args );
|
||||
} catch ( Exception $e ) {
|
||||
// Preserve original trace, especially from custom functions.
|
||||
// https://github.com/wikimedia/less.php/issues/38
|
||||
|
@ -128,8 +149,4 @@ class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
$output->add( ')' );
|
||||
}
|
||||
|
||||
// public function toCSS(){
|
||||
// return $this->compile()->toCSS();
|
||||
//}
|
||||
|
||||
}
|
||||
|
|
18
include/thirdparty/less.php/Tree/Color.php
vendored
18
include/thirdparty/less.php/Tree/Color.php
vendored
|
@ -55,7 +55,7 @@ class Less_Tree_Color extends Less_Tree {
|
|||
|
||||
public function toCSS( $doNotCompress = false ) {
|
||||
$compress = Less_Parser::$options['compress'] && !$doNotCompress;
|
||||
$alpha = Less_Functions::fround( $this->alpha );
|
||||
$alpha = $this->fround( $this->alpha );
|
||||
if ( $this->value ) {
|
||||
return $this->value;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ class Less_Tree_Color extends Less_Tree {
|
|||
|
||||
$values = [];
|
||||
foreach ( $this->rgb as $c ) {
|
||||
$values[] = Less_Functions::clamp( round( $c ), 255 );
|
||||
$values[] = $this->clamp( round( $c ), 255 );
|
||||
}
|
||||
$values[] = $alpha;
|
||||
|
||||
|
@ -109,7 +109,7 @@ class Less_Tree_Color extends Less_Tree {
|
|||
$rgb = [];
|
||||
$alpha = $this->alpha * ( 1 - $other->alpha ) + $other->alpha;
|
||||
for ( $c = 0; $c < 3; $c++ ) {
|
||||
$rgb[$c] = Less_Functions::operate( $op, $this->rgb[$c], $other->rgb[$c] );
|
||||
$rgb[$c] = $this->_operate( $op, $this->rgb[$c], $other->rgb[$c] );
|
||||
}
|
||||
return new self( $rgb, $alpha );
|
||||
}
|
||||
|
@ -207,10 +207,20 @@ class Less_Tree_Color extends Less_Tree {
|
|||
$x->alpha === $this->alpha ) ? 0 : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|float $val
|
||||
* @param int $max
|
||||
* @return int|float
|
||||
* @see less-2.5.3.js#Color.prototype
|
||||
*/
|
||||
private function clamp( $val, $max ) {
|
||||
return min( max( $val, 0 ), $max );
|
||||
}
|
||||
|
||||
public function toHex( $v ) {
|
||||
$ret = '#';
|
||||
foreach ( $v as $c ) {
|
||||
$c = Less_Functions::clamp( Less_Parser::round( $c ), 255 );
|
||||
$c = $this->clamp( Less_Parser::round( $c ), 255 );
|
||||
if ( $c < 16 ) {
|
||||
$ret .= '0';
|
||||
}
|
||||
|
|
24
include/thirdparty/less.php/Tree/Comment.php
vendored
24
include/thirdparty/less.php/Tree/Comment.php
vendored
|
@ -1,38 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Comment.prototype
|
||||
*/
|
||||
class Less_Tree_Comment extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $value;
|
||||
public $silent;
|
||||
public $isLineComment;
|
||||
public $isReferenced;
|
||||
public $currentFileInfo;
|
||||
|
||||
public function __construct( $value, $silent, $index = null, $currentFileInfo = null ) {
|
||||
public function __construct( $value, $isLineComment, $index = null, $currentFileInfo = null ) {
|
||||
$this->value = $value;
|
||||
$this->silent = (bool)$silent;
|
||||
$this->isLineComment = (bool)$isLineComment;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
// if( $this->debugInfo ){
|
||||
//$output->add( tree.debugInfo($env, $this), $this->currentFileInfo, $this->index);
|
||||
//}
|
||||
$output->add( trim( $this->value ) );// TODO shouldn't need to trim, we shouldn't grab the \n
|
||||
}
|
||||
// NOTE: Skip debugInfo handling (not implemented)
|
||||
|
||||
public function toCSS() {
|
||||
return Less_Parser::$options['compress'] ? '' : $this->value;
|
||||
$output->add( $this->value );
|
||||
}
|
||||
|
||||
public function isSilent() {
|
||||
$isReference = ( $this->currentFileInfo && isset( $this->currentFileInfo['reference'] ) && ( !isset( $this->isReferenced ) || !$this->isReferenced ) );
|
||||
$isCompressed = Less_Parser::$options['compress'] && !preg_match( '/^\/\*!/', $this->value );
|
||||
return $this->silent || $isReference || $isCompressed;
|
||||
$isCompressed = Less_Parser::$options['compress'] && ( $this->value[2] ?? '' ) !== "!";
|
||||
return $this->isLineComment || $isReference || $isCompressed;
|
||||
}
|
||||
|
||||
public function markReferenced() {
|
||||
|
|
25
include/thirdparty/less.php/Tree/Condition.php
vendored
25
include/thirdparty/less.php/Tree/Condition.php
vendored
|
@ -42,20 +42,19 @@ class Less_Tree_Condition extends Less_Tree {
|
|||
break;
|
||||
|
||||
default:
|
||||
switch ( Less_Tree::nodeCompare( $a, $b ) ) {
|
||||
case -1:
|
||||
$result = $this->op === '<' || $this->op === '=<' || $this->op === '<=';
|
||||
break;
|
||||
case 0:
|
||||
$result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<=';
|
||||
break;
|
||||
case 1:
|
||||
$result = $this->op === '>' || $this->op === '>=';
|
||||
break;
|
||||
default:
|
||||
$result = false;
|
||||
$res = Less_Tree::nodeCompare( $a, $b );
|
||||
// In JS, switch(undefined) with -1,0,-1,defaults goes to `default`.
|
||||
// In PHP, switch(null) would go to case 0. Use if/else instead.
|
||||
if ( $res === -1 ) {
|
||||
$result = $this->op === '<' || $this->op === '=<' || $this->op === '<=';
|
||||
} elseif ( $res === 0 ) {
|
||||
$result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<=';
|
||||
} elseif ( $res === 1 ) {
|
||||
$result = $this->op === '>' || $this->op === '>=';
|
||||
} else {
|
||||
// null, NAN
|
||||
$result = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->negate ? !$result : $result;
|
||||
|
|
18
include/thirdparty/less.php/Tree/Dimension.php
vendored
18
include/thirdparty/less.php/Tree/Dimension.php
vendored
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Dimension.prototype
|
||||
*/
|
||||
class Less_Tree_Dimension extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
|
@ -36,7 +37,7 @@ class Less_Tree_Dimension extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
throw new Less_Exception_Compiler( "Multiple units in dimension. Correct the units or use the unit function. Bad unit: " . $this->unit->toString() );
|
||||
}
|
||||
|
||||
$value = Less_Functions::fround( $this->value );
|
||||
$value = $this->fround( $this->value );
|
||||
$strValue = (string)$value;
|
||||
|
||||
if ( $value !== 0 && $value < 0.000001 && $value > -0.000001 ) {
|
||||
|
@ -75,14 +76,15 @@ class Less_Tree_Dimension extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
* @param self $other
|
||||
*/
|
||||
public function operate( $op, $other ) {
|
||||
$value = Less_Functions::operate( $op, $this->value, $other->value );
|
||||
$unit = clone $this->unit;
|
||||
$value = $this->_operate( $op, $this->value, $other->value );
|
||||
$unit = $this->unit->clone();
|
||||
|
||||
if ( $op === '+' || $op === '-' ) {
|
||||
|
||||
if ( !$unit->numerator && !$unit->denominator ) {
|
||||
$unit->numerator = $other->unit->numerator;
|
||||
$unit->denominator = $other->unit->denominator;
|
||||
$unit = $other->unit->clone();
|
||||
if ( $this->unit->backupUnit ) {
|
||||
$unit->backupUnit = $this->unit->backupUnit;
|
||||
}
|
||||
} elseif ( !$other->unit->numerator && !$other->unit->denominator ) {
|
||||
// do nothing
|
||||
} else {
|
||||
|
@ -92,7 +94,7 @@ class Less_Tree_Dimension extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
throw new Less_Exception_Compiler( "Incompatible units. Change the units or use the unit function. Bad units: '" . $unit->toString() . "' and " . $other->unit->toString() . "'." );
|
||||
}
|
||||
|
||||
$value = Less_Functions::operate( $op, $this->value, $other->value );
|
||||
$value = $this->_operate( $op, $this->value, $other->value );
|
||||
}
|
||||
} elseif ( $op === '*' ) {
|
||||
$unit->numerator = array_merge( $unit->numerator, $other->unit->numerator );
|
||||
|
@ -140,7 +142,7 @@ class Less_Tree_Dimension extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
|
||||
public function convertTo( $conversions ) {
|
||||
$value = $this->value;
|
||||
$unit = clone $this->unit;
|
||||
$unit = $this->unit->clone();
|
||||
|
||||
if ( is_string( $conversions ) ) {
|
||||
$derivedConversions = [];
|
||||
|
|
15
include/thirdparty/less.php/Tree/Directive.php
vendored
15
include/thirdparty/less.php/Tree/Directive.php
vendored
|
@ -13,11 +13,11 @@ class Less_Tree_Directive extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
public $currentFileInfo;
|
||||
public $debugInfo;
|
||||
|
||||
public function __construct( $name, $value = null, $rules = null, $index = null, $isRooted = false, $currentFileInfo = null, $debugInfo = null ) {
|
||||
public function __construct( $name, $value = null, $rules = null, $index = null, $isRooted = false, $currentFileInfo = null, $debugInfo = null, $isReferenced = false ) {
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
|
||||
if ( $rules ) {
|
||||
if ( $rules !== null ) {
|
||||
if ( is_array( $rules ) ) {
|
||||
$this->rules = $rules;
|
||||
} else {
|
||||
|
@ -34,6 +34,7 @@ class Less_Tree_Directive extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
$this->isRooted = $isRooted;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
$this->debugInfo = $debugInfo;
|
||||
$this->isReferenced = $isReferenced;
|
||||
}
|
||||
|
||||
public function accept( $visitor ) {
|
||||
|
@ -57,14 +58,12 @@ class Less_Tree_Directive extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$value = $this->value;
|
||||
$rules = $this->rules;
|
||||
$output->add( $this->name, $this->currentFileInfo, $this->index );
|
||||
if ( $this->value ) {
|
||||
$output->add( ' ' );
|
||||
$this->value->genCSS( $output );
|
||||
}
|
||||
if ( $this->rules ) {
|
||||
if ( $this->rules !== null ) {
|
||||
Less_Tree::outputRuleset( $output, $this->rules );
|
||||
} else {
|
||||
$output->add( ';' );
|
||||
|
@ -97,7 +96,7 @@ class Less_Tree_Directive extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
$env->mediaPath = $mediaPathBackup;
|
||||
$env->mediaBlocks = $mediaPBlocksBackup;
|
||||
|
||||
return new self( $this->name, $value, $rules, $this->index, $this->isRooted, $this->currentFileInfo, $this->debugInfo );
|
||||
return new self( $this->name, $value, $rules, $this->index, $this->isRooted, $this->currentFileInfo, $this->debugInfo, $this->isReferenced );
|
||||
}
|
||||
|
||||
public function variable( $name ) {
|
||||
|
@ -119,6 +118,10 @@ class Less_Tree_Directive extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
}
|
||||
}
|
||||
|
||||
public function getIsReferenced() {
|
||||
return !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] || $this->isReferenced;
|
||||
}
|
||||
|
||||
public function emptySelectors() {
|
||||
$el = new Less_Tree_Element( '', '&', $this->index, $this->currentFileInfo );
|
||||
$sels = [ new Less_Tree_Selector( [ $el ], [], null, $this->index, $this->currentFileInfo ) ];
|
||||
|
|
7
include/thirdparty/less.php/Tree/Element.php
vendored
7
include/thirdparty/less.php/Tree/Element.php
vendored
|
@ -62,11 +62,12 @@ class Less_Tree_Element extends Less_Tree implements Less_Tree_HasValueProperty
|
|||
$value = $this->value;
|
||||
}
|
||||
|
||||
if ( $value === '' && $this->combinator === '&' ) {
|
||||
return '';
|
||||
$spaceOrEmpty = ' ';
|
||||
if ( Less_Parser::$options['compress'] || ( isset( Less_Environment::$_noSpaceCombinators[$this->combinator] ) && Less_Environment::$_noSpaceCombinators[$this->combinator] ) ) {
|
||||
$spaceOrEmpty = '';
|
||||
}
|
||||
|
||||
return Less_Environment::$_outputMap[$this->combinator] . $value;
|
||||
return $spaceOrEmpty . $this->combinator . $spaceOrEmpty . $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
32
include/thirdparty/less.php/Tree/Expression.php
vendored
32
include/thirdparty/less.php/Tree/Expression.php
vendored
|
@ -54,7 +54,7 @@ class Less_Tree_Expression extends Less_Tree implements Less_Tree_HasValueProper
|
|||
if ( !$this->parensInOp ) {
|
||||
Less_Environment::$parensStack--;
|
||||
|
||||
} elseif ( !Less_Environment::isMathOn() && !$doubleParen ) {
|
||||
} elseif ( !$env->isMathOn() && !$doubleParen ) {
|
||||
$returnValue = new Less_Tree_Paren( $returnValue );
|
||||
|
||||
}
|
||||
|
@ -87,4 +87,34 @@ class Less_Tree_Expression extends Less_Tree implements Less_Tree_HasValueProper
|
|||
$this->value = $new_value;
|
||||
}
|
||||
}
|
||||
|
||||
public function markReferenced() {
|
||||
if ( is_array( $this->value ) ) {
|
||||
foreach ( $this->value as $v ) {
|
||||
if ( method_exists( $v, 'markReferenced' ) ) {
|
||||
$v->markReferenced();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be used only in Less_Tree_Call::functionCaller()
|
||||
* to retrieve expression without comments
|
||||
* @internal
|
||||
*/
|
||||
public function mapToFunctionCallArgument() {
|
||||
if ( is_array( $this->value ) ) {
|
||||
$subNodes = [];
|
||||
foreach ( $this->value as $subNode ) {
|
||||
if ( !( $subNode instanceof Less_Tree_Comment ) ) {
|
||||
$subNodes[] = $subNode;
|
||||
}
|
||||
}
|
||||
return count( $subNodes ) === 1
|
||||
? $subNodes[0]
|
||||
: new Less_Tree_Expression( $subNodes );
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
272
include/thirdparty/less.php/Tree/Import.php
vendored
272
include/thirdparty/less.php/Tree/Import.php
vendored
|
@ -12,6 +12,7 @@
|
|||
* the file has been fetched, and parsed.
|
||||
*
|
||||
* @private
|
||||
* @see less-2.5.3.js#Import.prototype
|
||||
*/
|
||||
class Less_Tree_Import extends Less_Tree {
|
||||
|
||||
|
@ -21,29 +22,38 @@ class Less_Tree_Import extends Less_Tree {
|
|||
public $features;
|
||||
public $currentFileInfo;
|
||||
public $css;
|
||||
public $skip;
|
||||
/** @var bool|null This is populated by Less_ImportVisitor */
|
||||
public $doSkip = false;
|
||||
/** @var string|null This is populated by Less_ImportVisitor */
|
||||
public $importedFilename;
|
||||
/**
|
||||
* This is populated by Less_ImportVisitor.
|
||||
*
|
||||
* For imports that use "inline", this holds a raw string.
|
||||
*
|
||||
* @var string|Less_Tree_Ruleset|null
|
||||
*/
|
||||
public $root;
|
||||
|
||||
public function __construct( $path, $features, $options, $index, $currentFileInfo = null ) {
|
||||
$this->options = $options;
|
||||
public function __construct( $path, $features, array $options, $index, $currentFileInfo = null ) {
|
||||
$this->options = $options + [ 'inline' => false, 'optional' => false, 'multiple' => false ];
|
||||
$this->index = $index;
|
||||
$this->path = $path;
|
||||
$this->features = $features;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
|
||||
if ( is_array( $options ) ) {
|
||||
$this->options += [ 'inline' => false ];
|
||||
|
||||
if ( isset( $this->options['less'] ) || $this->options['inline'] ) {
|
||||
$this->css = !isset( $this->options['less'] ) || !$this->options['less'] || $this->options['inline'];
|
||||
} else {
|
||||
$pathValue = $this->getPath();
|
||||
// Leave any ".css" file imports as literals for the browser.
|
||||
// Also leave any remote HTTP resources as literals regardless of whether
|
||||
// they contain ".css" in their filename.
|
||||
if ( $pathValue && preg_match( '/^(https?:)?\/\/|\.css$/i', $pathValue ) ) {
|
||||
$this->css = true;
|
||||
}
|
||||
if ( isset( $this->options['less'] ) || $this->options['inline'] ) {
|
||||
$this->css = !isset( $this->options['less'] ) || !$this->options['less'] || $this->options['inline'];
|
||||
} else {
|
||||
$pathValue = $this->getPath();
|
||||
// Leave any ".css" file imports as literals for the browser.
|
||||
// Also leave any remote HTTP resources as literals regardless of whether
|
||||
// they contain ".css" in their filename.
|
||||
if ( $pathValue && (
|
||||
preg_match( '/[#\.\&\?\/]css([\?;].*)?$/', $pathValue )
|
||||
|| preg_match( '/^(https?:)?\/\//i', $pathValue )
|
||||
) ) {
|
||||
$this->css = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,14 +79,9 @@ class Less_Tree_Import extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
if ( $this->css ) {
|
||||
|
||||
if ( $this->css && !isset( $this->path->currentFileInfo["reference"] ) ) {
|
||||
$output->add( '@import ', $this->currentFileInfo, $this->index );
|
||||
|
||||
$this->path->genCSS( $output );
|
||||
if ( $this->features ) {
|
||||
$output->add( ' ' );
|
||||
|
@ -86,47 +91,47 @@ class Less_Tree_Import extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
public function toCSS() {
|
||||
$features = $this->features ? ' ' . $this->features->toCSS() : '';
|
||||
|
||||
if ( $this->css ) {
|
||||
return "@import " . $this->path->toCSS() . $features . ";\n";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPath() {
|
||||
if ( $this->path instanceof Less_Tree_Quoted ) {
|
||||
$path = $this->path->value;
|
||||
$path = ( isset( $this->css ) || preg_match( '/(\.[a-z]*$)|([\?;].*)$/', $path ) ) ? $path : $path . '.less';
|
||||
|
||||
// During the first pass, Less_Tree_Url may contain a Less_Tree_Variable (not yet expanded),
|
||||
// and thus has no value property defined yet. Return null until we reach the next phase.
|
||||
// https://github.com/wikimedia/less.php/issues/29
|
||||
} elseif ( $this->path instanceof Less_Tree_Url && !( $this->path->value instanceof Less_Tree_Variable ) ) {
|
||||
$path = $this->path->value->value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
// TODO: Upstream doesn't need a check against Less_Tree_Variable. Why do we?
|
||||
$path = ( $this->path instanceof Less_Tree_Url && !( $this->path->value instanceof Less_Tree_Variable ) )
|
||||
? $this->path->value->value
|
||||
// e.g. Less_Tree_Quoted
|
||||
: $this->path->value;
|
||||
|
||||
// remove query string and fragment
|
||||
return preg_replace( '/[\?#][^\?]*$/', '', $path );
|
||||
if ( is_string( $path ) ) {
|
||||
// remove query string and fragment
|
||||
return preg_replace( '/[\?#][^\?]*$/', '', $path );
|
||||
}
|
||||
}
|
||||
|
||||
public function isVariableImport() {
|
||||
$path = $this->path;
|
||||
if ( $path instanceof Less_Tree_Url ) {
|
||||
$path = $path->value;
|
||||
}
|
||||
if ( $path instanceof Less_Tree_Quoted ) {
|
||||
return $path->containsVariables();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function compileForImport( $env ) {
|
||||
return new self( $this->path->compile( $env ), $this->features, $this->options, $this->index, $this->currentFileInfo );
|
||||
$path = $this->path;
|
||||
if ( $path instanceof Less_Tree_Url ) {
|
||||
$path = $path->value;
|
||||
}
|
||||
return new self( $path->compile( $env ), $this->features, $this->options, $this->index, $this->currentFileInfo );
|
||||
}
|
||||
|
||||
public function compilePath( $env ) {
|
||||
$path = $this->path->compile( $env );
|
||||
$rootpath = '';
|
||||
if ( $this->currentFileInfo && $this->currentFileInfo['rootpath'] ) {
|
||||
$rootpath = $this->currentFileInfo['rootpath'];
|
||||
}
|
||||
$rootpath = $this->currentFileInfo['rootpath'] ?? null;
|
||||
|
||||
if ( !( $path instanceof Less_Tree_Url ) ) {
|
||||
if ( $rootpath ) {
|
||||
|
@ -147,135 +152,57 @@ class Less_Tree_Import extends Less_Tree {
|
|||
* @see less-2.5.3.js#Import.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$evald = $this->compileForImport( $env );
|
||||
$features = ( $this->features ? $this->features->compile( $env ) : null );
|
||||
|
||||
// TODO: Upstream doesn't do path resolution here. The reason we need it here is
|
||||
// because skip() takes a $path_and_uri argument. Once the TODO in ImportVisitor
|
||||
// about Less_Tree_Import::PathAndUri() is fixed, this can be removed by letting
|
||||
// skip() call $this->PathAndUri() on its own.
|
||||
// get path & uri
|
||||
$callback = Less_Parser::$options['import_callback'];
|
||||
$path_and_uri = is_callable( $callback ) ? $callback( $evald ) : null;
|
||||
$path_and_uri = $env->callImportCallback( $this );
|
||||
|
||||
if ( !$path_and_uri ) {
|
||||
$path_and_uri = $evald->PathAndUri();
|
||||
$path_and_uri = Less_FileManager::getFilePath( $this->getPath(), $this->currentFileInfo );
|
||||
}
|
||||
|
||||
if ( $path_and_uri ) {
|
||||
[ $full_path, $uri ] = $path_and_uri;
|
||||
} else {
|
||||
$full_path = $uri = $evald->getPath();
|
||||
}
|
||||
|
||||
// import once
|
||||
if ( $evald->skip( $full_path, $env ) ) {
|
||||
return [];
|
||||
$full_path = $uri = $this->getPath();
|
||||
}
|
||||
'@phan-var string $full_path';
|
||||
|
||||
if ( $this->options['inline'] ) {
|
||||
Less_Parser::AddParsedFile( $full_path );
|
||||
$contents = new Less_Tree_Anonymous( file_get_contents( $full_path ), 0, [], true, true );
|
||||
|
||||
if ( $this->features ) {
|
||||
return new Less_Tree_Media( [ $contents ], $this->features->value );
|
||||
}
|
||||
|
||||
return [ $contents ];
|
||||
}
|
||||
|
||||
// optional (need to be before "CSS" to support optional CSS imports. CSS should be checked only if empty($this->currentFileInfo))
|
||||
if ( isset( $this->options['optional'] ) && $this->options['optional'] && !file_exists( $full_path ) && ( !$evald->css || !empty( $this->currentFileInfo ) ) ) {
|
||||
// import once
|
||||
if ( $this->skip( $full_path, $env ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// css ?
|
||||
if ( $evald->css ) {
|
||||
$features = ( $evald->features ? $evald->features->compile( $env ) : null );
|
||||
return new self( $this->compilePath( $env ), $features, $this->options, $this->index );
|
||||
if ( $this->options['inline'] ) {
|
||||
$contents = new Less_Tree_Anonymous( $this->root, 0,
|
||||
[
|
||||
'filename' => $this->importedFilename,
|
||||
'reference' => $this->currentFileInfo['reference'] ?? null,
|
||||
],
|
||||
true,
|
||||
true,
|
||||
false
|
||||
);
|
||||
return $this->features
|
||||
? new Less_Tree_Media( [ $contents ], $this->features->value )
|
||||
: [ $contents ];
|
||||
} elseif ( $this->css ) {
|
||||
$newImport = new self( $this->compilePath( $env ), $features, $this->options, $this->index );
|
||||
// TODO: We might need upstream's `if (!newImport.css && this.error) { throw this.error;`
|
||||
return $newImport;
|
||||
} else {
|
||||
$ruleset = new Less_Tree_Ruleset( null, $this->root->rules );
|
||||
|
||||
$ruleset->evalImports( $env );
|
||||
|
||||
return $this->features
|
||||
? new Less_Tree_Media( $ruleset->rules, $this->features->value )
|
||||
: $ruleset->rules;
|
||||
|
||||
}
|
||||
|
||||
return $this->ParseImport( $full_path, $uri, $env );
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the import directories, get the full absolute path and uri of the import
|
||||
*/
|
||||
public function PathAndUri() {
|
||||
$evald_path = $this->getPath();
|
||||
|
||||
if ( $evald_path ) {
|
||||
|
||||
$import_dirs = [];
|
||||
|
||||
if ( Less_Environment::isPathRelative( $evald_path ) ) {
|
||||
// if the path is relative, the file should be in the current directory
|
||||
if ( $this->currentFileInfo ) {
|
||||
$import_dirs[ $this->currentFileInfo['currentDirectory'] ] = $this->currentFileInfo['uri_root'];
|
||||
}
|
||||
|
||||
} else {
|
||||
// otherwise, the file should be relative to the server root
|
||||
if ( $this->currentFileInfo ) {
|
||||
$import_dirs[ $this->currentFileInfo['entryPath'] ] = $this->currentFileInfo['entryUri'];
|
||||
}
|
||||
// if the user supplied entryPath isn't the actual root
|
||||
$import_dirs[ $_SERVER['DOCUMENT_ROOT'] ] = '';
|
||||
|
||||
}
|
||||
|
||||
// always look in user supplied import directories
|
||||
$import_dirs = array_merge( $import_dirs, Less_Parser::$options['import_dirs'] );
|
||||
|
||||
foreach ( $import_dirs as $rootpath => $rooturi ) {
|
||||
if ( is_callable( $rooturi ) ) {
|
||||
$res = $rooturi( $evald_path );
|
||||
if ( $res && is_string( $res[0] ) ) {
|
||||
return [
|
||||
Less_Environment::normalizePath( $res[0] ),
|
||||
Less_Environment::normalizePath( $res[1] ?? dirname( $evald_path ) )
|
||||
];
|
||||
}
|
||||
} elseif ( !empty( $rootpath ) ) {
|
||||
$path = rtrim( $rootpath, '/\\' ) . '/' . ltrim( $evald_path, '/\\' );
|
||||
if ( file_exists( $path ) ) {
|
||||
return [
|
||||
Less_Environment::normalizePath( $path ),
|
||||
Less_Environment::normalizePath( dirname( $rooturi . $evald_path ) )
|
||||
];
|
||||
}
|
||||
if ( file_exists( $path . '.less' ) ) {
|
||||
return [
|
||||
Less_Environment::normalizePath( $path . '.less' ),
|
||||
Less_Environment::normalizePath( dirname( $rooturi . $evald_path . '.less' ) )
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the import url and return the rules
|
||||
*
|
||||
* @param string $full_path
|
||||
* @param string|null $uri
|
||||
* @param mixed $env
|
||||
* @return Less_Tree_Media|array
|
||||
*/
|
||||
public function ParseImport( $full_path, $uri, $env ) {
|
||||
$import_env = clone $env;
|
||||
if ( ( isset( $this->options['reference'] ) && $this->options['reference'] ) || isset( $this->currentFileInfo['reference'] ) ) {
|
||||
$import_env->currentFileInfo['reference'] = true;
|
||||
}
|
||||
|
||||
if ( ( isset( $this->options['multiple'] ) && $this->options['multiple'] ) ) {
|
||||
$import_env->importMultiple = true;
|
||||
}
|
||||
|
||||
$parser = new Less_Parser( $import_env );
|
||||
$root = $parser->parseFile( $full_path, $uri, true );
|
||||
|
||||
$ruleset = new Less_Tree_Ruleset( null, $root->rules );
|
||||
$ruleset->evalImports( $import_env );
|
||||
|
||||
return $this->features ? new Less_Tree_Media( $ruleset->rules, $this->features->value ) : $ruleset->rules;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,16 +212,17 @@ class Less_Tree_Import extends Less_Tree {
|
|||
* @param Less_Environment $env
|
||||
* @return bool|null
|
||||
*/
|
||||
private function skip( $path, $env ) {
|
||||
$path = Less_Parser::AbsPath( $path, true );
|
||||
|
||||
if ( $path && Less_Parser::FileParsed( $path ) ) {
|
||||
|
||||
if ( isset( $this->currentFileInfo['reference'] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !isset( $this->options['multiple'] ) && !$env->importMultiple;
|
||||
public function skip( $path, $env ) {
|
||||
if ( $this->doSkip !== null ) {
|
||||
return $this->doSkip;
|
||||
}
|
||||
|
||||
// @see less-2.5.3.js#ImportVisitor.prototype.onImported
|
||||
if ( isset( $env->importVisitorOnceMap[$path] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$env->importVisitorOnceMap[$path] = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
8
include/thirdparty/less.php/Tree/Keyword.php
vendored
8
include/thirdparty/less.php/Tree/Keyword.php
vendored
|
@ -24,12 +24,4 @@ class Less_Tree_Keyword extends Less_Tree implements Less_Tree_HasValueProperty
|
|||
|
||||
$output->add( $this->value );
|
||||
}
|
||||
|
||||
public function compare( $other ) {
|
||||
if ( $other instanceof self ) {
|
||||
return $other->value === $this->value ? 0 : 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
6
include/thirdparty/less.php/Tree/Media.php
vendored
6
include/thirdparty/less.php/Tree/Media.php
vendored
|
@ -45,15 +45,15 @@ class Less_Tree_Media extends Less_Tree {
|
|||
$media = new self( [], [], $this->index, $this->currentFileInfo );
|
||||
|
||||
$strictMathBypass = false;
|
||||
if ( Less_Parser::$options['strictMath'] === false ) {
|
||||
if ( !$env->strictMath ) {
|
||||
$strictMathBypass = true;
|
||||
Less_Parser::$options['strictMath'] = true;
|
||||
$env->strictMath = true;
|
||||
}
|
||||
|
||||
$media->features = $this->features->compile( $env );
|
||||
|
||||
if ( $strictMathBypass ) {
|
||||
Less_Parser::$options['strictMath'] = false;
|
||||
$env->strictMath = false;
|
||||
}
|
||||
|
||||
$env->mediaPath[] = $media;
|
||||
|
|
62
include/thirdparty/less.php/Tree/Mixin/Call.php
vendored
62
include/thirdparty/less.php/Tree/Mixin/Call.php
vendored
|
@ -31,14 +31,24 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
|
||||
$args = [];
|
||||
foreach ( $this->arguments as $a ) {
|
||||
$args[] = [ 'name' => $a['name'], 'value' => $a['value']->compile( $env ) ];
|
||||
$argValue = $a['value']->compile( $env );
|
||||
if ( !empty( $a['expand'] ) && is_array( $argValue->value ) ) {
|
||||
foreach ( $argValue->value as $value ) {
|
||||
$args[] = [ 'name' => null, 'value' => $value ];
|
||||
}
|
||||
} else {
|
||||
$args[] = [ 'name' => $a['name'], 'value' => $argValue ];
|
||||
}
|
||||
}
|
||||
|
||||
$defNone = 0;
|
||||
$defTrue = 1;
|
||||
$defFalse = 2;
|
||||
foreach ( $env->frames as $frame ) {
|
||||
$mixins = $frame->find( $this->selector );
|
||||
$noArgumentsFilter = static function ( $rule ) use ( $env ) {
|
||||
return $rule->matchArgs( [], $env );
|
||||
};
|
||||
$mixins = $frame->find( $this->selector, null, $noArgumentsFilter );
|
||||
if ( !$mixins ) {
|
||||
continue;
|
||||
}
|
||||
|
@ -52,7 +62,8 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
|
||||
$mixins_len = count( $mixins );
|
||||
for ( $m = 0; $m < $mixins_len; $m++ ) {
|
||||
$mixin = $mixins[$m];
|
||||
$mixin = $mixins[$m]["rule"];
|
||||
$mixinPath = $mixins[$m]["path"];
|
||||
|
||||
if ( $this->IsRecursive( $env, $mixin ) ) {
|
||||
continue;
|
||||
|
@ -60,25 +71,36 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
|
||||
if ( $mixin->matchArgs( $args, $env ) ) {
|
||||
|
||||
$candidate = [ 'mixin' => $mixin, 'group' => $defNone ];
|
||||
|
||||
if ( $mixin instanceof Less_Tree_Ruleset ) {
|
||||
for ( $f = 0; $f < 2; $f++ ) {
|
||||
Less_Tree_DefaultFunc::value( $f );
|
||||
$conditionResult[$f] = $mixin->matchCondition( $args, $env );
|
||||
}
|
||||
|
||||
// PhanTypeInvalidDimOffset -- False positive
|
||||
'@phan-var array{0:bool,1:bool} $conditionResult';
|
||||
|
||||
if ( $conditionResult[0] || $conditionResult[1] ) {
|
||||
if ( $conditionResult[0] != $conditionResult[1] ) {
|
||||
$candidate['group'] = $conditionResult[1] ? $defTrue : $defFalse;
|
||||
// less-2.5.3.js#MixinCall calcDefGroup()
|
||||
$group = -1;
|
||||
for ( $f = 0; $f < 2; $f++ ) {
|
||||
$conditionResult[$f] = true;
|
||||
Less_Tree_DefaultFunc::value( $f );
|
||||
for ( $p = 0; $p < count( $mixinPath ) && $conditionResult[$f]; $p++ ) {
|
||||
$namespace = $mixinPath[$p] ?? null;
|
||||
if ( isset( $namespace ) && method_exists( $namespace, "matchCondition" ) ) {
|
||||
$conditionResult[$f] = $conditionResult[$f] && $namespace->matchCondition( null, $env );
|
||||
}
|
||||
|
||||
$candidates[] = $candidate;
|
||||
}
|
||||
} else {
|
||||
if ( method_exists( $mixin, "matchCondition" ) ) {
|
||||
$conditionResult[$f] = $conditionResult[$f] && $mixin->matchCondition( $args, $env );
|
||||
}
|
||||
}
|
||||
// PhanTypeInvalidDimOffset -- False positive
|
||||
'@phan-var array{0:bool,1:bool} $conditionResult';
|
||||
if ( $conditionResult[0] || $conditionResult[1] ) {
|
||||
if ( $conditionResult[0] != $conditionResult[1] ) {
|
||||
$group = $conditionResult[1] ?
|
||||
$defTrue : $defFalse;
|
||||
} else {
|
||||
$group = $defNone;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$candidate = [ 'mixin' => $mixin, 'group' => $group ];
|
||||
|
||||
if ( $candidate["group"] !== -1 ) {
|
||||
$candidates[] = $candidate;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
public $frames = [];
|
||||
public $condition;
|
||||
public $variadic;
|
||||
public $optionalParameters = [];
|
||||
|
||||
public function __construct( $name, $params, $rules, $condition, $variadic = false, $frames = [] ) {
|
||||
$this->name = $name;
|
||||
|
@ -28,6 +29,8 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
foreach ( $params as $p ) {
|
||||
if ( !isset( $p['name'] ) || ( $p['name'] && !isset( $p['value'] ) ) ) {
|
||||
$this->required++;
|
||||
} else {
|
||||
$this->optionalParameters[ (string)$p['name'] ] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,11 +39,8 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
$this->SetRulesetIndex();
|
||||
}
|
||||
|
||||
public function toCSS() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @see less-2.5.3.js#Definition.prototype.evalParams
|
||||
*/
|
||||
public function compileParams( $env, $mixinFrames, $args = [], &$evaldArguments = [] ) {
|
||||
|
@ -101,8 +101,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
} elseif ( isset( $param['value'] ) ) {
|
||||
|
||||
if ( !$mixinEnv ) {
|
||||
$mixinEnv = new Less_Environment();
|
||||
$mixinEnv->frames = array_merge( [ $frame ], $mixinFrames );
|
||||
$mixinEnv = $env->copyEvalEnv( array_merge( [ $frame ], $mixinFrames ) );
|
||||
}
|
||||
|
||||
$val = $param['value']->compile( $mixinEnv );
|
||||
|
@ -137,6 +136,12 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
return new self( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @param array|null $args
|
||||
* @param bool|null $important
|
||||
* @return Less_Tree_Ruleset
|
||||
*/
|
||||
public function evalCall( $env, $args = null, $important = null ) {
|
||||
Less_Environment::$mixin_stack++;
|
||||
|
||||
|
@ -156,8 +161,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
$ruleset = new Less_Tree_Ruleset( null, $this->rules );
|
||||
$ruleset->originalRuleset = $this->ruleset_id;
|
||||
|
||||
$ruleSetEnv = new Less_Environment();
|
||||
$ruleSetEnv->frames = array_merge( [ $this, $frame ], $mixinFrames );
|
||||
$ruleSetEnv = $env->copyEvalEnv( array_merge( [ $this, $frame ], $mixinFrames ) );
|
||||
$ruleset = $ruleset->compile( $ruleSetEnv );
|
||||
|
||||
if ( $important ) {
|
||||
|
@ -169,7 +173,11 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
return $ruleset;
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
/**
|
||||
* @param array $args
|
||||
* @param Less_Environment $env
|
||||
* @return bool
|
||||
*/
|
||||
public function matchCondition( $args, $env ) {
|
||||
if ( !$this->condition ) {
|
||||
return true;
|
||||
|
@ -182,13 +190,13 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
|
||||
$frame = $this->compileParams( $env, array_merge( $this->frames, $env->frames ), $args );
|
||||
|
||||
$compile_env = new Less_Environment();
|
||||
$compile_env->frames = array_merge(
|
||||
$compile_env = $env->copyEvalEnv(
|
||||
array_merge(
|
||||
[ $frame ], // the parameter variables
|
||||
$this->frames, // the parent namespace/mixin frames
|
||||
$env->frames // the current environment frames
|
||||
);
|
||||
|
||||
$this->frames, // the parent namespace/mixin frames
|
||||
$env->frames // the current environment frames
|
||||
)
|
||||
);
|
||||
$compile_env->functions = $env->functions;
|
||||
|
||||
return (bool)$this->condition->compile( $compile_env );
|
||||
|
@ -206,23 +214,33 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
return new self( $this->name, $this->params, $important_rules, $this->condition, $this->variadic, $this->frames );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array[] $args
|
||||
* @param Less_Environment|null $env
|
||||
* @see less-2.5.3.js#Definition.prototype.matchArgs
|
||||
*/
|
||||
public function matchArgs( $args, $env = null ) {
|
||||
$argsLength = count( $args );
|
||||
|
||||
$allArgsCnt = count( $args );
|
||||
$requiredArgsCnt = 0;
|
||||
foreach ( $args as $arg ) {
|
||||
if ( !array_key_exists( $arg['name'], $this->optionalParameters ) ) {
|
||||
$requiredArgsCnt++;
|
||||
}
|
||||
}
|
||||
if ( !$this->variadic ) {
|
||||
if ( $argsLength < $this->required ) {
|
||||
if ( $requiredArgsCnt < $this->required ) {
|
||||
return false;
|
||||
}
|
||||
if ( $argsLength > count( $this->params ) ) {
|
||||
if ( $allArgsCnt > count( $this->params ) ) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ( $argsLength < ( $this->required - 1 ) ) {
|
||||
if ( $requiredArgsCnt < ( $this->required - 1 ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$len = min( $argsLength, $this->arity );
|
||||
$len = min( $requiredArgsCnt, $this->arity );
|
||||
|
||||
for ( $i = 0; $i < $len; $i++ ) {
|
||||
if ( !isset( $this->params[$i]['name'] ) && !isset( $this->params[$i]['variadic'] ) ) {
|
||||
|
|
|
@ -28,7 +28,7 @@ class Less_Tree_NameValue extends Less_Tree implements Less_Tree_HasValuePropert
|
|||
public function genCSS( $output ) {
|
||||
$output->add(
|
||||
$this->name
|
||||
. Less_Environment::$_outputMap[': ']
|
||||
. ( Less_Parser::$options['compress'] ? ':' : ': ' )
|
||||
. $this->value
|
||||
. $this->important
|
||||
. ( ( ( Less_Environment::$lastRule && Less_Parser::$options['compress'] ) ) ? "" : ";" ),
|
||||
|
|
|
@ -10,10 +10,6 @@ class Less_Tree_Negative extends Less_Tree implements Less_Tree_HasValueProperty
|
|||
$this->value = $node;
|
||||
}
|
||||
|
||||
// function accept($visitor) {
|
||||
// $this->value = $visitor->visit($this->value);
|
||||
//}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
|
@ -23,7 +19,7 @@ class Less_Tree_Negative extends Less_Tree implements Less_Tree_HasValueProperty
|
|||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
if ( Less_Environment::isMathOn() ) {
|
||||
if ( $env->isMathOn() ) {
|
||||
$ret = new Less_Tree_Operation( '*', [ new Less_Tree_Dimension( -1 ), $this->value ] );
|
||||
return $ret->compile( $env );
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class Less_Tree_Operation extends Less_Tree {
|
|||
// For example, if one argument is a Less_Tree_Call like 'var(--foo)' then we
|
||||
// preserve it as literal for native CSS.
|
||||
// https://phabricator.wikimedia.org/T331688
|
||||
if ( Less_Environment::isMathOn() ) {
|
||||
if ( $env->isMathOn() ) {
|
||||
|
||||
if ( $a instanceof Less_Tree_Dimension && $b instanceof Less_Tree_Color ) {
|
||||
$a = $a->toColor();
|
||||
|
|
4
include/thirdparty/less.php/Tree/Quoted.php
vendored
4
include/thirdparty/less.php/Tree/Quoted.php
vendored
|
@ -36,6 +36,10 @@ class Less_Tree_Quoted extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
}
|
||||
}
|
||||
|
||||
public function containsVariables() {
|
||||
return preg_match( '/(`([^`]+)`)|@\{([\w-]+)\}/', $this->value );
|
||||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
$value = $this->value;
|
||||
if ( preg_match_all( '/`([^`]+)`/', $this->value, $matches ) ) {
|
||||
|
|
66
include/thirdparty/less.php/Tree/Rule.php
vendored
66
include/thirdparty/less.php/Tree/Rule.php
vendored
|
@ -23,8 +23,10 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
* @param int|null $index
|
||||
* @param array|null $currentFileInfo
|
||||
* @param bool $inline
|
||||
* @param bool|null $variable
|
||||
*/
|
||||
public function __construct( $name, $value = null, $important = null, $merge = null, $index = null, $currentFileInfo = null, $inline = false ) {
|
||||
public function __construct( $name, $value = null, $important = null, $merge = null,
|
||||
$index = null, $currentFileInfo = null, $inline = false, $variable = null ) {
|
||||
$this->name = $name;
|
||||
$this->value = ( $value instanceof Less_Tree )
|
||||
? $value
|
||||
|
@ -34,7 +36,7 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
$this->index = $index;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
$this->inline = $inline;
|
||||
$this->variable = ( is_string( $name ) && $name[0] === '@' );
|
||||
$this->variable = $variable ?? ( is_string( $name ) && $name[0] === '@' );
|
||||
}
|
||||
|
||||
public function accept( $visitor ) {
|
||||
|
@ -42,10 +44,10 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
* @see less-2.5.3.js#Rule.prototype.genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( $this->name . Less_Environment::$_outputMap[': '], $this->currentFileInfo, $this->index );
|
||||
$output->add( $this->name . ( Less_Parser::$options['compress'] ? ':' : ': ' ), $this->currentFileInfo, $this->index );
|
||||
try {
|
||||
$this->value->genCSS( $output );
|
||||
|
||||
|
@ -58,10 +60,12 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#Rule.prototype.eval
|
||||
* @param Less_Environment $env
|
||||
* @return self
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$variable = $this->variable;
|
||||
$name = $this->name;
|
||||
if ( is_array( $name ) ) {
|
||||
// expand 'primitive' name directly to get
|
||||
|
@ -71,28 +75,40 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
} else {
|
||||
$name = $this->CompileName( $env, $name );
|
||||
}
|
||||
$variable = false; // never treat expanded interpolation as new variable name
|
||||
}
|
||||
|
||||
$strictMathBypass = Less_Parser::$options['strictMath'];
|
||||
if ( $name === "font" && !Less_Parser::$options['strictMath'] ) {
|
||||
Less_Parser::$options['strictMath'] = true;
|
||||
$strictMathBypass = false;
|
||||
if ( $name === "font" && !$env->strictMath ) {
|
||||
$strictMathBypass = true;
|
||||
$env->strictMath = true;
|
||||
}
|
||||
|
||||
try {
|
||||
$env->importantScope[] = [];
|
||||
$evaldValue = $this->value->compile( $env );
|
||||
|
||||
if ( !$this->variable && $evaldValue instanceof Less_Tree_DetachedRuleset ) {
|
||||
throw new Less_Exception_Compiler( "Rulesets cannot be evaluated on a property.", null, $this->index, $this->currentFileInfo );
|
||||
}
|
||||
|
||||
if ( Less_Environment::$mixin_stack ) {
|
||||
$return = new self( $name, $evaldValue, $this->important, $this->merge, $this->index, $this->currentFileInfo, $this->inline );
|
||||
} else {
|
||||
$this->name = $name;
|
||||
$this->value = $evaldValue;
|
||||
$return = $this;
|
||||
$important = $this->important;
|
||||
$importantResult = array_pop( $env->importantScope );
|
||||
|
||||
if ( !$important && isset( $importantResult['important'] ) && $importantResult['important'] ) {
|
||||
$important = $importantResult['important'];
|
||||
}
|
||||
|
||||
$return = new Less_Tree_Rule( $name,
|
||||
$evaldValue,
|
||||
$important,
|
||||
$this->merge,
|
||||
$this->index,
|
||||
$this->currentFileInfo,
|
||||
$this->inline,
|
||||
$variable,
|
||||
);
|
||||
|
||||
} catch ( Less_Exception_Parser $e ) {
|
||||
if ( !is_numeric( $e->index ) ) {
|
||||
$e->index = $this->index;
|
||||
|
@ -102,7 +118,9 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
throw $e;
|
||||
}
|
||||
|
||||
Less_Parser::$options['strictMath'] = $strictMathBypass;
|
||||
if ( $strictMathBypass ) {
|
||||
$env->strictMath = false;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
@ -119,4 +137,24 @@ class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
return new self( $this->name, $this->value, '!important', $this->merge, $this->index, $this->currentFileInfo, $this->inline );
|
||||
}
|
||||
|
||||
public function mark( $value ) {
|
||||
if ( !is_array( $this->value ) ) {
|
||||
|
||||
if ( method_exists( $value, 'markReferenced' ) ) {
|
||||
// @phan-suppress-next-line PhanUndeclaredMethod
|
||||
$value->markReferenced();
|
||||
}
|
||||
} else {
|
||||
foreach ( $this->value as $v ) {
|
||||
$this->mark( $v );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function markReferenced() {
|
||||
if ( $this->value ) {
|
||||
$this->mark( $this->value );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
63
include/thirdparty/less.php/Tree/Ruleset.php
vendored
63
include/thirdparty/less.php/Tree/Ruleset.php
vendored
|
@ -300,13 +300,26 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
$this->lookups = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#Ruleset.prototype.variables
|
||||
*/
|
||||
public function variables() {
|
||||
$this->_variables = [];
|
||||
foreach ( $this->rules as $r ) {
|
||||
if ( $r instanceof Less_Tree_Rule && $r->variable === true ) {
|
||||
$this->_variables[$r->name] = $r;
|
||||
}
|
||||
// when evaluating variables in an import statement, imports have not been eval'd
|
||||
// so we need to go inside import statements.
|
||||
// guard against root being a string (in the case of inlined less)
|
||||
if ( $r instanceof Less_Tree_Import && $r->root instanceof Less_Tree_Ruleset ) {
|
||||
$vars = $r->root->variables();
|
||||
foreach ( $vars as $key => $name ) {
|
||||
$this->_variables[$key] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->_variables;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,7 +333,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
return $this->_variables[$name] ?? null;
|
||||
}
|
||||
|
||||
public function find( $selector, $self = null ) {
|
||||
public function find( $selector, $self = null, $filter = null ) {
|
||||
$key = implode( ' ', $selector->_oelements );
|
||||
|
||||
if ( !isset( $this->lookups[$key] ) ) {
|
||||
|
@ -342,9 +355,15 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
$match = $selector->match( $ruleSelector );
|
||||
if ( $match ) {
|
||||
if ( $selector->elements_len > $match ) {
|
||||
$this->lookups[$key] = array_merge( $this->lookups[$key], $rule->find( new Less_Tree_Selector( array_slice( $selector->elements, $match ) ), $self ) );
|
||||
if ( !$filter || $filter( $rule ) ) {
|
||||
$foundMixins = $rule->find( new Less_Tree_Selector( array_slice( $selector->elements, $match ) ), $self, $filter );
|
||||
for ( $i = 0; $i < count( $foundMixins ); ++$i ) {
|
||||
$foundMixins[$i]["path"][] = $rule;
|
||||
}
|
||||
$this->lookups[$key] = array_merge( $this->lookups[$key], $foundMixins );
|
||||
}
|
||||
} else {
|
||||
$this->lookups[$key][] = $rule;
|
||||
$this->lookups[$key][] = [ "rule" => $rule, "path" => [] ];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -352,6 +371,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this->lookups[$key];
|
||||
|
@ -473,14 +493,43 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
}
|
||||
|
||||
public function markReferenced() {
|
||||
if ( !$this->selectors ) {
|
||||
return;
|
||||
if ( $this->selectors !== null ) {
|
||||
foreach ( $this->selectors as $selector ) {
|
||||
$selector->markReferenced();
|
||||
}
|
||||
}
|
||||
foreach ( $this->selectors as $selector ) {
|
||||
$selector->markReferenced();
|
||||
|
||||
if ( $this->rules ) {
|
||||
foreach ( $this->rules as $rule ) {
|
||||
if ( method_exists( $rule, 'markReferenced' ) ) {
|
||||
$rule->markReferenced();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getIsReferenced() {
|
||||
if ( $this->paths ) {
|
||||
foreach ( $this->paths as $path ) {
|
||||
foreach ( $path as $p ) {
|
||||
if ( method_exists( $p, 'getIsReferenced' ) && $p->getIsReferenced() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->selectors ) {
|
||||
foreach ( $this->selectors as $selector ) {
|
||||
if ( method_exists( $selector, 'getIsReferenced' ) && $selector->getIsReferenced() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Tree_Selector[][] $context
|
||||
* @param Less_Tree_Selector[]|null $selectors
|
||||
|
|
10
include/thirdparty/less.php/Tree/Selector.php
vendored
10
include/thirdparty/less.php/Tree/Selector.php
vendored
|
@ -101,12 +101,16 @@ class Less_Tree_Selector extends Less_Tree {
|
|||
$css .= $v->value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $v->value->value ) && !is_object( $v->value->value ) ) {
|
||||
$css .= $v->value->value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( $v->value instanceof Less_Tree_Selector || $v->value instanceof Less_Tree_Variable )
|
||||
|| !is_string( $v->value->value ) ) {
|
||||
$this->cacheable = false;
|
||||
}
|
||||
if ( isset( $v->value->value ) && !is_object( $v->value->value ) ) {
|
||||
$css .= $v->value->value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
36
include/thirdparty/less.php/Tree/Unit.php
vendored
36
include/thirdparty/less.php/Tree/Unit.php
vendored
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Unit.prototype
|
||||
*/
|
||||
class Less_Tree_Unit extends Less_Tree {
|
||||
|
||||
|
@ -11,22 +12,28 @@ class Less_Tree_Unit extends Less_Tree {
|
|||
public function __construct( $numerator = [], $denominator = [], $backupUnit = null ) {
|
||||
$this->numerator = $numerator;
|
||||
$this->denominator = $denominator;
|
||||
$this->backupUnit = $backupUnit;
|
||||
sort( $this->numerator );
|
||||
sort( $this->denominator );
|
||||
$this->backupUnit = $backupUnit ?? $numerator[0] ?? null;
|
||||
}
|
||||
|
||||
public function __clone() {
|
||||
public function clone() {
|
||||
// we are recreating a new object to trigger logic from constructor
|
||||
return new Less_Tree_Unit( $this->numerator, $this->denominator, $this->backupUnit );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
if ( $this->numerator ) {
|
||||
$output->add( $this->numerator[0] );
|
||||
} elseif ( $this->denominator ) {
|
||||
$output->add( $this->denominator[0] );
|
||||
} elseif ( !Less_Parser::$options['strictUnits'] && $this->backupUnit ) {
|
||||
$strictUnits = Less_Parser::$options['strictUnits'];
|
||||
|
||||
if ( count( $this->numerator ) === 1 ) {
|
||||
$output->add( $this->numerator[0] ); // the ideal situation
|
||||
} elseif ( !$strictUnits && $this->backupUnit ) {
|
||||
$output->add( $this->backupUnit );
|
||||
} elseif ( !$strictUnits && $this->denominator ) {
|
||||
$output->add( $this->denominator[0] );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +65,7 @@ class Less_Tree_Unit extends Less_Tree {
|
|||
return (bool)preg_match( '/px|em|%|in|cm|mm|pc|pt|ex/', $css );
|
||||
}
|
||||
|
||||
// TODO: Remove unused method
|
||||
public function isAngle() {
|
||||
return isset( Less_Tree_UnitConversions::$angle[$this->toCSS()] );
|
||||
}
|
||||
|
@ -92,21 +100,17 @@ class Less_Tree_Unit extends Less_Tree {
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#Unit.prototype.cancel
|
||||
*/
|
||||
public function cancel() {
|
||||
$counter = [];
|
||||
$backup = null;
|
||||
|
||||
foreach ( $this->numerator as $atomicUnit ) {
|
||||
if ( !$backup ) {
|
||||
$backup = $atomicUnit;
|
||||
}
|
||||
$counter[$atomicUnit] = ( $counter[$atomicUnit] ?? 0 ) + 1;
|
||||
}
|
||||
|
||||
foreach ( $this->denominator as $atomicUnit ) {
|
||||
if ( !$backup ) {
|
||||
$backup = $atomicUnit;
|
||||
}
|
||||
$counter[$atomicUnit] = ( $counter[$atomicUnit] ?? 0 ) - 1;
|
||||
}
|
||||
|
||||
|
@ -125,10 +129,6 @@ class Less_Tree_Unit extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
if ( !$this->numerator && !$this->denominator && $backup ) {
|
||||
$this->backupUnit = $backup;
|
||||
}
|
||||
|
||||
sort( $this->numerator );
|
||||
sort( $this->denominator );
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ class Less_Tree_UnitConversions {
|
|||
'cm' => 0.01,
|
||||
'mm' => 0.001,
|
||||
'in' => 0.0254,
|
||||
'px' => 0.000264583, // 0.0254 / 96,
|
||||
'pt' => 0.000352778, // 0.0254 / 72,
|
||||
'pc' => 0.004233333, // 0.0254 / 72 * 12
|
||||
'px' => 0.00026458333333, // 0.0254 / 96,
|
||||
'pt' => 0.00035277777777777776, // 0.0254 / 72,
|
||||
'pc' => 0.004233333333333333, // 0.0254 / 72 * 12
|
||||
];
|
||||
|
||||
public static $duration = [
|
||||
|
|
4
include/thirdparty/less.php/Tree/Value.php
vendored
4
include/thirdparty/less.php/Tree/Value.php
vendored
|
@ -31,14 +31,14 @@ class Less_Tree_Value extends Less_Tree implements Less_Tree_HasValueProperty {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
* @see less-2.5.3.js#Value.prototype.genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$len = count( $this->value );
|
||||
for ( $i = 0; $i < $len; $i++ ) {
|
||||
$this->value[$i]->genCSS( $output );
|
||||
if ( $i + 1 < $len ) {
|
||||
$output->add( Less_Environment::$_outputMap[','] );
|
||||
$output->add( Less_Parser::$options['compress'] ? ',' : ', ' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class Less_Tree_Variable extends Less_Tree {
|
|||
/**
|
||||
* @param Less_Environment $env
|
||||
* @return Less_Tree|Less_Tree_Keyword|Less_Tree_Quoted
|
||||
* @see less-2.5.3.js#Ruleset.prototype.eval
|
||||
* @see less-2.5.3.js#Variable.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
if ( $this->name[1] === '@' ) {
|
||||
|
@ -40,7 +40,12 @@ class Less_Tree_Variable extends Less_Tree {
|
|||
$this->evaluating = true;
|
||||
|
||||
foreach ( $env->frames as $frame ) {
|
||||
if ( $v = $frame->variable( $name ) ) {
|
||||
$v = $frame->variable( $name );
|
||||
if ( $v ) {
|
||||
if ( isset( $v->important ) && $v->important ) {
|
||||
$importantScopeLength = count( $env->importantScope );
|
||||
$env->importantScope[ $importantScopeLength - 1 ]['important'] = $v->important;
|
||||
}
|
||||
$r = $v->value->compile( $env );
|
||||
$this->evaluating = false;
|
||||
return $r;
|
||||
|
|
4
include/thirdparty/less.php/Version.php
vendored
4
include/thirdparty/less.php/Version.php
vendored
|
@ -6,11 +6,11 @@
|
|||
class Less_Version {
|
||||
|
||||
/* Current release version of less.php */
|
||||
public const version = '4.2.0';
|
||||
public const version = '4.4.1';
|
||||
|
||||
/* Upstream less.js version that this release should be compatible with */
|
||||
public const less_version = '2.5.3';
|
||||
|
||||
/* Parser cache version */
|
||||
public const cache_version = '253-1';
|
||||
public const cache_version = '253-3';
|
||||
}
|
||||
|
|
19
include/thirdparty/less.php/Visitor.php
vendored
19
include/thirdparty/less.php/Visitor.php
vendored
|
@ -13,16 +13,22 @@ class Less_Visitor {
|
|||
}
|
||||
|
||||
public function visitObj( $node ) {
|
||||
if ( !$node || !is_object( $node ) ) {
|
||||
return $node;
|
||||
}
|
||||
$funcName = 'visit' . str_replace( [ 'Less_Tree_', '_' ], '', get_class( $node ) );
|
||||
if ( isset( $this->_visitFnCache[$funcName] ) ) {
|
||||
$visitDeeper = true;
|
||||
$this->$funcName( $node, $visitDeeper );
|
||||
$newNode = $this->$funcName( $node, $visitDeeper );
|
||||
if ( $this instanceof Less_VisitorReplacing ) {
|
||||
$node = $newNode;
|
||||
}
|
||||
|
||||
if ( $visitDeeper ) {
|
||||
if ( $visitDeeper && is_object( $node ) ) {
|
||||
$node->accept( $this );
|
||||
}
|
||||
|
||||
$funcName .= "Out";
|
||||
$funcName .= 'Out';
|
||||
if ( isset( $this->_visitFnCache[$funcName] ) ) {
|
||||
$this->$funcName( $node );
|
||||
}
|
||||
|
@ -34,8 +40,11 @@ class Less_Visitor {
|
|||
return $node;
|
||||
}
|
||||
|
||||
public function visitArray( $nodes ) {
|
||||
foreach ( $nodes as $node ) {
|
||||
public function visitArray( &$nodes ) {
|
||||
// NOTE: The use of by-ref in a normal (non-replacing) Visitor may be surprising,
|
||||
// but upstream relies on this for Less_ImportVisitor, which modifies values of
|
||||
// `$importParent->rules` yet is not a replacing visitor.
|
||||
foreach ( $nodes as &$node ) {
|
||||
$this->visitObj( $node );
|
||||
}
|
||||
return $nodes;
|
||||
|
|
85
include/thirdparty/less.php/Visitor/toCSS.php
vendored
85
include/thirdparty/less.php/Visitor/toCSS.php
vendored
|
@ -52,26 +52,46 @@ class Less_Visitor_toCSS extends Less_VisitorReplacing {
|
|||
return $mediaNode;
|
||||
}
|
||||
|
||||
public function visitDirective( $directiveNode ) {
|
||||
if ( isset( $directiveNode->currentFileInfo['reference'] ) && ( !property_exists( $directiveNode, 'isReferenced' ) || !$directiveNode->isReferenced ) ) {
|
||||
return [];
|
||||
}
|
||||
public function visitDirective( $directiveNode, &$visitDeeper ) {
|
||||
if ( $directiveNode->name === '@charset' ) {
|
||||
// Only output the debug info together with subsequent @charset definitions
|
||||
// a comment (or @media statement) before the actual @charset directive would
|
||||
// be considered illegal css as it has to be on the first line
|
||||
if ( !$directiveNode->getIsReferenced() ) {
|
||||
return;
|
||||
}
|
||||
if ( isset( $this->charset ) && $this->charset ) {
|
||||
|
||||
// if( $directiveNode->debugInfo ){
|
||||
// $comment = new Less_Tree_Comment('/* ' . str_replace("\n",'',$directiveNode->toCSS())." */\n");
|
||||
// $comment->debugInfo = $directiveNode->debugInfo;
|
||||
// return $this->visit($comment);
|
||||
//}
|
||||
|
||||
return [];
|
||||
// NOTE: Skip debugInfo handling (not implemented)
|
||||
return;
|
||||
}
|
||||
$this->charset = true;
|
||||
}
|
||||
|
||||
if ( $directiveNode->rules ) {
|
||||
$this->_mergeRules( $directiveNode->rules[0]->rules );
|
||||
// process childs
|
||||
$directiveNode->accept( $this );
|
||||
$visitDeeper = false;
|
||||
|
||||
// the directive was directly referenced and therefore needs to be shown in the output
|
||||
if ( $directiveNode->getIsReferenced() ) {
|
||||
return $directiveNode;
|
||||
}
|
||||
|
||||
if ( !$directiveNode->rules ) {
|
||||
return;
|
||||
}
|
||||
if ( $this->hasVisibleChild( $directiveNode ) ) {
|
||||
// marking as referenced in case the directive is stored inside another directive
|
||||
$directiveNode->markReferenced();
|
||||
return $directiveNode;
|
||||
}
|
||||
// The directive was not directly referenced and does not contain anything that
|
||||
//was referenced. Therefore it must not be shown in output.
|
||||
return;
|
||||
} else {
|
||||
if ( !$directiveNode->getIsReferenced() ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return $directiveNode;
|
||||
}
|
||||
|
||||
|
@ -143,6 +163,22 @@ class Less_Visitor_toCSS extends Less_VisitorReplacing {
|
|||
return $rulesets;
|
||||
}
|
||||
|
||||
public function visitAnonymous( $anonymousNode ) {
|
||||
if ( !$anonymousNode->getIsReferenced() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$anonymousNode->accept( $this );
|
||||
return $anonymousNode;
|
||||
}
|
||||
|
||||
public function visitImport( $importNode ) {
|
||||
if ( isset( $importNode->path->currentFileInfo["reference"] ) && $importNode->css ) {
|
||||
return;
|
||||
}
|
||||
return $importNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for visitiRuleset
|
||||
*
|
||||
|
@ -273,4 +309,23 @@ class Less_Visitor_toCSS extends Less_VisitorReplacing {
|
|||
}
|
||||
return new Less_Tree_Value( $mapped );
|
||||
}
|
||||
|
||||
public function hasVisibleChild( $directiveNode ) {
|
||||
// prepare list of childs
|
||||
$rule = $bodyRules = $directiveNode->rules;
|
||||
// if there is only one nested ruleset and that one has no path, then it is
|
||||
//just fake ruleset that got not replaced and we need to look inside it to
|
||||
//get real childs
|
||||
if ( count( $bodyRules ) === 1 && ( !$bodyRules[0]->paths || count( $bodyRules[0]->paths ) === 0 ) ) {
|
||||
$bodyRules = $bodyRules[0]->rules;
|
||||
}
|
||||
foreach ( $bodyRules as $rule ) {
|
||||
if ( method_exists( $rule, 'getIsReferenced' ) && $rule->getIsReferenced() ) {
|
||||
// the directive contains something that was referenced (likely by extend)
|
||||
//therefore it needs to be shown in output too
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
26
include/thirdparty/less.php/VisitorReplacing.php
vendored
26
include/thirdparty/less.php/VisitorReplacing.php
vendored
|
@ -4,31 +4,7 @@
|
|||
*/
|
||||
class Less_VisitorReplacing extends Less_Visitor {
|
||||
|
||||
public function visitObj( $node ) {
|
||||
$funcName = 'visit' . str_replace( [ 'Less_Tree_', '_' ], '', get_class( $node ) );
|
||||
if ( isset( $this->_visitFnCache[$funcName] ) ) {
|
||||
$visitDeeper = true;
|
||||
$node = $this->$funcName( $node, $visitDeeper );
|
||||
|
||||
if ( $node ) {
|
||||
if ( $visitDeeper && is_object( $node ) ) {
|
||||
$node->accept( $this );
|
||||
}
|
||||
|
||||
$funcName .= "Out";
|
||||
if ( isset( $this->_visitFnCache[$funcName] ) ) {
|
||||
$this->$funcName( $node );
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$node->accept( $this );
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function visitArray( $nodes ) {
|
||||
public function visitArray( &$nodes ) {
|
||||
$newNodes = [];
|
||||
foreach ( $nodes as $node ) {
|
||||
$evald = $this->visitObj( $node );
|
||||
|
|
|
@ -19,7 +19,7 @@ class Less_Autoloader {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( !spl_autoload_register( [ 'Less_Autoloader', 'loadClass' ] ) ) {
|
||||
if ( !spl_autoload_register( [ __CLASS__, 'loadClass' ] ) ) {
|
||||
throw new Exception( 'Unable to register Less_Autoloader::loadClass as an autoloading method.' );
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ class Less_Autoloader {
|
|||
* @return void
|
||||
*/
|
||||
public static function unregister() {
|
||||
spl_autoload_unregister( [ 'Less_Autoloader', 'loadClass' ] );
|
||||
spl_autoload_unregister( [ __CLASS__, 'loadClass' ] );
|
||||
self::$registered = false;
|
||||
}
|
||||
|
|
@ -1,5 +1,38 @@
|
|||
# Changelog
|
||||
|
||||
## 4.2.0
|
||||
|
||||
Added:
|
||||
* Add `isruleset()` function (Hannah Okwelum) [T354895](https://phabricator.wikimedia.org/T354895)
|
||||
* Add source details to "Operation on an invalid type" error (Hannah Okwelum) [T344197](https://phabricator.wikimedia.org/T344197)
|
||||
* Add support for `method=relative` parameter in color functions (Hannah Okwelum) [T354895](https://phabricator.wikimedia.org/T354895)
|
||||
* Add support for comments in variables and function parameters (Hannah Okwelum) [T354895](https://phabricator.wikimedia.org/T354895)
|
||||
* Less_Parser: Add `functions` parser option API (Hannah Okwelum)
|
||||
|
||||
Changed, to match Less.js 2.5.3:
|
||||
* Preserve original color keywords and shorthand hex (Hannah Okwelum) [T352866](https://phabricator.wikimedia.org/T352866)
|
||||
|
||||
Fixed:
|
||||
* Fix PHP Warning when using a dynamic variable name like `@@name` (Hannah Okwelum) [T352830](https://phabricator.wikimedia.org/T352830)
|
||||
* Fix PHP Warning when `@extend` path contains non-quoted attribute (Gr8b) [T349433](https://phabricator.wikimedia.org/T349433)
|
||||
* Less_Parser: Faster `skipWhitespace` by using native `strspn` (Umherirrender)
|
||||
* Less_Parser: Fix Less_Tree_JavaScript references to consistently be in camel-case (Stefan Fröhlich)
|
||||
* Fix `!important` in nested mixins (Hannah Okwelum) [T353141](https://phabricator.wikimedia.org/T353141)
|
||||
* Fix crash when using recursive mixins (Timo Tijhof) [T352829](https://phabricator.wikimedia.org/T352829)
|
||||
* Fix disappearing selectors in certain nested blocks (Hannah Okwelum) [T352859](https://phabricator.wikimedia.org/T352859)
|
||||
* Fix Less_Exception_Compiler when passing unquoted value to `color()` (Hannah Okwelum) [T353289](https://phabricator.wikimedia.org/T353289)
|
||||
* Fix order of comments in `@font-face` blocks (Timo Tijhof) [T356706](https://phabricator.wikimedia.org/T356706)
|
||||
* Fix string comparison to ignore quote type (Timo Tijhof) [T357160](https://phabricator.wikimedia.org/T357160)
|
||||
* Fix string interpolation in selectors (Hannah Okwelum) [T353142](https://phabricator.wikimedia.org/T353142)
|
||||
|
||||
## 4.1.1
|
||||
|
||||
* Less_Parser: Faster `MatchQuoted` by using native `strcspn`. (Thiemo Kreuz)
|
||||
* Less_Parser: Faster `parseEntitiesQuoted` by inlining `MatchQuoted`. (Thiemo Kreuz)
|
||||
* Less_Parser: Faster `parseUnicodeDescriptor` and `parseEntitiesJavascript` by first-char checks. (Thiemo Kreuz)
|
||||
* Less_Tree_Mixin_Call: Include mixin name in error message (Jeremy P)
|
||||
* Fix mismatched casing in class names to fix autoloading on case-sensitive filesystems (Jeremy P)
|
||||
|
||||
## 4.1.0
|
||||
|
||||
* Add support for `@supports` blocks. (Anne Tomasevich) [T332923](http://phabricator.wikimedia.org/T332923)
|
|
@ -5,16 +5,19 @@
|
|||
*/
|
||||
class Less_Cache {
|
||||
|
||||
// directory less.php can use for storing data
|
||||
/** @var string|false Directory less.php can use for storing data */
|
||||
public static $cache_dir = false;
|
||||
|
||||
// prefix for the storing data
|
||||
/** @var string Prefix for the storing data */
|
||||
public static $prefix = 'lessphp_';
|
||||
|
||||
// prefix for the storing vars
|
||||
/** @var string Prefix for the storing vars */
|
||||
public static $prefix_vars = 'lessphpvars_';
|
||||
|
||||
// specifies the number of seconds after which data created by less.php will be seen as 'garbage' and potentially cleaned up
|
||||
/**
|
||||
* @var int Specifies the number of seconds after which data created by less.php will be seen
|
||||
* as 'garbage' and potentially cleaned up
|
||||
*/
|
||||
public static $gc_lifetime = 604800;
|
||||
|
||||
/**
|
||||
|
@ -146,7 +149,7 @@ class Less_Cache {
|
|||
|
||||
$compiled = $parser->getCss();
|
||||
|
||||
$less_files = $parser->allParsedFiles();
|
||||
$less_files = $parser->AllParsedFiles();
|
||||
|
||||
return $compiled;
|
||||
}
|
||||
|
@ -213,7 +216,7 @@ class Less_Cache {
|
|||
|
||||
// only remove files with extensions created by less.php
|
||||
// css files removed based on the list files
|
||||
$remove_types = [ 'lesscache' => 1,'list' => 1,'less' => 1,'map' => 1 ];
|
||||
$remove_types = [ 'lesscache' => 1, 'list' => 1, 'less' => 1, 'map' => 1 ];
|
||||
|
||||
$files = scandir( self::$cache_dir );
|
||||
if ( !$files ) {
|
||||
|
@ -261,7 +264,7 @@ class Less_Cache {
|
|||
/**
|
||||
* Get the list of less files and generated css file from a list file
|
||||
*/
|
||||
static function ListFiles( $list_file, &$list, &$css_file_name ) {
|
||||
public static function ListFiles( $list_file, &$list, &$css_file_name ) {
|
||||
$list = explode( "\n", file_get_contents( $list_file ) );
|
||||
|
||||
// pop the cached name that should match $compiled_name
|
|
@ -19,12 +19,7 @@ abstract class Less_Configurable {
|
|||
protected $defaultOptions = [];
|
||||
|
||||
/**
|
||||
* Set options
|
||||
*
|
||||
* If $options is an object it will be converted into an array by called
|
||||
* it's toArray method.
|
||||
*
|
||||
* @param array|object $options
|
||||
* @param array $options
|
||||
*/
|
||||
public function setOptions( $options ) {
|
||||
$options = array_intersect_key( $options, $this->defaultOptions );
|
|
@ -9,11 +9,11 @@ class Less_Environment {
|
|||
*
|
||||
* - rootpath: rootpath to append to URLs
|
||||
*
|
||||
* @var array|null $currentFileInfo
|
||||
* @var array|null
|
||||
*/
|
||||
public $currentFileInfo;
|
||||
|
||||
/* Whether we are currently importing multiple copies */
|
||||
/** @var bool Whether we are currently importing multiple copies */
|
||||
public $importMultiple = false;
|
||||
|
||||
/**
|
||||
|
@ -21,14 +21,9 @@ class Less_Environment {
|
|||
*/
|
||||
public $frames = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var Less_Tree_Media[] */
|
||||
public $mediaBlocks = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
/** @var Less_Tree_Media[] */
|
||||
public $mediaPath = [];
|
||||
|
||||
public static $parensStack = 0;
|
||||
|
@ -90,7 +85,7 @@ class Less_Environment {
|
|||
}
|
||||
|
||||
public function copyEvalEnv( $frames = [] ) {
|
||||
$new_env = new Less_Environment();
|
||||
$new_env = new self();
|
||||
$new_env->frames = $frames;
|
||||
return $new_env;
|
||||
}
|
|
@ -43,6 +43,7 @@ class Less_Exception_Chunk extends Less_Exception_Parser {
|
|||
$lastMultiComment = null;
|
||||
$lastParen = null;
|
||||
|
||||
// phpcs:ignore Generic.CodeAnalysis.JumbledIncrementer
|
||||
for ( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ) {
|
||||
$cc = $this->CharCode( $this->parserCurrentIndex );
|
||||
if ( ( ( $cc >= 97 ) && ( $cc <= 122 ) ) || ( $cc < 34 ) ) {
|
||||
|
@ -102,10 +103,12 @@ class Less_Exception_Chunk extends Less_Exception_Parser {
|
|||
$currentChunkStartIndex = $this->parserCurrentIndex;
|
||||
for ( $this->parserCurrentIndex += 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ) {
|
||||
$cc2 = $this->CharCode( $this->parserCurrentIndex );
|
||||
if ( $cc2 > 96 ) { continue;
|
||||
if ( $cc2 > 96 ) {
|
||||
continue;
|
||||
}
|
||||
if ( $cc2 == $cc ) { $matched = 1;
|
||||
break;
|
||||
if ( $cc2 == $cc ) {
|
||||
$matched = 1;
|
||||
break;
|
||||
}
|
||||
if ( $cc2 == 92 ) { // \
|
||||
if ( $this->parserCurrentIndex == $this->input_len - 1 ) {
|
||||
|
@ -114,20 +117,23 @@ break;
|
|||
$this->parserCurrentIndex++;
|
||||
}
|
||||
}
|
||||
if ( $matched ) { break;
|
||||
if ( $matched ) {
|
||||
break;
|
||||
}
|
||||
return $this->fail( "unmatched `" . chr( $cc ) . "`", $currentChunkStartIndex );
|
||||
|
||||
// /, check for comment
|
||||
case 47:
|
||||
if ( $parenLevel || ( $this->parserCurrentIndex == $this->input_len - 1 ) ) { break;
|
||||
if ( $parenLevel || ( $this->parserCurrentIndex == $this->input_len - 1 ) ) {
|
||||
break;
|
||||
}
|
||||
$cc2 = $this->CharCode( $this->parserCurrentIndex + 1 );
|
||||
if ( $cc2 == 47 ) {
|
||||
// //, find lnfeed
|
||||
for ( $this->parserCurrentIndex += 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ) {
|
||||
$cc2 = $this->CharCode( $this->parserCurrentIndex );
|
||||
if ( ( $cc2 <= 13 ) && ( ( $cc2 == 10 ) || ( $cc2 == 13 ) ) ) { break;
|
||||
if ( ( $cc2 <= 13 ) && ( ( $cc2 == 10 ) || ( $cc2 == 13 ) ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif ( $cc2 == 42 ) {
|
||||
|
@ -135,11 +141,14 @@ break;
|
|||
$lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex;
|
||||
for ( $this->parserCurrentIndex += 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++ ) {
|
||||
$cc2 = $this->CharCode( $this->parserCurrentIndex );
|
||||
if ( $cc2 == 125 ) { $lastMultiCommentEndBrace = $this->parserCurrentIndex;
|
||||
if ( $cc2 == 125 ) {
|
||||
$lastMultiCommentEndBrace = $this->parserCurrentIndex;
|
||||
}
|
||||
if ( $cc2 != 42 ) { continue;
|
||||
if ( $cc2 != 42 ) {
|
||||
continue;
|
||||
}
|
||||
if ( $this->CharCode( $this->parserCurrentIndex + 1 ) == 47 ) { break;
|
||||
if ( $this->CharCode( $this->parserCurrentIndex + 1 ) == 47 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( $this->parserCurrentIndex == $this->input_len - 1 ) {
|
|
@ -9,7 +9,7 @@ class Less_Functions {
|
|||
public $env;
|
||||
public $currentFileInfo;
|
||||
|
||||
function __construct( $env, array $currentFileInfo = null ) {
|
||||
public function __construct( $env, array $currentFileInfo = null ) {
|
||||
$this->env = $env;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ class Less_Functions {
|
|||
|
||||
public function rgba( $r = null, $g = null, $b = null, $a = null ) {
|
||||
$rgb = [ $r, $g, $b ];
|
||||
$rgb = array_map( [ 'Less_Functions','scaled' ], $rgb );
|
||||
$rgb = array_map( [ __CLASS__, 'scaled' ], $rgb );
|
||||
|
||||
$a = self::number( $a );
|
||||
return new Less_Tree_Color( $rgb, $a );
|
||||
|
@ -137,7 +137,7 @@ class Less_Functions {
|
|||
$v = self::number( $v );
|
||||
$a = self::number( $a );
|
||||
|
||||
$i = floor( (int)( $h / 60 ) % 6 );
|
||||
$i = (int)floor( (int)( $h / 60 ) % 6 );
|
||||
$f = ( $h / 60 ) - $i;
|
||||
|
||||
$vs = [
|
||||
|
@ -170,7 +170,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$c = $color->toHSL();
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $c['h'] ) );
|
||||
return new Less_Tree_Dimension( $c['h'] );
|
||||
}
|
||||
|
||||
public function saturation( $color = null ) {
|
||||
|
@ -179,7 +179,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$c = $color->toHSL();
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $c['s'] * 100 ), '%' );
|
||||
return new Less_Tree_Dimension( $c['s'] * 100, '%' );
|
||||
}
|
||||
|
||||
public function lightness( $color = null ) {
|
||||
|
@ -188,7 +188,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$c = $color->toHSL();
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $c['l'] * 100 ), '%' );
|
||||
return new Less_Tree_Dimension( $c['l'] * 100, '%' );
|
||||
}
|
||||
|
||||
public function hsvhue( $color = null ) {
|
||||
|
@ -197,7 +197,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsv = $color->toHSV();
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $hsv['h'] ) );
|
||||
return new Less_Tree_Dimension( $hsv['h'] );
|
||||
}
|
||||
|
||||
public function hsvsaturation( $color = null ) {
|
||||
|
@ -206,7 +206,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsv = $color->toHSV();
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $hsv['s'] * 100 ), '%' );
|
||||
return new Less_Tree_Dimension( $hsv['s'] * 100, '%' );
|
||||
}
|
||||
|
||||
public function hsvvalue( $color = null ) {
|
||||
|
@ -215,7 +215,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsv = $color->toHSV();
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $hsv['v'] * 100 ), '%' );
|
||||
return new Less_Tree_Dimension( $hsv['v'] * 100, '%' );
|
||||
}
|
||||
|
||||
public function red( $color = null ) {
|
||||
|
@ -256,7 +256,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The first argument to luma must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $color->luma() * $color->alpha * 100 ), '%' );
|
||||
return new Less_Tree_Dimension( $color->luma() * $color->alpha * 100, '%' );
|
||||
}
|
||||
|
||||
public function luminance( $color = null ) {
|
||||
|
@ -269,10 +269,10 @@ class Less_Functions {
|
|||
+ ( 0.7152 * $color->rgb[1] / 255 )
|
||||
+ ( 0.0722 * $color->rgb[2] / 255 );
|
||||
|
||||
return new Less_Tree_Dimension( Less_Parser::round( $luminance * $color->alpha * 100 ), '%' );
|
||||
return new Less_Tree_Dimension( $luminance * $color->alpha * 100, '%' );
|
||||
}
|
||||
|
||||
public function saturate( $color = null, $amount = null ) {
|
||||
public function saturate( $color = null, $amount = null, $method = null ) {
|
||||
// filter: saturate(3.2);
|
||||
// should be kept as is, so check for color
|
||||
if ( $color instanceof Less_Tree_Dimension ) {
|
||||
|
@ -288,8 +288,11 @@ class Less_Functions {
|
|||
|
||||
$hsl = $color->toHSL();
|
||||
|
||||
$hsl['s'] += $amount->value / 100;
|
||||
$hsl['s'] = self::clamp( $hsl['s'] );
|
||||
if ( isset( $method ) && $method->value === "relative" ) {
|
||||
$hsl['s'] += $hsl['s'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['s'] += $amount->value / 100;
|
||||
} $hsl['s'] = self::clamp( $hsl['s'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
@ -298,7 +301,7 @@ class Less_Functions {
|
|||
* @param Less_Tree_Color|null $color
|
||||
* @param Less_Tree_Dimension|null $amount
|
||||
*/
|
||||
public function desaturate( $color = null, $amount = null ) {
|
||||
public function desaturate( $color = null, $amount = null, $method = null ) {
|
||||
if ( !$color instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The first argument to desaturate must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
@ -307,13 +310,19 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsl = $color->toHSL();
|
||||
$hsl['s'] -= $amount->value / 100;
|
||||
|
||||
if ( isset( $method ) && $method->value === "relative" ) {
|
||||
$hsl['s'] -= $hsl['s'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['s'] -= $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['s'] = self::clamp( $hsl['s'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
public function lighten( $color = null, $amount = null ) {
|
||||
public function lighten( $color = null, $amount = null, $method = null ) {
|
||||
if ( !$color instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The first argument to lighten must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
@ -323,13 +332,18 @@ class Less_Functions {
|
|||
|
||||
$hsl = $color->toHSL();
|
||||
|
||||
$hsl['l'] += $amount->value / 100;
|
||||
if ( isset( $method ) && $method->value === "relative" ) {
|
||||
$hsl['l'] += $hsl['l'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['l'] += $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['l'] = self::clamp( $hsl['l'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
public function darken( $color = null, $amount = null ) {
|
||||
public function darken( $color = null, $amount = null, $method = null ) {
|
||||
if ( !$color instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The first argument to darken must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
@ -338,13 +352,17 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsl = $color->toHSL();
|
||||
$hsl['l'] -= $amount->value / 100;
|
||||
if ( isset( $method ) && $method->value === "relative" ) {
|
||||
$hsl['l'] -= $hsl['l'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['l'] -= $amount->value / 100;
|
||||
}
|
||||
$hsl['l'] = self::clamp( $hsl['l'] );
|
||||
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
public function fadein( $color = null, $amount = null ) {
|
||||
public function fadein( $color = null, $amount = null, $method = null ) {
|
||||
if ( !$color instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The first argument to fadein must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
@ -353,12 +371,18 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsl = $color->toHSL();
|
||||
$hsl['a'] += $amount->value / 100;
|
||||
|
||||
if ( isset( $method ) && $method->value === "relative" ) {
|
||||
$hsl['a'] += $hsl['a'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['a'] += $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['a'] = self::clamp( $hsl['a'] );
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
||||
public function fadeout( $color = null, $amount = null ) {
|
||||
public function fadeout( $color = null, $amount = null, $method = null ) {
|
||||
if ( !$color instanceof Less_Tree_Color ) {
|
||||
throw new Less_Exception_Compiler( 'The first argument to fadeout must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
@ -367,7 +391,13 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
$hsl = $color->toHSL();
|
||||
$hsl['a'] -= $amount->value / 100;
|
||||
|
||||
if ( isset( $method ) && $method->value === "relative" ) {
|
||||
$hsl['a'] -= $hsl['a'] * $amount->value / 100;
|
||||
} else {
|
||||
$hsl['a'] -= $amount->value / 100;
|
||||
}
|
||||
|
||||
$hsl['a'] = self::clamp( $hsl['a'] );
|
||||
return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] );
|
||||
}
|
||||
|
@ -498,7 +528,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
public function escape( $str ) {
|
||||
$revert = [ '%21' => '!', '%2A' => '*', '%27' => "'",'%3F' => '?','%26' => '&','%2C' => ',','%2F' => '/','%40' => '@','%2B' => '+','%24' => '$' ];
|
||||
$revert = [ '%21' => '!', '%2A' => '*', '%27' => "'", '%3F' => '?', '%26' => '&', '%2C' => ',', '%2F' => '/', '%40' => '@', '%2B' => '+', '%24' => '$' ];
|
||||
|
||||
return new Less_Tree_Anonymous( strtr( rawurlencode( $str->value ), $revert ) );
|
||||
}
|
||||
|
@ -514,52 +544,44 @@ class Less_Functions {
|
|||
if ( $flags && $flags->value ) {
|
||||
$expr .= self::replace_flags( $flags->value );
|
||||
}
|
||||
$replacement = ( $replacement instanceof Less_Tree_Quoted ) ?
|
||||
$replacement->value : $replacement->toCSS();
|
||||
|
||||
$result = preg_replace( $expr, $replacement->value, $result );
|
||||
$result = preg_replace( $expr, $replacement, $result, 1 );
|
||||
|
||||
if ( property_exists( $string, 'quote' ) ) {
|
||||
if ( $flags && $flags->value && preg_match( '/g/', $flags->value ) ) {
|
||||
$result = preg_replace( $expr, $replacement, $result );
|
||||
}
|
||||
|
||||
if ( $string instanceof Less_Tree_Quoted ) {
|
||||
return new Less_Tree_Quoted( $string->quote, $result, $string->escaped );
|
||||
}
|
||||
return new Less_Tree_Quoted( '', $result );
|
||||
}
|
||||
|
||||
public static function replace_flags( $flags ) {
|
||||
$flags = str_split( $flags, 1 );
|
||||
$new_flags = '';
|
||||
|
||||
foreach ( $flags as $flag ) {
|
||||
switch ( $flag ) {
|
||||
case 'e':
|
||||
case 'g':
|
||||
break;
|
||||
|
||||
default:
|
||||
$new_flags .= $flag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $new_flags;
|
||||
return str_replace( [ 'e', 'g' ], '', $flags );
|
||||
}
|
||||
|
||||
public function _percent() {
|
||||
$string = func_get_arg( 0 );
|
||||
|
||||
$args = func_get_args();
|
||||
array_shift( $args );
|
||||
public function _percent( $string, ...$args ) {
|
||||
$result = $string->value;
|
||||
|
||||
foreach ( $args as $arg ) {
|
||||
if ( preg_match( '/%[sda]/i', $result, $token ) ) {
|
||||
$token = $token[0];
|
||||
$value = stristr( $token, 's' ) ? $arg->value : $arg->toCSS();
|
||||
$value = ( ( $arg instanceof Less_Tree_Quoted ) &&
|
||||
stristr( $token, 's' ) ? $arg->value : $arg->toCSS() );
|
||||
|
||||
$value = preg_match( '/[A-Z]$/', $token ) ? urlencode( $value ) : $value;
|
||||
$result = preg_replace( '/%[sda]/i', $value, $result, 1 );
|
||||
}
|
||||
}
|
||||
$result = str_replace( '%%', '%', $result );
|
||||
|
||||
return new Less_Tree_Quoted( $string->quote, $result, $string->escaped );
|
||||
if ( $string instanceof Less_Tree_Quoted ) {
|
||||
return new Less_Tree_Quoted( $string->quote, $result, $string->escaped );
|
||||
}
|
||||
return new Less_Tree_Quoted( '', $result );
|
||||
}
|
||||
|
||||
public function unit( $val, $unit = null ) {
|
||||
|
@ -589,7 +611,7 @@ class Less_Functions {
|
|||
$fraction = $f->value;
|
||||
}
|
||||
|
||||
return $this->_math( 'Less_Parser::round', null, $n, $fraction );
|
||||
return $this->_math( [ Less_Parser::class, 'round' ], null, $n, $fraction );
|
||||
}
|
||||
|
||||
public function pi() {
|
||||
|
@ -617,7 +639,7 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
public function floor( $n ) {
|
||||
return $this->_math( 'floor', null, $n );
|
||||
return $this->_math( 'floor', null, $n );
|
||||
}
|
||||
|
||||
public function sqrt( $n ) {
|
||||
|
@ -652,22 +674,17 @@ class Less_Functions {
|
|||
return $this->_math( 'acos', 'rad', $n );
|
||||
}
|
||||
|
||||
private function _math() {
|
||||
$args = func_get_args();
|
||||
$fn = array_shift( $args );
|
||||
$unit = array_shift( $args );
|
||||
|
||||
private function _math( $fn, $unit, ...$args ) {
|
||||
if ( $args[0] instanceof Less_Tree_Dimension ) {
|
||||
|
||||
if ( $unit === null ) {
|
||||
$unit = $args[0]->unit;
|
||||
} else {
|
||||
$args[0] = $args[0]->unify();
|
||||
}
|
||||
$args[0] = (float)$args[0]->value;
|
||||
return new Less_Tree_Dimension( call_user_func_array( $fn, $args ), $unit );
|
||||
return new Less_Tree_Dimension( $fn( ...$args ), $unit );
|
||||
} elseif ( is_numeric( $args[0] ) ) {
|
||||
return call_user_func_array( $fn, $args );
|
||||
return $fn( ...$args );
|
||||
} else {
|
||||
throw new Less_Exception_Compiler( "math functions take numbers as parameters" );
|
||||
}
|
||||
|
@ -697,9 +714,7 @@ class Less_Functions {
|
|||
for ( $i = 0; $i < $arg_count; $i++ ) {
|
||||
$current = $args[$i];
|
||||
if ( !( $current instanceof Less_Tree_Dimension ) ) {
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty Checked Less_Tree->value
|
||||
if ( property_exists( $args[$i], 'value' ) && is_array( $args[$i]->value ) ) {
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty Checked Less_Tree->value
|
||||
if ( $args[$i] instanceof Less_Tree_HasValueProperty && is_array( $args[$i]->value ) ) {
|
||||
$args[] = $args[$i]->value;
|
||||
}
|
||||
continue;
|
||||
|
@ -763,13 +778,11 @@ class Less_Functions {
|
|||
return new Less_Tree_Anonymous( ( $isMin ? 'min(' : 'max(' ) . implode( Less_Environment::$_outputMap[','], $args ) . ')' );
|
||||
}
|
||||
|
||||
public function min() {
|
||||
$args = func_get_args();
|
||||
public function min( ...$args ) {
|
||||
return $this->_minmax( true, $args );
|
||||
}
|
||||
|
||||
public function max() {
|
||||
$args = func_get_args();
|
||||
public function max( ...$args ) {
|
||||
return $this->_minmax( false, $args );
|
||||
}
|
||||
|
||||
|
@ -789,40 +802,48 @@ class Less_Functions {
|
|||
return new Less_Tree_Dimension( $n->value * 100, '%' );
|
||||
}
|
||||
|
||||
public function color( $n ) {
|
||||
if ( $n instanceof Less_Tree_Quoted ) {
|
||||
$colorCandidate = $n->value;
|
||||
$returnColor = Less_Tree_Color::fromKeyword( $colorCandidate );
|
||||
if ( $returnColor ) {
|
||||
return $returnColor;
|
||||
}
|
||||
if ( preg_match( '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/', $colorCandidate ) ) {
|
||||
return new Less_Tree_Color( substr( $colorCandidate, 1 ) );
|
||||
}
|
||||
throw new Less_Exception_Compiler( "argument must be a color keyword or 3/6 digit hex e.g. #FFF" );
|
||||
} else {
|
||||
throw new Less_Exception_Compiler( "argument must be a string" );
|
||||
/**
|
||||
* @see less-2.5.3.js#colorFunctions.color
|
||||
* @param Less_Tree_Quoted|Less_Tree_Color|Less_Tree_Keyword $c
|
||||
* @return Less_Tree_Color
|
||||
*/
|
||||
public function color( $c ) {
|
||||
if ( ( $c instanceof Less_Tree_Quoted ) &&
|
||||
preg_match( '/^#([a-f0-9]{6}|[a-f0-9]{3})/', $c->value )
|
||||
) {
|
||||
return new Less_Tree_Color( substr( $c->value, 1 ) );
|
||||
}
|
||||
|
||||
if ( ( $c instanceof Less_Tree_Color ) || ( $c = Less_Tree_Color::fromKeyword( $c->value ) ) ) {
|
||||
$c->value = null;
|
||||
return $c;
|
||||
}
|
||||
|
||||
throw new Less_Exception_Compiler( "argument must be a color keyword or 3/6 digit hex e.g. #FFF" );
|
||||
}
|
||||
|
||||
public function isruleset( $n ) {
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_DetachedRuleset ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function iscolor( $n ) {
|
||||
return $this->_isa( $n, 'Less_Tree_Color' );
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_Color ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function isnumber( $n ) {
|
||||
return $this->_isa( $n, 'Less_Tree_Dimension' );
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_Dimension ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function isstring( $n ) {
|
||||
return $this->_isa( $n, 'Less_Tree_Quoted' );
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_Quoted ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function iskeyword( $n ) {
|
||||
return $this->_isa( $n, 'Less_Tree_Keyword' );
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_Keyword ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function isurl( $n ) {
|
||||
return $this->_isa( $n, 'Less_Tree_Url' );
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_Url ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function ispixel( $n ) {
|
||||
|
@ -842,20 +863,11 @@ class Less_Functions {
|
|||
* @param Less_Tree|string $unit
|
||||
*/
|
||||
public function isunit( $n, $unit ) {
|
||||
if ( is_object( $unit ) && property_exists( $unit, 'value' ) ) {
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty Checked Less_Tree->value
|
||||
if ( $unit instanceof Less_Tree_Keyword || $unit instanceof Less_Tree_Quoted ) {
|
||||
$unit = $unit->value;
|
||||
}
|
||||
|
||||
return ( $n instanceof Less_Tree_Dimension ) && $n->unit->is( $unit ) ? new Less_Tree_Keyword( 'true' ) : new Less_Tree_Keyword( 'false' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Tree $n
|
||||
* @param string $type
|
||||
*/
|
||||
private function _isa( $n, $type ) {
|
||||
return is_a( $n, $type ) ? new Less_Tree_Keyword( 'true' ) : new Less_Tree_Keyword( 'false' );
|
||||
return new Less_Tree_Keyword( $n instanceof Less_Tree_Dimension && $n->unit->is( $unit ) ? 'true' : 'false' );
|
||||
}
|
||||
|
||||
public function tint( $color, $amount = null ) {
|
||||
|
@ -870,7 +882,7 @@ class Less_Functions {
|
|||
$index = (int)$index->value - 1; // (1-based index)
|
||||
// handle non-array values as an array of length 1
|
||||
// return 'undefined' if index is invalid
|
||||
if ( property_exists( $values, 'value' ) && is_array( $values->value ) ) {
|
||||
if ( !( $values instanceof Less_Tree_Color ) && is_array( $values->value ) ) {
|
||||
if ( isset( $values->value[$index] ) ) {
|
||||
return $values->value[$index];
|
||||
}
|
||||
|
@ -884,7 +896,8 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
public function length( $values ) {
|
||||
$n = ( property_exists( $values, 'value' ) && is_array( $values->value ) ) ? count( $values->value ) : 1;
|
||||
$n = ( $values instanceof Less_Tree_Expression || $values instanceof Less_Tree_Value ) ?
|
||||
count( $values->value ) : 1;
|
||||
return new Less_Tree_Dimension( $n );
|
||||
}
|
||||
|
||||
|
@ -931,7 +944,8 @@ class Less_Functions {
|
|||
|
||||
$charset = Less_Mime::charsets_lookup( $mimetype );
|
||||
$useBase64 = !in_array( $charset, [ 'US-ASCII', 'UTF-8' ] );
|
||||
if ( $useBase64 ) { $mimetype .= ';base64';
|
||||
if ( $useBase64 ) {
|
||||
$mimetype .= ';base64';
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -962,15 +976,13 @@ class Less_Functions {
|
|||
}
|
||||
|
||||
// svg-gradient
|
||||
public function svggradient( $direction ) {
|
||||
public function svggradient( $direction, ...$stops ) {
|
||||
$throw_message = 'svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]';
|
||||
$arguments = func_get_args();
|
||||
|
||||
if ( count( $arguments ) < 3 ) {
|
||||
if ( count( $stops ) < 2 ) {
|
||||
throw new Less_Exception_Compiler( $throw_message );
|
||||
}
|
||||
|
||||
$stops = array_slice( $arguments, 1 );
|
||||
$gradientType = 'linear';
|
||||
$rectangleDimension = 'x="0" y="0" width="1" height="1"';
|
||||
$useBase64 = true;
|
||||
|
@ -1004,7 +1016,8 @@ class Less_Functions {
|
|||
'<' . $gradientType . 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' . $gradientDirectionSvg . '>';
|
||||
|
||||
for ( $i = 0; $i < count( $stops ); $i++ ) {
|
||||
if ( is_object( $stops[$i] ) && property_exists( $stops[$i], 'value' ) ) {
|
||||
|
||||
if ( $stops[$i] instanceof Less_Tree_Expression ) {
|
||||
$color = $stops[$i]->value[0];
|
||||
$position = $stops[$i]->value[1];
|
||||
} else {
|
||||
|
@ -1034,7 +1047,7 @@ class Less_Functions {
|
|||
$returner = "'data:image/svg+xml," . $returner . "'";
|
||||
}
|
||||
|
||||
return new Less_Tree_URL( new Less_Tree_Anonymous( $returner ) );
|
||||
return new Less_Tree_Url( new Less_Tree_Anonymous( $returner ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1061,7 +1074,7 @@ class Less_Functions {
|
|||
for ( $i = 0; $i < 3; $i++ ) {
|
||||
$cb = $color1->rgb[$i] / 255;
|
||||
$cs = $color2->rgb[$i] / 255;
|
||||
$cr = call_user_func( $mode, $cb, $cs );
|
||||
$cr = $mode( $cb, $cs );
|
||||
if ( $ar ) {
|
||||
$cr = ( $as * $cs + $ab * ( $cb - $as * ( $cb + $cs - $cr ) ) ) / $ar;
|
||||
}
|
||||
|
@ -1079,7 +1092,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to multiply must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendMultiply' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendMultiply' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendMultiply( $cb, $cs ) {
|
||||
|
@ -1094,7 +1107,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to screen must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendScreen' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendScreen' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendScreen( $cb, $cs ) {
|
||||
|
@ -1109,7 +1122,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to overlay must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendOverlay' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendOverlay' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendOverlay( $cb, $cs ) {
|
||||
|
@ -1127,7 +1140,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to softlight must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendSoftlight' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendSoftlight' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendSoftlight( $cb, $cs ) {
|
||||
|
@ -1149,7 +1162,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to hardlight must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendHardlight' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendHardlight' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendHardlight( $cb, $cs ) {
|
||||
|
@ -1164,7 +1177,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to difference must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendDifference' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendDifference' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendDifference( $cb, $cs ) {
|
||||
|
@ -1179,7 +1192,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to exclusion must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendExclusion' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendExclusion' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
private function colorBlendExclusion( $cb, $cs ) {
|
||||
|
@ -1194,7 +1207,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to average must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendAverage' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendAverage' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
// non-w3c functions:
|
||||
|
@ -1210,7 +1223,7 @@ class Less_Functions {
|
|||
throw new Less_Exception_Compiler( 'The second argument to negation must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) );
|
||||
}
|
||||
|
||||
return $this->colorBlend( [ $this,'colorBlendNegation' ], $color1, $color2 );
|
||||
return $this->colorBlend( [ $this, 'colorBlendNegation' ], $color1, $color2 );
|
||||
}
|
||||
|
||||
public function colorBlendNegation( $cb, $cs ) {
|
|
@ -6,8 +6,11 @@
|
|||
*/
|
||||
class Less_Mime {
|
||||
|
||||
// this map is intentionally incomplete
|
||||
// if you want more, install 'mime' dep
|
||||
/**
|
||||
* this map is intentionally incomplete
|
||||
* if you want more, install 'mime' dep
|
||||
* @var array<string,string>
|
||||
*/
|
||||
private static $types = [
|
||||
'.htm' => 'text/html',
|
||||
'.html' => 'text/html',
|
|
@ -19,7 +19,7 @@ class Less_Output {
|
|||
* @param string $chunk The chunk to output
|
||||
* @param array|null $fileInfo The file information
|
||||
* @param int $index The index
|
||||
* @param mixed $mapLines
|
||||
* @param bool|null $mapLines
|
||||
*/
|
||||
public function add( $chunk, $fileInfo = null, $index = 0, $mapLines = null ) {
|
||||
$this->strs[] = $chunk;
|
|
@ -52,7 +52,7 @@ class Less_Output_Mapped extends Less_Output {
|
|||
* @param string $chunk
|
||||
* @param array|null $fileInfo
|
||||
* @param int $index
|
||||
* @param mixed $mapLines
|
||||
* @param bool|null $mapLines
|
||||
*/
|
||||
public function add( $chunk, $fileInfo = null, $index = 0, $mapLines = null ) {
|
||||
// ignore adding empty strings
|
||||
|
@ -84,19 +84,19 @@ class Less_Output_Mapped extends Less_Output {
|
|||
|
||||
if ( !$mapLines ) {
|
||||
$this->generator->addMapping(
|
||||
$this->lineNumber + 1, // generated_line
|
||||
$this->column, // generated_column
|
||||
count( $sourceLines ), // original_line
|
||||
strlen( $sourceColumns ), // original_column
|
||||
$this->lineNumber + 1, // generated_line
|
||||
$this->column, // generated_column
|
||||
count( $sourceLines ), // original_line
|
||||
strlen( $sourceColumns ), // original_column
|
||||
$fileInfo
|
||||
);
|
||||
} else {
|
||||
for ( $i = 0, $count = count( $lines ); $i < $count; $i++ ) {
|
||||
$this->generator->addMapping(
|
||||
$this->lineNumber + $i + 1, // generated_line
|
||||
$i === 0 ? $this->column : 0, // generated_column
|
||||
count( $sourceLines ) + $i, // original_line
|
||||
$i === 0 ? strlen( $sourceColumns ) : 0, // original_column
|
||||
$this->lineNumber + $i + 1, // generated_line
|
||||
$i === 0 ? $this->column : 0, // generated_column
|
||||
count( $sourceLines ) + $i, // original_line
|
||||
$i === 0 ? strlen( $sourceColumns ) : 0, // original_column
|
||||
$fileInfo
|
||||
);
|
||||
}
|
|
@ -7,23 +7,24 @@ class Less_Parser {
|
|||
|
||||
/**
|
||||
* Default parser options
|
||||
* @var array<string,mixed>
|
||||
*/
|
||||
public static $default_options = [
|
||||
'compress' => false, // option - whether to compress
|
||||
'strictUnits' => false, // whether units need to evaluate correctly
|
||||
'strictMath' => false, // whether math has to be within parenthesis
|
||||
'relativeUrls' => true, // option - whether to adjust URL's to be relative
|
||||
'urlArgs' => '', // whether to add args into url tokens
|
||||
'compress' => false, // option - whether to compress
|
||||
'strictUnits' => false, // whether units need to evaluate correctly
|
||||
'strictMath' => false, // whether math has to be within parenthesis
|
||||
'relativeUrls' => true, // option - whether to adjust URL's to be relative
|
||||
'urlArgs' => '', // whether to add args into url tokens
|
||||
'numPrecision' => 8,
|
||||
|
||||
'import_dirs' => [],
|
||||
'import_callback' => null,
|
||||
'cache_dir' => null,
|
||||
'cache_method' => 'serialize', // false, 'serialize', 'callback';
|
||||
'cache_method' => 'serialize', // false, 'serialize', 'callback';
|
||||
'cache_callback_get' => null,
|
||||
'cache_callback_set' => null,
|
||||
|
||||
'sourceMap' => false, // whether to output a source map
|
||||
'sourceMap' => false, // whether to output a source map
|
||||
'sourceMapBasepath' => null,
|
||||
'sourceMapWriteTo' => null,
|
||||
'sourceMapURL' => null,
|
||||
|
@ -31,6 +32,7 @@ class Less_Parser {
|
|||
'indentation' => ' ',
|
||||
|
||||
'plugins' => [],
|
||||
'functions' => [],
|
||||
|
||||
];
|
||||
|
||||
|
@ -133,6 +135,11 @@ class Less_Parser {
|
|||
Less_Cache::CheckCacheDir();
|
||||
}
|
||||
return;
|
||||
case 'functions':
|
||||
foreach ( $value as $key => $function ) {
|
||||
$this->registerFunction( $key, $function );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self::$options[$option] = $value;
|
||||
|
@ -238,23 +245,23 @@ class Less_Parser {
|
|||
$variables = [];
|
||||
|
||||
$not_variable_type = [
|
||||
'Comment', // this include less comments ( // ) and css comments (/* */)
|
||||
'Import', // do not search variables in included files @import
|
||||
'Ruleset', // selectors (.someclass, #someid, …)
|
||||
'Operation', //
|
||||
Less_Tree_Comment::class, // this include less comments ( // ) and css comments (/* */)
|
||||
Less_Tree_Import::class, // do not search variables in included files @import
|
||||
Less_Tree_Ruleset::class, // selectors (.someclass, #someid, …)
|
||||
Less_Tree_Operation::class,
|
||||
];
|
||||
|
||||
// @TODO run compilation if not runned yet
|
||||
foreach ( $this->rules as $key => $rule ) {
|
||||
if ( in_array( $rule->type, $not_variable_type ) ) {
|
||||
if ( in_array( get_class( $rule ), $not_variable_type ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note: it seems rule->type is always Rule when variable = true
|
||||
if ( $rule->type == 'Rule' && $rule->variable ) {
|
||||
// Note: it seems $rule is always Less_Tree_Rule when variable = true
|
||||
if ( $rule instanceof Less_Tree_Rule && $rule->variable ) {
|
||||
$variables[$rule->name] = $this->getVariableValue( $rule );
|
||||
} else {
|
||||
if ( $rule->type == 'Comment' ) {
|
||||
if ( $rule instanceof Less_Tree_Comment ) {
|
||||
$variables[] = $this->getVariableValue( $rule );
|
||||
}
|
||||
}
|
||||
|
@ -321,27 +328,16 @@ class Less_Parser {
|
|||
case Less_Tree_Import::class:
|
||||
case Less_Tree_Ruleset::class:
|
||||
default:
|
||||
throw new Exception( "type missing in switch/case getVariableValue for " . $var->type );
|
||||
throw new Exception( "type missing in switch/case getVariableValue for " . get_class( $var ) );
|
||||
}
|
||||
}
|
||||
|
||||
private function rgb2html( $r, $g = -1, $b = -1 ) {
|
||||
if ( is_array( $r ) && count( $r ) == 3 ) {
|
||||
list( $r, $g, $b ) = $r;
|
||||
[ $r, $g, $b ] = $r;
|
||||
}
|
||||
|
||||
$r = intval( $r );
|
||||
$g = intval( $g );
|
||||
$b = intval( $b );
|
||||
|
||||
$r = dechex( $r < 0 ? 0 : ( $r > 255 ? 255 : $r ) );
|
||||
$g = dechex( $g < 0 ? 0 : ( $g > 255 ? 255 : $g ) );
|
||||
$b = dechex( $b < 0 ? 0 : ( $b > 255 ? 255 : $b ) );
|
||||
|
||||
$color = ( strlen( $r ) < 2 ? '0' : '' ) . $r;
|
||||
$color .= ( strlen( $g ) < 2 ? '0' : '' ) . $g;
|
||||
$color .= ( strlen( $b ) < 2 ? '0' : '' ) . $b;
|
||||
return '#' . $color;
|
||||
return sprintf( '#%02x%02x%02x', $r, $g, $b );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -393,7 +389,7 @@ $g = intval( $g );
|
|||
* @throws Less_Exception_Parser If the compiler encounters invalid syntax
|
||||
* @param string $str The string to convert
|
||||
* @param string|null $file_uri The url of the file
|
||||
* @return Less_Parser
|
||||
* @return $this
|
||||
*/
|
||||
public function parse( $str, $file_uri = null ) {
|
||||
if ( !$file_uri ) {
|
||||
|
@ -426,7 +422,7 @@ $g = intval( $g );
|
|||
* @param string $filename The file to parse
|
||||
* @param string $uri_root The url of the file
|
||||
* @param bool $returnRoot Indicates whether the return value should be a css string a root node
|
||||
* @return Less_Tree_Ruleset|Less_Parser
|
||||
* @return Less_Tree_Ruleset|$this
|
||||
*/
|
||||
public function parseFile( $filename, $uri_root = '', $returnRoot = false ) {
|
||||
if ( !file_exists( $filename ) ) {
|
||||
|
@ -468,7 +464,7 @@ $g = intval( $g );
|
|||
/**
|
||||
* Allows a user to set variables values
|
||||
* @param array $vars
|
||||
* @return Less_Parser
|
||||
* @return $this
|
||||
*/
|
||||
public function ModifyVars( $vars ) {
|
||||
$this->input = self::serializeVars( $vars );
|
||||
|
@ -604,11 +600,9 @@ $g = intval( $g );
|
|||
$cache_file = $this->CacheFile( $file_path );
|
||||
if ( $cache_file ) {
|
||||
if ( self::$options['cache_method'] == 'callback' ) {
|
||||
if ( is_callable( self::$options['cache_callback_get'] ) ) {
|
||||
$cache = call_user_func_array(
|
||||
self::$options['cache_callback_get'],
|
||||
[ $this, $file_path, $cache_file ]
|
||||
);
|
||||
$callback = self::$options['cache_callback_get'];
|
||||
if ( is_callable( $callback ) ) {
|
||||
$cache = $callback( $this, $file_path, $cache_file );
|
||||
|
||||
if ( $cache ) {
|
||||
$this->UnsetInput();
|
||||
|
@ -643,13 +637,10 @@ $g = intval( $g );
|
|||
// save the cache
|
||||
if ( $cache_file ) {
|
||||
if ( self::$options['cache_method'] == 'callback' ) {
|
||||
if ( is_callable( self::$options['cache_callback_set'] ) ) {
|
||||
call_user_func_array(
|
||||
self::$options['cache_callback_set'],
|
||||
[ $this, $file_path, $cache_file, $rules ]
|
||||
);
|
||||
$callback = self::$options['cache_callback_set'];
|
||||
if ( is_callable( $callback ) ) {
|
||||
$callback( $this, $file_path, $cache_file, $rules );
|
||||
}
|
||||
|
||||
} else {
|
||||
switch ( self::$options['cache_method'] ) {
|
||||
case 'serialize':
|
||||
|
@ -709,22 +700,22 @@ $g = intval( $g );
|
|||
}
|
||||
}
|
||||
|
||||
static function AddParsedFile( $file ) {
|
||||
public static function AddParsedFile( $file ) {
|
||||
self::$imports[] = $file;
|
||||
}
|
||||
|
||||
static function AllParsedFiles() {
|
||||
public static function AllParsedFiles() {
|
||||
return self::$imports;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
*/
|
||||
static function FileParsed( $file ) {
|
||||
public static function FileParsed( $file ) {
|
||||
return in_array( $file, self::$imports );
|
||||
}
|
||||
|
||||
function save() {
|
||||
public function save() {
|
||||
$this->saveStack[] = $this->pos;
|
||||
}
|
||||
|
||||
|
@ -815,39 +806,6 @@ $g = intval( $g );
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
* @see less-2.5.3.js#parserInput.$quoted
|
||||
*/
|
||||
private function MatchQuoted() {
|
||||
$startChar = $this->input[$this->pos] ?? null;
|
||||
if ( $startChar !== "'" && $startChar !== '"' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
while ( $this->pos + $i < $this->input_len ) {
|
||||
$nextChar = $this->input[$this->pos + $i];
|
||||
switch ( $nextChar ) {
|
||||
case "\\":
|
||||
$i++;
|
||||
break;
|
||||
case "\r":
|
||||
case "\n":
|
||||
return;
|
||||
case $startChar:
|
||||
$i++;
|
||||
$matched = substr( $this->input, $this->pos, $i );
|
||||
$this->skipWhitespace( $i );
|
||||
return $matched;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as match(), but don't change the state of the parser,
|
||||
* just return the match.
|
||||
|
@ -872,14 +830,8 @@ $g = intval( $g );
|
|||
*/
|
||||
public function skipWhitespace( $length ) {
|
||||
$this->pos += $length;
|
||||
|
||||
for ( ; $this->pos < $this->input_len; $this->pos++ ) {
|
||||
$c = $this->input[$this->pos];
|
||||
|
||||
if ( ( $c !== "\n" ) && ( $c !== "\r" ) && ( $c !== "\t" ) && ( $c !== ' ' ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Optimization: Skip over irrelevant chars without slow loop
|
||||
$this->pos += strspn( $this->input, "\n\r\t ", $this->pos );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1040,20 +992,49 @@ $g = intval( $g );
|
|||
* @see less-2.5.3.js#entities.quoted
|
||||
*/
|
||||
private function parseEntitiesQuoted() {
|
||||
$index = $this->pos;
|
||||
|
||||
$this->save();
|
||||
|
||||
$isEscaped = $this->MatchChar( '~' ) !== null;
|
||||
$str = $this->MatchQuoted();
|
||||
if ( $str === null ) {
|
||||
$this->restore();
|
||||
// Optimization: Determine match potential without save()/restore() overhead
|
||||
// Optimization: Inline MatchChar() here, with its skipWhitespace(1) call below
|
||||
$startChar = $this->input[$this->pos] ?? null;
|
||||
$isEscaped = $startChar === '~';
|
||||
if ( !$isEscaped && $startChar !== "'" && $startChar !== '"' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->forget();
|
||||
$index = $this->pos;
|
||||
$this->save();
|
||||
|
||||
return new Less_Tree_Quoted( $str[0], substr( $str, 1, -1 ), $isEscaped, $index, $this->env->currentFileInfo );
|
||||
if ( $isEscaped ) {
|
||||
$this->skipWhitespace( 1 );
|
||||
$startChar = $this->input[$this->pos] ?? null;
|
||||
if ( $startChar !== "'" && $startChar !== '"' ) {
|
||||
$this->restore();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Optimization: Inline matching of quotes for 8% overall speed up
|
||||
// on large LESS files. https://gerrit.wikimedia.org/r/939727
|
||||
// @see less-2.5.3.js#parserInput.$quoted
|
||||
$i = 1;
|
||||
while ( $this->pos + $i < $this->input_len ) {
|
||||
// Optimization: Skip over irrelevant chars without slow loop
|
||||
$i += strcspn( $this->input, "\n\r$startChar\\", $this->pos + $i );
|
||||
switch ( $this->input[$this->pos + $i++] ) {
|
||||
case "\\":
|
||||
$i++;
|
||||
break;
|
||||
case "\r":
|
||||
case "\n":
|
||||
break 2;
|
||||
case $startChar:
|
||||
$str = substr( $this->input, $this->pos, $i );
|
||||
$this->skipWhitespace( $i );
|
||||
$this->forget();
|
||||
return new Less_Tree_Quoted( $str[0], substr( $str, 1, -1 ), $isEscaped, $index, $this->env->currentFileInfo );
|
||||
}
|
||||
}
|
||||
|
||||
$this->restore();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1068,7 +1049,7 @@ $g = intval( $g );
|
|||
$k = $this->MatchReg( '/\\G%|\\G[_A-Za-z-][_A-Za-z0-9-]*/' );
|
||||
if ( $k ) {
|
||||
$k = $k[0];
|
||||
$color = $this->fromKeyword( $k );
|
||||
$color = Less_Tree_Color::fromKeyword( $k );
|
||||
if ( $color ) {
|
||||
return $color;
|
||||
}
|
||||
|
@ -1076,20 +1057,6 @@ $g = intval( $g );
|
|||
}
|
||||
}
|
||||
|
||||
// duplicate of Less_Tree_Color::FromKeyword
|
||||
private function FromKeyword( $keyword ) {
|
||||
$keyword = strtolower( $keyword );
|
||||
|
||||
if ( Less_Colors::hasOwnProperty( $keyword ) ) {
|
||||
// detect named color
|
||||
return new Less_Tree_Color( substr( Less_Colors::color( $keyword ), 1 ) );
|
||||
}
|
||||
|
||||
if ( $keyword === 'transparent' ) {
|
||||
return new Less_Tree_Color( [ 0, 0, 0 ], 0, true );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// A function call
|
||||
//
|
||||
|
@ -1200,15 +1167,14 @@ $g = intval( $g );
|
|||
return;
|
||||
}
|
||||
|
||||
$value = $this->matcher( [ 'parseEntitiesQuoted','parseEntitiesVariable','/\\Gdata\:.*?[^\)]+/','/\\G(?:(?:\\\\[\(\)\'"])|[^\(\)\'"])+/' ] );
|
||||
$value = $this->matcher( [ 'parseEntitiesQuoted', 'parseEntitiesVariable', '/\\Gdata\:.*?[^\)]+/', '/\\G(?:(?:\\\\[\(\)\'"])|[^\(\)\'"])+/' ] );
|
||||
if ( !$value ) {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
$this->expectChar( ')' );
|
||||
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty
|
||||
if ( isset( $value->value ) || $value instanceof Less_Tree_Variable ) {
|
||||
if ( $value instanceof Less_Tree_Quoted || $value instanceof Less_Tree_Variable ) {
|
||||
return new Less_Tree_Url( $value, $this->env->currentFileInfo );
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1222,7 @@ $g = intval( $g );
|
|||
*/
|
||||
private function parseEntitiesColor() {
|
||||
if ( $this->PeekChar( '#' ) && ( $rgb = $this->MatchReg( '/\\G#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/' ) ) ) {
|
||||
return new Less_Tree_Color( $rgb[1] );
|
||||
return new Less_Tree_Color( $rgb[1], 1, null, $rgb[0] );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1275,7 +1241,7 @@ $g = intval( $g );
|
|||
return;
|
||||
}
|
||||
|
||||
$value = $this->MatchReg( '/\\G([+-]?\d*\.?\d+)(%|[a-z]+)?/' );
|
||||
$value = $this->MatchReg( '/\\G([+-]?\d*\.?\d+)(%|[a-z]+)?/i' );
|
||||
if ( $value ) {
|
||||
if ( isset( $value[2] ) ) {
|
||||
return new Less_Tree_Dimension( $value[1], $value[2] );
|
||||
|
@ -1291,7 +1257,13 @@ $g = intval( $g );
|
|||
*
|
||||
* @return Less_Tree_UnicodeDescriptor|null
|
||||
*/
|
||||
function parseUnicodeDescriptor() {
|
||||
public function parseUnicodeDescriptor() {
|
||||
// Optimization: Hardcode first char, to avoid MatchReg() cost for common case
|
||||
$char = $this->input[$this->pos] ?? null;
|
||||
if ( $char !== 'U' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ud = $this->MatchReg( '/\\G(U\+[0-9a-fA-F?]+)(\-[0-9a-fA-F?]+)?/' );
|
||||
if ( $ud ) {
|
||||
return new Less_Tree_UnicodeDescriptor( $ud[0] );
|
||||
|
@ -1303,24 +1275,35 @@ $g = intval( $g );
|
|||
*
|
||||
* `window.location.href`
|
||||
*
|
||||
* @return Less_Tree_Javascript|null
|
||||
* @return Less_Tree_JavaScript|null
|
||||
* @see less-2.5.3.js#parsers.entities.javascript
|
||||
*/
|
||||
private function parseEntitiesJavascript() {
|
||||
$index = $this->pos;
|
||||
|
||||
$this->save();
|
||||
|
||||
$isEscaped = $this->MatchChar( '~' ) !== null;
|
||||
$jsQuote = $this->MatchChar( '`' ) !== null;
|
||||
if ( !$jsQuote ) {
|
||||
$this->restore();
|
||||
// Optimization: Hardcode first char, to avoid save()/restore() overhead
|
||||
// Optimization: Inline MatchChar(), with skipWhitespace(1) below
|
||||
$char = $this->input[$this->pos] ?? null;
|
||||
$isEscaped = $char === '~';
|
||||
if ( !$isEscaped && $char !== '`' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$index = $this->pos;
|
||||
$this->save();
|
||||
|
||||
if ( $isEscaped ) {
|
||||
$this->skipWhitespace( 1 );
|
||||
$char = $this->input[$this->pos] ?? null;
|
||||
if ( $char !== '`' ) {
|
||||
$this->restore();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->skipWhitespace( 1 );
|
||||
$js = $this->MatchReg( '/\\G[^`]*`/' );
|
||||
if ( $js ) {
|
||||
$this->forget();
|
||||
return new Less_Tree_Javascript( substr( $js[0], 0, -1 ), $index, $isEscaped );
|
||||
return new Less_Tree_JavaScript( substr( $js[0], 0, -1 ), $index, $isEscaped );
|
||||
}
|
||||
$this->restore();
|
||||
}
|
||||
|
@ -1352,7 +1335,7 @@ $g = intval( $g );
|
|||
//
|
||||
// extend syntax - used to extend selectors
|
||||
//
|
||||
function parseExtend( $isRule = false ) {
|
||||
public function parseExtend( $isRule = false ) {
|
||||
$index = $this->pos;
|
||||
$extendList = [];
|
||||
|
||||
|
@ -1365,7 +1348,8 @@ $g = intval( $g );
|
|||
$elements = [];
|
||||
while ( true ) {
|
||||
$option = $this->MatchReg( '/\\G(all)(?=\s*(\)|,))/' );
|
||||
if ( $option ) { break;
|
||||
if ( $option ) {
|
||||
break;
|
||||
}
|
||||
$e = $this->parseElement();
|
||||
if ( !$e ) {
|
||||
|
@ -1499,7 +1483,7 @@ $g = intval( $g );
|
|||
|
||||
if ( $isCall ) {
|
||||
// Variable
|
||||
if ( property_exists( $arg, 'value' ) && count( $arg->value ) == 1 ) {
|
||||
if ( $value instanceof Less_Tree_Expression && count( $arg->value ) == 1 ) {
|
||||
$val = $arg->value[0];
|
||||
}
|
||||
} else {
|
||||
|
@ -1661,7 +1645,13 @@ $g = intval( $g );
|
|||
// and can be found inside a rule's value.
|
||||
//
|
||||
private function parseEntity() {
|
||||
return $this->parseEntitiesLiteral() ?? $this->parseEntitiesVariable() ?? $this->parseEntitiesUrl() ?? $this->parseEntitiesCall() ?? $this->parseEntitiesKeyword() ?? $this->parseEntitiesJavascript() ?? $this->parseComment();
|
||||
return $this->parseEntitiesLiteral() ??
|
||||
$this->parseEntitiesVariable() ??
|
||||
$this->parseEntitiesUrl() ??
|
||||
$this->parseEntitiesCall() ??
|
||||
$this->parseEntitiesKeyword() ??
|
||||
$this->parseEntitiesJavascript() ??
|
||||
$this->parseComment();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1843,7 +1833,7 @@ $g = intval( $g );
|
|||
}
|
||||
|
||||
private function parseTag() {
|
||||
return ( $tag = $this->MatchReg( '/\\G[A-Za-z][A-Za-z-]*[0-9]?/' ) ) ? $tag : $this->MatchChar( '*' );
|
||||
return $this->MatchReg( '/\\G[A-Za-z][A-Za-z-]*[0-9]?/' ) ?: $this->MatchChar( '*' );
|
||||
}
|
||||
|
||||
private function parseAttribute() {
|
||||
|
@ -1860,7 +1850,7 @@ $g = intval( $g );
|
|||
|
||||
$op = $this->MatchReg( '/\\G[|~*$^]?=/' );
|
||||
if ( $op ) {
|
||||
$val = $this->matcher( [ 'parseEntitiesQuoted','/\\G[0-9]+%/','/\\G[\w-]+/','parseEntitiesVariableCurly' ] );
|
||||
$val = $this->matcher( [ 'parseEntitiesQuoted', '/\\G[0-9]+%/', '/\\G[\w-]+/', 'parseEntitiesVariableCurly' ] );
|
||||
}
|
||||
|
||||
$this->expectChar( ']' );
|
||||
|
@ -2042,7 +2032,7 @@ $g = intval( $g );
|
|||
}
|
||||
}
|
||||
|
||||
function parseAnonymousValue() {
|
||||
public function parseAnonymousValue() {
|
||||
$match = $this->MatchReg( '/\\G([^@+\/\'"*`(;{}-]*);/' );
|
||||
if ( $match ) {
|
||||
return new Less_Tree_Anonymous( $match[1] );
|
||||
|
@ -2091,7 +2081,7 @@ $g = intval( $g );
|
|||
if ( !$this->MatchChar( '(' ) ) {
|
||||
return $options;
|
||||
}
|
||||
do{
|
||||
do {
|
||||
$optionName = $this->parseImportOption();
|
||||
if ( $optionName ) {
|
||||
$value = true;
|
||||
|
@ -2106,10 +2096,11 @@ $g = intval( $g );
|
|||
break;
|
||||
}
|
||||
$options[$optionName] = $value;
|
||||
if ( !$this->MatchChar( ',' ) ) { break;
|
||||
if ( !$this->MatchChar( ',' ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while ( $optionName );
|
||||
} while ( $optionName );
|
||||
$this->expectChar( ')' );
|
||||
return $options;
|
||||
}
|
||||
|
@ -2124,7 +2115,7 @@ $g = intval( $g );
|
|||
private function parseMediaFeature() {
|
||||
$nodes = [];
|
||||
|
||||
do{
|
||||
do {
|
||||
$e = $this->parseEntitiesKeyword() ?? $this->parseEntitiesVariable();
|
||||
if ( $e ) {
|
||||
$nodes[] = $e;
|
||||
|
@ -2317,7 +2308,7 @@ $g = intval( $g );
|
|||
private function parseValue() {
|
||||
$expressions = [];
|
||||
|
||||
do{
|
||||
do {
|
||||
$e = $this->parseExpression();
|
||||
if ( $e ) {
|
||||
$expressions[] = $e;
|
||||
|
@ -2353,7 +2344,7 @@ $g = intval( $g );
|
|||
*
|
||||
* @return Less_Tree_Operation|null
|
||||
*/
|
||||
function parseMultiplication() {
|
||||
public function parseMultiplication() {
|
||||
$return = $m = $this->parseOperand();
|
||||
if ( $return ) {
|
||||
while ( true ) {
|
||||
|
@ -2374,7 +2365,8 @@ $g = intval( $g );
|
|||
|
||||
$a = $this->parseOperand();
|
||||
|
||||
if ( !$a ) { break;
|
||||
if ( !$a ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$m->parensInOp = true;
|
||||
|
@ -2402,7 +2394,7 @@ $g = intval( $g );
|
|||
$op = $op[0];
|
||||
} else {
|
||||
if ( !$isSpaced ) {
|
||||
$op = $this->matcher( [ '#+','#-' ] );
|
||||
$op = $this->matcher( [ '#+', '#-' ] );
|
||||
}
|
||||
if ( !$op ) {
|
||||
break;
|
|
@ -75,3 +75,8 @@ Less.php can be used with [Drupal's less module](https://drupal.org/project/less
|
|||
## Credits
|
||||
|
||||
Less.php was originally ported to PHP in 2011 by [Matt Agar](https://github.com/agar) and then updated by [Martin Jantošovič](https://github.com/Mordred) in 2012. From 2013 to 2017, [Josh Schmidt](https://github.com/oyejorge) lead development of the library. Since 2019, the library is maintained by Wikimedia Foundation.
|
||||
|
||||
## Contribute
|
||||
|
||||
* Issue tracker: https://phabricator.wikimedia.org/tag/less.php/
|
||||
* Source code: https://gerrit.wikimedia.org/g/mediawiki/libs/less.php ([Get started with Gerrit](https://www.mediawiki.org/wiki/Gerrit/Tutorial/tl;dr))
|
|
@ -34,14 +34,14 @@ class Less_SourceMap_Base64VLQ {
|
|||
*/
|
||||
private $charToIntMap = [
|
||||
'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6,
|
||||
'H' => 7,'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
|
||||
'H' => 7, 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
|
||||
'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20,
|
||||
'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27,
|
||||
'c' => 28, 'd' => 29, 'e' => 30, 'f' => 31, 'g' => 32, 'h' => 33, 'i' => 34,
|
||||
'j' => 35, 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39, 'o' => 40, 'p' => 41,
|
||||
'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47, 'w' => 48,
|
||||
'x' => 49, 'y' => 50, 'z' => 51, 0 => 52, 1 => 53, 2 => 54, 3 => 55, 4 => 56,
|
||||
5 => 57, 6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63,
|
||||
5 => 57, 6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -111,8 +111,7 @@ class Less_SourceMap_Base64VLQ {
|
|||
public function encode( $aValue ) {
|
||||
$encoded = '';
|
||||
$vlq = $this->toVLQSigned( $aValue );
|
||||
do
|
||||
{
|
||||
do {
|
||||
$digit = $vlq & $this->mask;
|
||||
$vlq = $this->zeroFill( $vlq, $this->shift );
|
||||
if ( $vlq > 0 ) {
|
||||
|
@ -133,8 +132,7 @@ class Less_SourceMap_Base64VLQ {
|
|||
public function decode( $encoded ) {
|
||||
$vlq = 0;
|
||||
$i = 0;
|
||||
do
|
||||
{
|
||||
do {
|
||||
$digit = $this->base64Decode( $encoded[$i] );
|
||||
$vlq |= ( $digit & $this->mask ) << ( $i * $this->shift );
|
||||
$i++;
|
||||
|
@ -163,7 +161,7 @@ class Less_SourceMap_Base64VLQ {
|
|||
*/
|
||||
public function base64Encode( $number ) {
|
||||
if ( $number < 0 || $number > 63 ) {
|
||||
throw new Exception( sprintf( 'Invalid number "%s" given. Must be between 0 and 63.', (string)$number ) );
|
||||
throw new Exception( "Invalid number \"$number\" given. Must be between 0 and 63." );
|
||||
}
|
||||
return $this->intToCharMap[$number];
|
||||
}
|
|
@ -2,16 +2,9 @@
|
|||
|
||||
/**
|
||||
* Tree
|
||||
*
|
||||
* TODO: Callers often use `property_exists(, 'value')` to distinguish
|
||||
* tree nodes that are considerd value-holding. Refactor this to move
|
||||
* the 'value' property that most subclasses implement to there, and use
|
||||
* something else (special value, method, or intermediate class?) to
|
||||
* signal whether a subclass is considered value-holding.
|
||||
*/
|
||||
class Less_Tree {
|
||||
|
||||
public $cache_string;
|
||||
public $parensInOp = false;
|
||||
public $extendOnEveryPath;
|
||||
public $allExtends;
|
||||
|
@ -71,6 +64,63 @@ class Less_Tree {
|
|||
public function accept( $visitor ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Tree $a
|
||||
* @param Less_Tree $b
|
||||
* @return int|null
|
||||
* @see less-2.5.3.js#Node.compare
|
||||
*/
|
||||
public static function nodeCompare( $a, $b ) {
|
||||
// Less_Tree subclasses that implement compare() are:
|
||||
// Anonymous, Color, Dimension, Keyword, Quoted, Unit
|
||||
if ( $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Anonymous ) {
|
||||
// for "symmetric results" force toCSS-based comparison via b.compare()
|
||||
// of Quoted or Anonymous if either value is one of those
|
||||
return -$b->compare( $a );
|
||||
} elseif ( $a instanceof Less_Tree_Anonymous || $a instanceof Less_Tree_Color
|
||||
|| $a instanceof Less_Tree_Dimension || $a instanceof Less_Tree_Keyword
|
||||
|| $a instanceof Less_Tree_Quoted || $a instanceof Less_Tree_Unit
|
||||
) {
|
||||
return $a->compare( $b );
|
||||
} elseif ( get_class( $a ) !== get_class( $b ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Less_Tree subclasses that have an array value: Less_Tree_Expression, Less_Tree_Value
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty
|
||||
$aval = $a->value ?? [];
|
||||
// @phan-suppress-next-line PhanUndeclaredProperty
|
||||
$bval = $b->value ?? [];
|
||||
if ( !( $a instanceof Less_Tree_Expression || $a instanceof Less_Tree_Value ) ) {
|
||||
return $aval === $bval ? 0 : null;
|
||||
}
|
||||
if ( count( $aval ) !== count( $bval ) ) {
|
||||
return null;
|
||||
}
|
||||
foreach ( $aval as $i => $item ) {
|
||||
if ( self::nodeCompare( $item, $bval[$i] ) !== 0 ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|float|int $a
|
||||
* @param string|float|int $b
|
||||
* @return int|null
|
||||
* @see less-2.5.3.js#Node.numericCompare
|
||||
*/
|
||||
public static function numericCompare( $a, $b ) {
|
||||
return $a < $b ? -1
|
||||
: ( $a === $b ? 0
|
||||
: ( $a > $b ? 1
|
||||
// NAN is not greater, less, or equal
|
||||
: null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function ReferencedArray( $rules ) {
|
||||
foreach ( $rules as $rule ) {
|
||||
if ( method_exists( $rule, 'markReferenced' ) ) {
|
|
@ -2,9 +2,8 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Alpha extends Less_Tree {
|
||||
class Less_Tree_Alpha extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
public $value;
|
||||
public $type = 'Alpha';
|
||||
|
||||
public function __construct( $val ) {
|
||||
$this->value = $val;
|
58
include/thirdparty/less.php/___4.2/Tree/Anonymous.php
vendored
Normal file
58
include/thirdparty/less.php/___4.2/Tree/Anonymous.php
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Anonymous.prototype
|
||||
*/
|
||||
class Less_Tree_Anonymous extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
public $value;
|
||||
public $quote;
|
||||
public $index;
|
||||
public $mapLines;
|
||||
public $currentFileInfo;
|
||||
/** @var bool */
|
||||
public $rulesetLike;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param int|null $index
|
||||
* @param array|null $currentFileInfo
|
||||
* @param bool|null $mapLines
|
||||
* @param bool $rulesetLike
|
||||
*/
|
||||
public function __construct( $value, $index = null, $currentFileInfo = null, $mapLines = null, $rulesetLike = false ) {
|
||||
$this->value = $value;
|
||||
$this->index = $index;
|
||||
$this->mapLines = $mapLines;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
$this->rulesetLike = $rulesetLike;
|
||||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
return new self( $this->value, $this->index, $this->currentFileInfo, $this->mapLines );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Tree|mixed $x
|
||||
* @return int|null
|
||||
* @see less-2.5.3.js#Anonymous.prototype.compare
|
||||
*/
|
||||
public function compare( $x ) {
|
||||
return ( is_object( $x ) && $this->toCSS() === $x->toCSS() ) ? 0 : null;
|
||||
}
|
||||
|
||||
public function isRulesetLike() {
|
||||
return $this->rulesetLike;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( $this->value, $this->currentFileInfo, $this->index, $this->mapLines );
|
||||
}
|
||||
|
||||
public function toCSS() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,10 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Assignment extends Less_Tree {
|
||||
class Less_Tree_Assignment extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $key;
|
||||
public $value;
|
||||
public $type = 'Assignment';
|
||||
|
||||
public function __construct( $key, $val ) {
|
||||
$this->key = $key;
|
||||
|
@ -18,7 +17,7 @@ class Less_Tree_Assignment extends Less_Tree {
|
|||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
return new Less_Tree_Assignment( $this->key, $this->value->compile( $env ) );
|
||||
return new self( $this->key, $this->value->compile( $env ) );
|
||||
}
|
||||
|
||||
/**
|
|
@ -2,12 +2,11 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Attribute extends Less_Tree {
|
||||
class Less_Tree_Attribute extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $key;
|
||||
public $op;
|
||||
public $value;
|
||||
public $type = 'Attribute';
|
||||
|
||||
public function __construct( $key, $op, $value ) {
|
||||
$this->key = $key;
|
||||
|
@ -23,7 +22,7 @@ class Less_Tree_Attribute extends Less_Tree {
|
|||
return $this;
|
||||
}
|
||||
|
||||
return new Less_Tree_Attribute(
|
||||
return new self(
|
||||
$key_obj ? $this->key->compile( $env ) : $this->key,
|
||||
$this->op,
|
||||
$val_obj ? $this->value->compile( $env ) : $this->value );
|
|
@ -3,7 +3,7 @@
|
|||
* @private
|
||||
* @see less.tree.Call in less.js 3.0.0 https://github.com/less/less.js/blob/v3.0.0/dist/less.js#L6336
|
||||
*/
|
||||
class Less_Tree_Call extends Less_Tree {
|
||||
class Less_Tree_Call extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
public $value;
|
||||
|
||||
public $name;
|
||||
|
@ -12,7 +12,6 @@ class Less_Tree_Call extends Less_Tree {
|
|||
public $mathOn;
|
||||
public $index;
|
||||
public $currentFileInfo;
|
||||
public $type = 'Call';
|
||||
|
||||
public function __construct( $name, $args, $index, $currentFileInfo = null ) {
|
||||
$this->name = $name;
|
||||
|
@ -47,24 +46,35 @@ class Less_Tree_Call extends Less_Tree {
|
|||
$args[] = $a->compile( $env );
|
||||
}
|
||||
|
||||
foreach ( $args as $key => $arg ) {
|
||||
if ( $arg instanceof Less_Tree_Expression ) {
|
||||
$arg->throwAwayComments();
|
||||
|
||||
if ( count( $arg->value ) === 1 ) {
|
||||
$subNode = $arg->value[0];
|
||||
array_splice( $args, $key, 1, [ $subNode ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Less_Environment::$mathOn = $currentMathContext;
|
||||
|
||||
$nameLC = strtolower( $this->name );
|
||||
switch ( $nameLC ) {
|
||||
case '%':
|
||||
$nameLC = '_percent';
|
||||
$nameLC = '_percent';
|
||||
break;
|
||||
|
||||
case 'get-unit':
|
||||
$nameLC = 'getunit';
|
||||
$nameLC = 'getunit';
|
||||
break;
|
||||
|
||||
case 'data-uri':
|
||||
$nameLC = 'datauri';
|
||||
$nameLC = 'datauri';
|
||||
break;
|
||||
|
||||
case 'svg-gradient':
|
||||
$nameLC = 'svggradient';
|
||||
$nameLC = 'svggradient';
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -73,7 +83,7 @@ class Less_Tree_Call extends Less_Tree {
|
|||
$result = Less_Tree_DefaultFunc::compile();
|
||||
} else {
|
||||
$func = null;
|
||||
if ( method_exists( 'Less_Functions', $nameLC ) ) {
|
||||
if ( method_exists( Less_Functions::class, $nameLC ) ) {
|
||||
$functions = new Less_Functions( $env, $this->currentFileInfo );
|
||||
$func = [ $functions, $nameLC ];
|
||||
} elseif ( isset( $env->functions[$nameLC] ) && is_callable( $env->functions[$nameLC] ) ) {
|
||||
|
@ -82,7 +92,7 @@ class Less_Tree_Call extends Less_Tree {
|
|||
// If the function name isn't known to LESS, output it unchanged as CSS.
|
||||
if ( $func ) {
|
||||
try {
|
||||
$result = call_user_func_array( $func, $args );
|
||||
$result = $func( ...$args );
|
||||
} catch ( Exception $e ) {
|
||||
// Preserve original trace, especially from custom functions.
|
||||
// https://github.com/wikimedia/less.php/issues/38
|
||||
|
@ -99,7 +109,7 @@ class Less_Tree_Call extends Less_Tree {
|
|||
return $result;
|
||||
}
|
||||
|
||||
return new Less_Tree_Call( $this->name, $args, $this->index, $this->currentFileInfo );
|
||||
return new self( $this->name, $args, $this->index, $this->currentFileInfo );
|
||||
}
|
||||
|
||||
/**
|
|
@ -6,15 +6,18 @@ class Less_Tree_Color extends Less_Tree {
|
|||
public $rgb;
|
||||
public $alpha;
|
||||
public $isTransparentKeyword;
|
||||
public $type = 'Color';
|
||||
public $value;
|
||||
|
||||
public function __construct( $rgb, $a = 1, $isTransparentKeyword = null ) {
|
||||
public function __construct( $rgb, $a = 1, $isTransparentKeyword = null, $originalForm = null ) {
|
||||
if ( $isTransparentKeyword ) {
|
||||
$this->rgb = $rgb;
|
||||
$this->alpha = $a;
|
||||
$this->isTransparentKeyword = true;
|
||||
return;
|
||||
}
|
||||
if ( isset( $originalForm ) ) {
|
||||
$this->value = $originalForm;
|
||||
}
|
||||
|
||||
$this->rgb = [];
|
||||
if ( is_array( $rgb ) ) {
|
||||
|
@ -53,7 +56,9 @@ class Less_Tree_Color extends Less_Tree {
|
|||
public function toCSS( $doNotCompress = false ) {
|
||||
$compress = Less_Parser::$options['compress'] && !$doNotCompress;
|
||||
$alpha = Less_Functions::fround( $this->alpha );
|
||||
|
||||
if ( $this->value ) {
|
||||
return $this->value;
|
||||
}
|
||||
//
|
||||
// If we have some transparency, the only way to represent it
|
||||
// is via `rgba`. Otherwise, we use the hex representation,
|
||||
|
@ -98,7 +103,7 @@ class Less_Tree_Color extends Less_Tree {
|
|||
|
||||
/**
|
||||
* @param string $op
|
||||
* @param Less_Tree_Color $other
|
||||
* @param self $other
|
||||
*/
|
||||
public function operate( $op, $other ) {
|
||||
$rgb = [];
|
||||
|
@ -106,7 +111,7 @@ class Less_Tree_Color extends Less_Tree {
|
|||
for ( $c = 0; $c < 3; $c++ ) {
|
||||
$rgb[$c] = Less_Functions::operate( $op, $this->rgb[$c], $other->rgb[$c] );
|
||||
}
|
||||
return new Less_Tree_Color( $rgb, $alpha );
|
||||
return new self( $rgb, $alpha );
|
||||
}
|
||||
|
||||
public function toRGB() {
|
||||
|
@ -186,15 +191,20 @@ class Less_Tree_Color extends Less_Tree {
|
|||
return $this->toHex( $argb );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $x
|
||||
* @return int|null
|
||||
* @see less-2.5.3.js#Color.prototype.compare
|
||||
*/
|
||||
public function compare( $x ) {
|
||||
if ( !property_exists( $x, 'rgb' ) ) {
|
||||
if ( !$x instanceof self ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ( $x->rgb[0] === $this->rgb[0] &&
|
||||
$x->rgb[1] === $this->rgb[1] &&
|
||||
$x->rgb[2] === $this->rgb[2] &&
|
||||
$x->alpha === $this->alpha ) ? 0 : -1;
|
||||
$x->alpha === $this->alpha ) ? 0 : null;
|
||||
}
|
||||
|
||||
public function toHex( $v ) {
|
||||
|
@ -214,15 +224,20 @@ class Less_Tree_Color extends Less_Tree {
|
|||
* @param string $keyword
|
||||
*/
|
||||
public static function fromKeyword( $keyword ) {
|
||||
$keyword = strtolower( $keyword );
|
||||
$c = $keyword = strtolower( $keyword );
|
||||
|
||||
if ( Less_Colors::hasOwnProperty( $keyword ) ) {
|
||||
// detect named color
|
||||
return new Less_Tree_Color( substr( Less_Colors::color( $keyword ), 1 ) );
|
||||
$c = new self( substr( Less_Colors::color( $keyword ), 1 ) );
|
||||
}
|
||||
|
||||
if ( $keyword === 'transparent' ) {
|
||||
return new Less_Tree_Color( [ 0, 0, 0 ], 0, true );
|
||||
$c = new self( [ 0, 0, 0 ], 0, true );
|
||||
}
|
||||
|
||||
if ( isset( $c ) && is_object( $c ) ) {
|
||||
$c->value = $keyword;
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,12 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Comment extends Less_Tree {
|
||||
class Less_Tree_Comment extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $value;
|
||||
public $silent;
|
||||
public $isReferenced;
|
||||
public $currentFileInfo;
|
||||
public $type = 'Comment';
|
||||
|
||||
public function __construct( $value, $silent, $index = null, $currentFileInfo = null ) {
|
||||
$this->value = $value;
|
|
@ -9,7 +9,6 @@ class Less_Tree_Condition extends Less_Tree {
|
|||
public $rvalue;
|
||||
public $index;
|
||||
public $negate;
|
||||
public $type = 'Condition';
|
||||
|
||||
public function __construct( $op, $l, $r, $i = 0, $negate = false ) {
|
||||
$this->op = trim( $op );
|
||||
|
@ -24,6 +23,11 @@ class Less_Tree_Condition extends Less_Tree {
|
|||
$this->rvalue = $visitor->visitObj( $this->rvalue );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @return bool
|
||||
* @see less-2.5.3.js#Condition.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$a = $this->lvalue->compile( $env );
|
||||
$b = $this->rvalue->compile( $env );
|
||||
|
@ -38,26 +42,18 @@ class Less_Tree_Condition extends Less_Tree {
|
|||
break;
|
||||
|
||||
default:
|
||||
if ( Less_Parser::is_method( $a, 'compare' ) ) {
|
||||
$result = $a->compare( $b );
|
||||
} elseif ( Less_Parser::is_method( $b, 'compare' ) ) {
|
||||
$result = $b->compare( $a );
|
||||
} else {
|
||||
throw new Less_Exception_Compiler( 'Unable to perform comparison', null, $this->index );
|
||||
}
|
||||
|
||||
switch ( $result ) {
|
||||
switch ( Less_Tree::nodeCompare( $a, $b ) ) {
|
||||
case -1:
|
||||
$result = $this->op === '<' || $this->op === '=<' || $this->op === '<=';
|
||||
$result = $this->op === '<' || $this->op === '=<' || $this->op === '<=';
|
||||
break;
|
||||
|
||||
case 0:
|
||||
$result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<=';
|
||||
$result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<=';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
$result = $this->op === '>' || $this->op === '>=';
|
||||
$result = $this->op === '>' || $this->op === '>=';
|
||||
break;
|
||||
default:
|
||||
$result = false;
|
||||
}
|
||||
break;
|
||||
}
|
|
@ -4,8 +4,8 @@
|
|||
*/
|
||||
class Less_Tree_DefaultFunc {
|
||||
|
||||
static $error_;
|
||||
static $value_;
|
||||
private static $error_;
|
||||
private static $value_;
|
||||
|
||||
public static function compile() {
|
||||
if ( self::$error_ ) {
|
|
@ -6,7 +6,6 @@ class Less_Tree_DetachedRuleset extends Less_Tree {
|
|||
|
||||
public $ruleset;
|
||||
public $frames;
|
||||
public $type = 'DetachedRuleset';
|
||||
|
||||
public function __construct( $ruleset, $frames = null ) {
|
||||
$this->ruleset = $ruleset;
|
||||
|
@ -23,7 +22,7 @@ class Less_Tree_DetachedRuleset extends Less_Tree {
|
|||
} else {
|
||||
$frames = $env->frames;
|
||||
}
|
||||
return new Less_Tree_DetachedRuleset( $this->ruleset, $frames );
|
||||
return new self( $this->ruleset, $frames );
|
||||
}
|
||||
|
||||
public function callEval( $env ) {
|
|
@ -2,16 +2,16 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Dimension extends Less_Tree {
|
||||
class Less_Tree_Dimension extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
/** @var float */
|
||||
public $value;
|
||||
public $unit;
|
||||
public $type = 'Dimension';
|
||||
|
||||
public function __construct( $value, $unit = null ) {
|
||||
$this->value = floatval( $value );
|
||||
|
||||
if ( $unit && ( $unit instanceof Less_Tree_Unit ) ) {
|
||||
if ( $unit instanceof Less_Tree_Unit ) {
|
||||
$this->unit = $unit;
|
||||
} elseif ( $unit ) {
|
||||
$this->unit = new Less_Tree_Unit( [ $unit ] );
|
||||
|
@ -72,6 +72,7 @@ class Less_Tree_Dimension extends Less_Tree {
|
|||
|
||||
/**
|
||||
* @param string $op
|
||||
* @param self $other
|
||||
*/
|
||||
public function operate( $op, $other ) {
|
||||
$value = Less_Functions::operate( $op, $this->value, $other->value );
|
||||
|
@ -106,35 +107,31 @@ class Less_Tree_Dimension extends Less_Tree {
|
|||
sort( $unit->denominator );
|
||||
$unit->cancel();
|
||||
}
|
||||
return new Less_Tree_Dimension( $value, $unit );
|
||||
return new self( $value, $unit );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Tree $other
|
||||
* @return int|null
|
||||
* @see less-2.5.3.js#Dimension.prototype.compare
|
||||
*/
|
||||
public function compare( $other ) {
|
||||
if ( $other instanceof Less_Tree_Dimension ) {
|
||||
|
||||
if ( $this->unit->isEmpty() || $other->unit->isEmpty() ) {
|
||||
$a = $this;
|
||||
$b = $other;
|
||||
} else {
|
||||
$a = $this->unify();
|
||||
$b = $other->unify();
|
||||
if ( $a->unit->compare( $b->unit ) !== 0 ) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
$aValue = $a->value;
|
||||
$bValue = $b->value;
|
||||
|
||||
if ( $bValue > $aValue ) {
|
||||
return -1;
|
||||
} elseif ( $bValue < $aValue ) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
if ( !$other instanceof self ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( $this->unit->isEmpty() || $other->unit->isEmpty() ) {
|
||||
$a = $this;
|
||||
$b = $other;
|
||||
} else {
|
||||
$a = $this->unify();
|
||||
$b = $other->unify();
|
||||
if ( $a->unit->compare( $b->unit ) !== 0 ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return Less_Tree::numericCompare( $a->value, $b->value );
|
||||
}
|
||||
|
||||
public function unify() {
|
||||
|
@ -165,7 +162,7 @@ class Less_Tree_Dimension extends Less_Tree {
|
|||
continue;
|
||||
}
|
||||
|
||||
$value = $value * ( $group[$atomicUnit] / $group[$targetUnit] );
|
||||
$value *= $group[$atomicUnit] / $group[$targetUnit];
|
||||
|
||||
$unit->numerator[$i] = $targetUnit;
|
||||
}
|
||||
|
@ -177,7 +174,7 @@ class Less_Tree_Dimension extends Less_Tree {
|
|||
continue;
|
||||
}
|
||||
|
||||
$value = $value / ( $group[$atomicUnit] / $group[$targetUnit] );
|
||||
$value /= $group[$atomicUnit] / $group[$targetUnit];
|
||||
|
||||
$unit->denominator[$i] = $targetUnit;
|
||||
}
|
||||
|
@ -185,6 +182,6 @@ class Less_Tree_Dimension extends Less_Tree {
|
|||
|
||||
$unit->cancel();
|
||||
|
||||
return new Less_Tree_Dimension( $value, $unit );
|
||||
return new self( $value, $unit );
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @see less-2.5.3.js#Anonymous.prototype
|
||||
*/
|
||||
class Less_Tree_Directive extends Less_Tree {
|
||||
|
||||
class Less_Tree_Directive extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
public $name;
|
||||
public $value;
|
||||
public $rules;
|
||||
|
@ -12,7 +12,6 @@ class Less_Tree_Directive extends Less_Tree {
|
|||
public $isRooted;
|
||||
public $currentFileInfo;
|
||||
public $debugInfo;
|
||||
public $type = 'Directive';
|
||||
|
||||
public function __construct( $name, $value = null, $rules = null, $index = null, $isRooted = false, $currentFileInfo = null, $debugInfo = null ) {
|
||||
$this->name = $name;
|
||||
|
@ -46,6 +45,14 @@ class Less_Tree_Directive extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
public function isRulesetLike() {
|
||||
return $this->rules || !$this->isCharset();
|
||||
}
|
||||
|
||||
public function isCharset() {
|
||||
return $this->name === "@charset";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
|
@ -90,7 +97,7 @@ class Less_Tree_Directive extends Less_Tree {
|
|||
$env->mediaPath = $mediaPathBackup;
|
||||
$env->mediaBlocks = $mediaPBlocksBackup;
|
||||
|
||||
return new Less_Tree_Directive( $this->name, $value, $rules, $this->index, $this->isRooted, $this->currentFileInfo, $this->debugInfo );
|
||||
return new self( $this->name, $value, $rules, $this->index, $this->isRooted, $this->currentFileInfo, $this->debugInfo );
|
||||
}
|
||||
|
||||
public function variable( $name ) {
|
||||
|
@ -105,8 +112,6 @@ class Less_Tree_Directive extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
// rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
|
||||
|
||||
public function markReferenced() {
|
||||
$this->isReferenced = true;
|
||||
if ( $this->rules ) {
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Element extends Less_Tree {
|
||||
class Less_Tree_Element extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
/** @var string */
|
||||
public $combinator;
|
||||
|
@ -12,7 +12,6 @@ class Less_Tree_Element extends Less_Tree {
|
|||
public $value;
|
||||
public $index;
|
||||
public $currentFileInfo;
|
||||
public $type = 'Element';
|
||||
|
||||
public $value_is_object = false;
|
||||
|
||||
|
@ -41,7 +40,7 @@ class Less_Tree_Element extends Less_Tree {
|
|||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
return new Less_Tree_Element(
|
||||
return new self(
|
||||
$this->combinator,
|
||||
( $this->value_is_object ? $this->value->compile( $env ) : $this->value ),
|
||||
$this->index,
|
||||
|
@ -63,7 +62,7 @@ class Less_Tree_Element extends Less_Tree {
|
|||
$value = $this->value;
|
||||
}
|
||||
|
||||
if ( $value === '' && $this->combinator && $this->combinator === '&' ) {
|
||||
if ( $value === '' && $this->combinator === '&' ) {
|
||||
return '';
|
||||
}
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Expression extends Less_Tree {
|
||||
/** @var array */
|
||||
class Less_Tree_Expression extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
/** @var Less_Tree[] */
|
||||
public $value = [];
|
||||
public $parens = false;
|
||||
public $type = 'Expression';
|
||||
|
||||
public function __construct( $value, $parens = null ) {
|
||||
$this->value = $value;
|
||||
|
@ -35,11 +35,11 @@ class Less_Tree_Expression extends Less_Tree {
|
|||
foreach ( $this->value as $e ) {
|
||||
$ret[] = $e->compile( $env );
|
||||
}
|
||||
$returnValue = new Less_Tree_Expression( $ret );
|
||||
$returnValue = new self( $ret );
|
||||
|
||||
} else {
|
||||
|
||||
if ( ( $this->value[0] instanceof Less_Tree_Expression ) && $this->value[0]->parens && !$this->value[0]->parensInOp ) {
|
||||
if ( ( $this->value[0] instanceof self ) && $this->value[0]->parens && !$this->value[0]->parensInOp ) {
|
||||
$doubleParen = true;
|
||||
}
|
||||
|
|
@ -11,13 +11,14 @@ class Less_Tree_Extend extends Less_Tree {
|
|||
public $allowBefore;
|
||||
public $allowAfter;
|
||||
public $firstExtendOnThisSelectorPath;
|
||||
public $type = 'Extend';
|
||||
public $ruleset;
|
||||
|
||||
public $object_id;
|
||||
public $parent_ids = [];
|
||||
|
||||
/**
|
||||
* @param Less_Tree_Selector $selector
|
||||
* @param string $option
|
||||
* @param int $index
|
||||
*/
|
||||
public function __construct( $selector, $option, $index ) {
|
||||
|
@ -54,11 +55,11 @@ class Less_Tree_Extend extends Less_Tree {
|
|||
Less_Parser::$has_extends = true;
|
||||
$this->selector = $this->selector->compile( $env );
|
||||
return $this;
|
||||
// return new Less_Tree_Extend( $this->selector->compile($env), $this->option, $this->index);
|
||||
// return new self( $this->selector->compile($env), $this->option, $this->index);
|
||||
}
|
||||
|
||||
public function clone() {
|
||||
return new Less_Tree_Extend( $this->selector, $this->option, $this->index );
|
||||
return new self( $this->selector, $this->option, $this->index );
|
||||
}
|
||||
|
||||
public function findSelfSelectors( $selectors ) {
|
8
include/thirdparty/less.php/___4.2/Tree/HasValueProperty.php
vendored
Normal file
8
include/thirdparty/less.php/___4.2/Tree/HasValueProperty.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
* @property mixed $value
|
||||
*/
|
||||
interface Less_Tree_HasValueProperty {
|
||||
|
||||
}
|
|
@ -23,7 +23,6 @@ class Less_Tree_Import extends Less_Tree {
|
|||
public $css;
|
||||
public $skip;
|
||||
public $root;
|
||||
public $type = 'Import';
|
||||
|
||||
public function __construct( $path, $features, $options, $index, $currentFileInfo = null ) {
|
||||
$this->options = $options;
|
||||
|
@ -105,10 +104,10 @@ class Less_Tree_Import extends Less_Tree {
|
|||
$path = $this->path->value;
|
||||
$path = ( isset( $this->css ) || preg_match( '/(\.[a-z]*$)|([\?;].*)$/', $path ) ) ? $path : $path . '.less';
|
||||
|
||||
// During the first pass, Less_Tree_URL may contain a Less_Tree_Variable (not yet expanded),
|
||||
// During the first pass, Less_Tree_Url may contain a Less_Tree_Variable (not yet expanded),
|
||||
// and thus has no value property defined yet. Return null until we reach the next phase.
|
||||
// https://github.com/wikimedia/less.php/issues/29
|
||||
} elseif ( $this->path instanceof Less_Tree_URL && !( $this->path->value instanceof Less_Tree_Variable ) ) {
|
||||
} elseif ( $this->path instanceof Less_Tree_Url && !( $this->path->value instanceof Less_Tree_Variable ) ) {
|
||||
$path = $this->path->value->value;
|
||||
} else {
|
||||
return null;
|
||||
|
@ -119,7 +118,7 @@ class Less_Tree_Import extends Less_Tree {
|
|||
}
|
||||
|
||||
public function compileForImport( $env ) {
|
||||
return new Less_Tree_Import( $this->path->compile( $env ), $this->features, $this->options, $this->index, $this->currentFileInfo );
|
||||
return new self( $this->path->compile( $env ), $this->features, $this->options, $this->index, $this->currentFileInfo );
|
||||
}
|
||||
|
||||
public function compilePath( $env ) {
|
||||
|
@ -129,7 +128,7 @@ class Less_Tree_Import extends Less_Tree {
|
|||
$rootpath = $this->currentFileInfo['rootpath'];
|
||||
}
|
||||
|
||||
if ( !( $path instanceof Less_Tree_URL ) ) {
|
||||
if ( !( $path instanceof Less_Tree_Url ) ) {
|
||||
if ( $rootpath ) {
|
||||
$pathValue = $path->value;
|
||||
// Add the base path if the import is relative
|
||||
|
@ -143,21 +142,23 @@ class Less_Tree_Import extends Less_Tree {
|
|||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @see less-2.5.3.js#Import.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$evald = $this->compileForImport( $env );
|
||||
|
||||
// get path & uri
|
||||
$path_and_uri = null;
|
||||
if ( is_callable( Less_Parser::$options['import_callback'] ) ) {
|
||||
$path_and_uri = call_user_func( Less_Parser::$options['import_callback'], $evald );
|
||||
}
|
||||
$callback = Less_Parser::$options['import_callback'];
|
||||
$path_and_uri = is_callable( $callback ) ? $callback( $evald ) : null;
|
||||
|
||||
if ( !$path_and_uri ) {
|
||||
$path_and_uri = $evald->PathAndUri();
|
||||
}
|
||||
|
||||
if ( $path_and_uri ) {
|
||||
list( $full_path, $uri ) = $path_and_uri;
|
||||
[ $full_path, $uri ] = $path_and_uri;
|
||||
} else {
|
||||
$full_path = $uri = $evald->getPath();
|
||||
}
|
||||
|
@ -169,11 +170,8 @@ class Less_Tree_Import extends Less_Tree {
|
|||
'@phan-var string $full_path';
|
||||
|
||||
if ( $this->options['inline'] ) {
|
||||
// todo needs to reference css file not import
|
||||
//$contents = new Less_Tree_Anonymous($this->root, 0, array('filename'=>$this->importedFilename), true );
|
||||
|
||||
Less_Parser::AddParsedFile( $full_path );
|
||||
$contents = new Less_Tree_Anonymous( file_get_contents( $full_path ), 0, [], true );
|
||||
$contents = new Less_Tree_Anonymous( file_get_contents( $full_path ), 0, [], true, true );
|
||||
|
||||
if ( $this->features ) {
|
||||
return new Less_Tree_Media( [ $contents ], $this->features->value );
|
||||
|
@ -190,7 +188,7 @@ class Less_Tree_Import extends Less_Tree {
|
|||
// css ?
|
||||
if ( $evald->css ) {
|
||||
$features = ( $evald->features ? $evald->features->compile( $env ) : null );
|
||||
return new Less_Tree_Import( $this->compilePath( $env ), $features, $this->options, $this->index );
|
||||
return new self( $this->compilePath( $env ), $features, $this->options, $this->index );
|
||||
}
|
||||
|
||||
return $this->ParseImport( $full_path, $uri, $env );
|
|
@ -2,15 +2,15 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Javascript extends Less_Tree {
|
||||
class Less_Tree_JavaScript extends Less_Tree {
|
||||
|
||||
public $type = 'Javascript';
|
||||
public $escaped;
|
||||
public $expression;
|
||||
public $index;
|
||||
|
||||
/**
|
||||
* @param bool $index
|
||||
* @param string $string
|
||||
* @param int $index
|
||||
* @param bool $escaped
|
||||
*/
|
||||
public function __construct( $string, $index, $escaped ) {
|
|
@ -2,10 +2,10 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Keyword extends Less_Tree {
|
||||
class Less_Tree_Keyword extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
/** @var string */
|
||||
public $value;
|
||||
public $type = 'Keyword';
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
|
@ -26,7 +26,7 @@ class Less_Tree_Keyword extends Less_Tree {
|
|||
}
|
||||
|
||||
public function compare( $other ) {
|
||||
if ( $other instanceof Less_Tree_Keyword ) {
|
||||
if ( $other instanceof self ) {
|
||||
return $other->value === $this->value ? 0 : 1;
|
||||
} else {
|
||||
return -1;
|
|
@ -9,7 +9,6 @@ class Less_Tree_Media extends Less_Tree {
|
|||
public $index;
|
||||
public $currentFileInfo;
|
||||
public $isReferenced;
|
||||
public $type = 'Media';
|
||||
|
||||
public function __construct( $value = [], $features = [], $index = null, $currentFileInfo = null ) {
|
||||
$this->index = $index;
|
||||
|
@ -39,11 +38,11 @@ class Less_Tree_Media extends Less_Tree {
|
|||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @return Less_Tree_Media|Less_Tree_Ruleset
|
||||
* @return self|Less_Tree_Ruleset
|
||||
* @see less-2.5.3.js#Media.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$media = new Less_Tree_Media( [], [], $this->index, $this->currentFileInfo );
|
||||
$media = new self( [], [], $this->index, $this->currentFileInfo );
|
||||
|
||||
$strictMathBypass = false;
|
||||
if ( Less_Parser::$options['strictMath'] === false ) {
|
||||
|
@ -112,7 +111,7 @@ class Less_Tree_Media extends Less_Tree {
|
|||
*/
|
||||
public function compileNested( $env ) {
|
||||
$path = array_merge( $env->mediaPath, [ $this ] );
|
||||
'@phan-var array<Less_Tree_Media> $path';
|
||||
'@phan-var self[] $path';
|
||||
|
||||
// Extract the media-query conditions separated with `,` (OR).
|
||||
foreach ( $path as $key => $p ) {
|
||||
|
@ -130,6 +129,7 @@ class Less_Tree_Media extends Less_Tree {
|
|||
// b and c and e
|
||||
|
||||
$permuted = $this->permute( $path );
|
||||
'@phan-var (Less_Tree|string)[][] $permuted';
|
||||
$expressions = [];
|
||||
foreach ( $permuted as $path ) {
|
||||
|
|
@ -10,12 +10,7 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
public $currentFileInfo;
|
||||
|
||||
public $important;
|
||||
public $type = 'MixinCall';
|
||||
|
||||
/**
|
||||
* less.js: tree.mixin.Call
|
||||
*
|
||||
*/
|
||||
public function __construct( $elements, $args, $index, $currentFileInfo, $important = false ) {
|
||||
$this->selector = new Less_Tree_Selector( $elements );
|
||||
$this->arguments = $args;
|
||||
|
@ -24,17 +19,14 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
$this->important = $important;
|
||||
}
|
||||
|
||||
// function accept($visitor){
|
||||
// $this->selector = $visitor->visit($this->selector);
|
||||
// $this->arguments = $visitor->visit($this->arguments);
|
||||
//}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#MixinCall.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$rules = [];
|
||||
$match = false;
|
||||
$isOneFound = false;
|
||||
$candidates = [];
|
||||
$defaultUsed = false;
|
||||
$conditionResult = [];
|
||||
|
||||
$args = [];
|
||||
|
@ -42,18 +34,16 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
$args[] = [ 'name' => $a['name'], 'value' => $a['value']->compile( $env ) ];
|
||||
}
|
||||
|
||||
$defNone = 0;
|
||||
$defTrue = 1;
|
||||
$defFalse = 2;
|
||||
foreach ( $env->frames as $frame ) {
|
||||
|
||||
$mixins = $frame->find( $this->selector );
|
||||
|
||||
if ( !$mixins ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isOneFound = true;
|
||||
$defNone = 0;
|
||||
$defTrue = 1;
|
||||
$defFalse = 2;
|
||||
|
||||
// To make `default()` function independent of definition order we have two "subpasses" here.
|
||||
// At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
|
||||
|
@ -113,20 +103,18 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
}
|
||||
|
||||
$candidates_length = count( $candidates );
|
||||
$length_1 = ( $candidates_length == 1 );
|
||||
|
||||
for ( $m = 0; $m < $candidates_length; $m++ ) {
|
||||
$candidate = $candidates[$m]['group'];
|
||||
if ( ( $candidate === $defNone ) || ( $candidate === $defaultResult ) ) {
|
||||
try{
|
||||
try {
|
||||
$mixin = $candidates[$m]['mixin'];
|
||||
if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) {
|
||||
$originalRuleset = $mixin instanceof Less_Tree_Ruleset ? $mixin->originalRuleset : $mixin;
|
||||
$mixin = new Less_Tree_Mixin_Definition( '', [], $mixin->rules, null, false );
|
||||
$mixin->originalRuleset = $mixins[$m]->originalRuleset;
|
||||
$mixin->originalRuleset = $originalRuleset;
|
||||
}
|
||||
$rules = array_merge( $rules, $mixin->evalCall( $env, $args, $this->important )->rules );
|
||||
} catch ( Exception $e ) {
|
||||
// throw new Less_Exception_Compiler($e->getMessage(), $e->index, null, $this->currentFileInfo['filename']);
|
||||
throw new Less_Exception_Compiler( $e->getMessage(), null, null, $this->currentFileInfo );
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +130,8 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
}
|
||||
|
||||
if ( $isOneFound ) {
|
||||
throw new Less_Exception_Compiler( 'No matching definition was found for `' . $this->Format( $args ) . '`', null, $this->index, $this->currentFileInfo );
|
||||
$selectorName = $this->selector->toCSS();
|
||||
throw new Less_Exception_Compiler( 'No matching definition was found for ' . $selectorName . ' with args `' . $this->Format( $args ) . '`', null, $this->index, $this->currentFileInfo );
|
||||
|
||||
} else {
|
||||
throw new Less_Exception_Compiler( trim( $this->selector->toCSS() ) . " is undefined in " . $this->currentFileInfo['filename'], null, $this->index );
|
||||
|
@ -151,7 +140,6 @@ class Less_Tree_Mixin_Call extends Less_Tree {
|
|||
|
||||
/**
|
||||
* Format the args for use in exception messages
|
||||
*
|
||||
*/
|
||||
private function Format( $args ) {
|
||||
$message = [];
|
|
@ -13,9 +13,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
public $frames = [];
|
||||
public $condition;
|
||||
public $variadic;
|
||||
public $type = 'MixinDefinition';
|
||||
|
||||
// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition
|
||||
public function __construct( $name, $params, $rules, $condition, $variadic = false, $frames = [] ) {
|
||||
$this->name = $name;
|
||||
$this->selectors = [ new Less_Tree_Selector( [ new Less_Tree_Element( null, $name ) ] ) ];
|
||||
|
@ -38,17 +36,13 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
$this->SetRulesetIndex();
|
||||
}
|
||||
|
||||
// function accept( $visitor ){
|
||||
// $this->params = $visitor->visit($this->params);
|
||||
// $this->rules = $visitor->visit($this->rules);
|
||||
// $this->condition = $visitor->visit($this->condition);
|
||||
//}
|
||||
|
||||
public function toCSS() {
|
||||
return '';
|
||||
}
|
||||
|
||||
// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition.evalParams
|
||||
/**
|
||||
* @see less-2.5.3.js#Definition.prototype.evalParams
|
||||
*/
|
||||
public function compileParams( $env, $mixinFrames, $args = [], &$evaldArguments = [] ) {
|
||||
$frame = new Less_Tree_Ruleset( null, [] );
|
||||
$params = $this->params;
|
||||
|
@ -64,7 +58,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
$isNamedFound = false;
|
||||
|
||||
foreach ( $params as $j => $param ) {
|
||||
if ( !isset( $evaldArguments[$j] ) && $arg['name'] === $params[$j]['name'] ) {
|
||||
if ( !isset( $evaldArguments[$j] ) && $arg['name'] === $param['name'] ) {
|
||||
$evaldArguments[$j] = $arg['value']->compile( $env );
|
||||
array_unshift( $frame->rules, new Less_Tree_Rule( $arg['name'], $arg['value']->compile( $env ) ) );
|
||||
$isNamedFound = true;
|
||||
|
@ -75,7 +69,6 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
array_splice( $args, $i, 1 );
|
||||
$i--;
|
||||
$argsLength--;
|
||||
continue;
|
||||
} else {
|
||||
throw new Less_Exception_Compiler( "Named argument for " . $this->name . ' ' . $args[$i]['name'] . ' not found' );
|
||||
}
|
||||
|
@ -85,24 +78,21 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
|
||||
$argIndex = 0;
|
||||
foreach ( $params as $i => $param ) {
|
||||
|
||||
if ( isset( $evaldArguments[$i] ) ) { continue;
|
||||
if ( isset( $evaldArguments[$i] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$arg = null;
|
||||
if ( isset( $args[$argIndex] ) ) {
|
||||
$arg = $args[$argIndex];
|
||||
}
|
||||
|
||||
if ( isset( $param['name'] ) && $param['name'] ) {
|
||||
$arg = $args[$argIndex] ?? null;
|
||||
|
||||
$name = $param['name'] ?? null;
|
||||
if ( $name ) {
|
||||
if ( isset( $param['variadic'] ) ) {
|
||||
$varargs = [];
|
||||
for ( $j = $argIndex; $j < $argsLength; $j++ ) {
|
||||
$varargs[] = $args[$j]['value']->compile( $env );
|
||||
}
|
||||
$expression = new Less_Tree_Expression( $varargs );
|
||||
array_unshift( $frame->rules, new Less_Tree_Rule( $param['name'], $expression->compile( $env ) ) );
|
||||
array_unshift( $frame->rules, new Less_Tree_Rule( $name, $expression->compile( $env ) ) );
|
||||
} else {
|
||||
$val = ( $arg && $arg['value'] ) ? $arg['value'] : false;
|
||||
|
||||
|
@ -121,7 +111,7 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
throw new Less_Exception_Compiler( "Wrong number of arguments for " . $this->name . " (" . $argsLength . ' for ' . $this->arity . ")" );
|
||||
}
|
||||
|
||||
array_unshift( $frame->rules, new Less_Tree_Rule( $param['name'], $val ) );
|
||||
array_unshift( $frame->rules, new Less_Tree_Rule( $name, $val ) );
|
||||
$evaldArguments[$i] = $val;
|
||||
}
|
||||
}
|
||||
|
@ -142,9 +132,9 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
|
||||
public function compile( $env ) {
|
||||
if ( $this->frames ) {
|
||||
return new Less_Tree_Mixin_Definition( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $this->frames );
|
||||
return new self( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $this->frames );
|
||||
}
|
||||
return new Less_Tree_Mixin_Definition( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
|
||||
return new self( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
|
||||
}
|
||||
|
||||
public function evalCall( $env, $args = null, $important = null ) {
|
||||
|
@ -194,8 +184,8 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
|
||||
$compile_env = new Less_Environment();
|
||||
$compile_env->frames = array_merge(
|
||||
[ $frame ], // the parameter variables
|
||||
$this->frames, // the parent namespace/mixin frames
|
||||
[ $frame ], // the parameter variables
|
||||
$this->frames, // the parent namespace/mixin frames
|
||||
$env->frames // the current environment frames
|
||||
);
|
||||
|
||||
|
@ -204,6 +194,18 @@ class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
|
|||
return (bool)$this->condition->compile( $compile_env );
|
||||
}
|
||||
|
||||
public function makeImportant() {
|
||||
$important_rules = [];
|
||||
foreach ( $this->rules as $rule ) {
|
||||
if ( $rule instanceof Less_Tree_Rule || $rule instanceof self || $rule instanceof Less_Tree_NameValue ) {
|
||||
$important_rules[] = $rule->makeImportant();
|
||||
} else {
|
||||
$important_rules[] = $rule;
|
||||
}
|
||||
}
|
||||
return new self( $this->name, $this->params, $important_rules, $this->condition, $this->variadic, $this->frames );
|
||||
}
|
||||
|
||||
public function matchArgs( $args, $env = null ) {
|
||||
$argsLength = count( $args );
|
||||
|
|
@ -10,13 +10,12 @@
|
|||
*
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_NameValue extends Less_Tree {
|
||||
class Less_Tree_NameValue extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $name;
|
||||
public $value;
|
||||
public $index;
|
||||
public $currentFileInfo;
|
||||
public $type = 'NameValue';
|
||||
public $important = '';
|
||||
|
||||
public function __construct( $name, $value = null, $index = null, $currentFileInfo = null ) {
|
||||
|
@ -41,7 +40,7 @@ class Less_Tree_NameValue extends Less_Tree {
|
|||
}
|
||||
|
||||
public function makeImportant() {
|
||||
$new = new Less_Tree_NameValue( $this->name, $this->value, $this->index, $this->currentFileInfo );
|
||||
$new = new self( $this->name, $this->value, $this->index, $this->currentFileInfo );
|
||||
$new->important = ' !important';
|
||||
return $new;
|
||||
}
|
|
@ -2,10 +2,9 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Negative extends Less_Tree {
|
||||
class Less_Tree_Negative extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $value;
|
||||
public $type = 'Negative';
|
||||
|
||||
public function __construct( $node ) {
|
||||
$this->value = $node;
|
||||
|
@ -28,6 +27,6 @@ class Less_Tree_Negative extends Less_Tree {
|
|||
$ret = new Less_Tree_Operation( '*', [ new Less_Tree_Dimension( -1 ), $this->value ] );
|
||||
return $ret->compile( $env );
|
||||
}
|
||||
return new Less_Tree_Negative( $this->value->compile( $env ) );
|
||||
return new self( $this->value->compile( $env ) );
|
||||
}
|
||||
}
|
|
@ -7,7 +7,6 @@ class Less_Tree_Operation extends Less_Tree {
|
|||
public $op;
|
||||
public $operands;
|
||||
public $isSpaced;
|
||||
public $type = 'Operation';
|
||||
|
||||
/**
|
||||
* @param string $op
|
||||
|
@ -48,7 +47,7 @@ class Less_Tree_Operation extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
return new Less_Tree_Operation( $this->op, [ $a, $b ], $this->isSpaced );
|
||||
return new self( $this->op, [ $a, $b ], $this->isSpaced );
|
||||
}
|
||||
|
||||
/**
|
|
@ -2,11 +2,10 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Paren extends Less_Tree {
|
||||
class Less_Tree_Paren extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
/** @var Less_Tree $value */
|
||||
/** @var Less_Tree */
|
||||
public $value;
|
||||
public $type = 'Paren';
|
||||
|
||||
/**
|
||||
* @param Less_Tree $value
|
||||
|
@ -29,7 +28,7 @@ class Less_Tree_Paren extends Less_Tree {
|
|||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
return new Less_Tree_Paren( $this->value->compile( $env ) );
|
||||
return new self( $this->value->compile( $env ) );
|
||||
}
|
||||
|
||||
}
|
79
include/thirdparty/less.php/___4.2/Tree/Quoted.php
vendored
Normal file
79
include/thirdparty/less.php/___4.2/Tree/Quoted.php
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Quoted extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
public $escaped;
|
||||
/** @var string */
|
||||
public $value;
|
||||
public $quote;
|
||||
public $index;
|
||||
public $currentFileInfo;
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*/
|
||||
public function __construct( $str, $content = '', $escaped = true, $index = false, $currentFileInfo = null ) {
|
||||
$this->escaped = $escaped;
|
||||
$this->value = $content;
|
||||
if ( $str ) {
|
||||
$this->quote = $str[0];
|
||||
}
|
||||
$this->index = $index;
|
||||
$this->currentFileInfo = $currentFileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
if ( !$this->escaped ) {
|
||||
$output->add( $this->quote, $this->currentFileInfo, $this->index );
|
||||
}
|
||||
$output->add( $this->value );
|
||||
if ( !$this->escaped ) {
|
||||
$output->add( $this->quote );
|
||||
}
|
||||
}
|
||||
|
||||
public function compile( $env ) {
|
||||
$value = $this->value;
|
||||
if ( preg_match_all( '/`([^`]+)`/', $this->value, $matches ) ) {
|
||||
foreach ( $matches[1] as $i => $match ) {
|
||||
$js = new Less_Tree_JavaScript( $match, $this->index, true );
|
||||
$js = $js->compile( $env )->value;
|
||||
$value = str_replace( $matches[0][$i], $js, $value );
|
||||
}
|
||||
}
|
||||
$r = $value;
|
||||
do {
|
||||
$value = $r;
|
||||
if ( preg_match_all( '/@\{([\w-]+)\}/', $value, $matches ) ) {
|
||||
foreach ( $matches[1] as $i => $match ) {
|
||||
$v = new Less_Tree_Variable( '@' . $match, $this->index, $this->currentFileInfo );
|
||||
$v = $v->compile( $env );
|
||||
$v = ( $v instanceof self ) ? $v->value : $v->toCSS();
|
||||
$r = str_replace( $matches[0][$i], $v, $r );
|
||||
}
|
||||
}
|
||||
} while ( $r != $value );
|
||||
|
||||
return new self( $this->quote . $r . $this->quote, $r, $this->escaped, $this->index, $this->currentFileInfo );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $other
|
||||
* @return int|null
|
||||
* @see less-2.5.3.js#Quoted.prototype.compare
|
||||
*/
|
||||
public function compare( $other ) {
|
||||
if ( $other instanceof self && !$this->escaped && !$other->escaped ) {
|
||||
return Less_Tree::numericCompare( $this->value, $other->value );
|
||||
} else {
|
||||
return (
|
||||
Less_Parser::is_method( $other, 'toCSS' )
|
||||
&& $this->toCSS() === $other->toCSS()
|
||||
) ? 0 : null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,19 +2,18 @@
|
|||
/**
|
||||
* @private
|
||||
*/
|
||||
class Less_Tree_Rule extends Less_Tree {
|
||||
class Less_Tree_Rule extends Less_Tree implements Less_Tree_HasValueProperty {
|
||||
|
||||
public $name;
|
||||
/** @var Less_Tree $value */
|
||||
/** @var Less_Tree */
|
||||
public $value;
|
||||
/** @var string $important */
|
||||
/** @var string */
|
||||
public $important;
|
||||
public $merge;
|
||||
public $index;
|
||||
public $inline;
|
||||
public $variable;
|
||||
public $currentFileInfo;
|
||||
public $type = 'Rule';
|
||||
|
||||
/**
|
||||
* @param string|array<Less_Tree_Keyword|Less_Tree_Variable> $name
|
||||
|
@ -47,10 +46,10 @@ class Less_Tree_Rule extends Less_Tree {
|
|||
*/
|
||||
public function genCSS( $output ) {
|
||||
$output->add( $this->name . Less_Environment::$_outputMap[': '], $this->currentFileInfo, $this->index );
|
||||
try{
|
||||
try {
|
||||
$this->value->genCSS( $output );
|
||||
|
||||
}catch ( Less_Exception_Parser $e ) {
|
||||
} catch ( Less_Exception_Parser $e ) {
|
||||
$e->index = $this->index;
|
||||
$e->currentFile = $this->currentFileInfo;
|
||||
throw $e;
|
||||
|
@ -60,7 +59,7 @@ class Less_Tree_Rule extends Less_Tree {
|
|||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @return Less_Tree_Rule
|
||||
* @return self
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
$name = $this->name;
|
||||
|
@ -82,12 +81,12 @@ class Less_Tree_Rule extends Less_Tree {
|
|||
try {
|
||||
$evaldValue = $this->value->compile( $env );
|
||||
|
||||
if ( !$this->variable && $evaldValue->type === "DetachedRuleset" ) {
|
||||
if ( !$this->variable && $evaldValue instanceof Less_Tree_DetachedRuleset ) {
|
||||
throw new Less_Exception_Compiler( "Rulesets cannot be evaluated on a property.", null, $this->index, $this->currentFileInfo );
|
||||
}
|
||||
|
||||
if ( Less_Environment::$mixin_stack ) {
|
||||
$return = new Less_Tree_Rule( $name, $evaldValue, $this->important, $this->merge, $this->index, $this->currentFileInfo, $this->inline );
|
||||
$return = new self( $name, $evaldValue, $this->important, $this->merge, $this->index, $this->currentFileInfo, $this->inline );
|
||||
} else {
|
||||
$this->name = $name;
|
||||
$this->value = $evaldValue;
|
||||
|
@ -98,6 +97,7 @@ class Less_Tree_Rule extends Less_Tree {
|
|||
if ( !is_numeric( $e->index ) ) {
|
||||
$e->index = $this->index;
|
||||
$e->currentFile = $this->currentFileInfo;
|
||||
$e->genMessage();
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ class Less_Tree_Rule extends Less_Tree {
|
|||
}
|
||||
|
||||
public function makeImportant() {
|
||||
return new Less_Tree_Rule( $this->name, $this->value, '!important', $this->merge, $this->index, $this->currentFileInfo, $this->inline );
|
||||
return new self( $this->name, $this->value, '!important', $this->merge, $this->index, $this->currentFileInfo, $this->inline );
|
||||
}
|
||||
|
||||
}
|
|
@ -16,11 +16,12 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
public $allowImports;
|
||||
public $paths;
|
||||
public $firstRoot;
|
||||
public $type = 'Ruleset';
|
||||
public $multiMedia;
|
||||
public $allExtends;
|
||||
|
||||
/** @var int */
|
||||
public $ruleset_id;
|
||||
/** @var int */
|
||||
public $originalRuleset;
|
||||
|
||||
public $first_oelements;
|
||||
|
@ -68,7 +69,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
|
||||
/**
|
||||
* @param Less_Environment $env
|
||||
* @return Less_Tree_Ruleset
|
||||
* @return self
|
||||
* @see less-2.5.3.js#Ruleset.prototype.eval
|
||||
*/
|
||||
public function compile( $env ) {
|
||||
|
@ -101,7 +102,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
$rule = $ruleset->rules[$i];
|
||||
|
||||
// for rulesets, check if it is a css guard and can be removed
|
||||
if ( $rule instanceof Less_Tree_Ruleset && $rule->selectors && count( $rule->selectors ) === 1 ) {
|
||||
if ( $rule instanceof self && $rule->selectors && count( $rule->selectors ) === 1 ) {
|
||||
|
||||
// check if it can be folded in (e.g. & where)
|
||||
if ( $rule->selectors[0]->isJustParentSelector() ) {
|
||||
|
@ -136,8 +137,9 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
/**
|
||||
* Compile Less_Tree_Mixin_Call objects
|
||||
*
|
||||
* @param Less_Tree_Ruleset $ruleset
|
||||
* @param int $rsRuleCnt
|
||||
* @param self $ruleset
|
||||
* @param Less_Environment $env
|
||||
* @param int &$rsRuleCnt
|
||||
*/
|
||||
private function EvalMixinCalls( $ruleset, $env, &$rsRuleCnt ) {
|
||||
for ( $i = 0; $i < $rsRuleCnt; $i++ ) {
|
||||
|
@ -190,7 +192,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
* Compile the selectors and create a new ruleset object for the compile() method
|
||||
*
|
||||
* @param Less_Environment $env
|
||||
* @return Less_Tree_Ruleset
|
||||
* @return self
|
||||
*/
|
||||
private function PrepareRuleset( $env ) {
|
||||
// NOTE: Preserve distinction between null and empty array when compiling
|
||||
|
@ -223,7 +225,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
$rules = [];
|
||||
}
|
||||
|
||||
$ruleset = new Less_Tree_Ruleset( $selectors, $rules, $this->strictImports );
|
||||
$ruleset = new self( $selectors, $rules, $this->strictImports );
|
||||
|
||||
$ruleset->originalRuleset = $this->ruleset_id;
|
||||
$ruleset->root = $this->root;
|
||||
|
@ -241,7 +243,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
return $ruleset;
|
||||
}
|
||||
|
||||
function evalImports( $env ) {
|
||||
public function evalImports( $env ) {
|
||||
$rules_len = count( $this->rules );
|
||||
for ( $i = 0; $i < $rules_len; $i++ ) {
|
||||
$rule = $this->rules[$i];
|
||||
|
@ -262,17 +264,17 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
}
|
||||
}
|
||||
|
||||
function makeImportant() {
|
||||
public function makeImportant() {
|
||||
$important_rules = [];
|
||||
foreach ( $this->rules as $rule ) {
|
||||
if ( $rule instanceof Less_Tree_Rule || $rule instanceof Less_Tree_Ruleset || $rule instanceof Less_Tree_NameValue ) {
|
||||
if ( $rule instanceof Less_Tree_Rule || $rule instanceof self || $rule instanceof Less_Tree_NameValue ) {
|
||||
$important_rules[] = $rule->makeImportant();
|
||||
} else {
|
||||
$important_rules[] = $rule;
|
||||
}
|
||||
}
|
||||
|
||||
return new Less_Tree_Ruleset( $this->selectors, $important_rules, $this->strictImports );
|
||||
return new self( $this->selectors, $important_rules, $this->strictImports );
|
||||
}
|
||||
|
||||
public function matchArgs( $args, $env = null ) {
|
||||
|
@ -292,7 +294,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
return true;
|
||||
}
|
||||
|
||||
function resetCache() {
|
||||
public function resetCache() {
|
||||
$this->_rulesets = null;
|
||||
$this->_variables = null;
|
||||
$this->lookups = [];
|
||||
|
@ -332,7 +334,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
$first_oelement = $selector->_oelements[0];
|
||||
|
||||
foreach ( $this->rules as $rule ) {
|
||||
if ( $rule instanceof Less_Tree_Ruleset && $rule->ruleset_id != $self ) {
|
||||
if ( $rule instanceof self && $rule->ruleset_id != $self ) {
|
||||
|
||||
if ( isset( $rule->first_oelements[$first_oelement] ) ) {
|
||||
|
||||
|
@ -355,8 +357,23 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
return $this->lookups[$key];
|
||||
}
|
||||
|
||||
private function isRulesetLikeNode( $rule ) {
|
||||
// if it has nested rules, then it should be treated like a ruleset
|
||||
// medias and comments do not have nested rules, but should be treated like rulesets anyway
|
||||
// some directives and anonymous nodes are ruleset like, others are not
|
||||
if ( $rule instanceof Less_Tree_Media || $rule instanceof Less_Tree_Ruleset ) {
|
||||
return true;
|
||||
} elseif ( $rule instanceof Less_Tree_Anonymous || $rule instanceof Less_Tree_Directive ) {
|
||||
return $rule->isRulesetLike();
|
||||
}
|
||||
|
||||
// anything else is assumed to be a rule
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Less_Tree::genCSS
|
||||
* @param Less_Output $output
|
||||
* @see less-2.5.3.js#Ruleset.prototype.genCSS
|
||||
*/
|
||||
public function genCSS( $output ) {
|
||||
if ( !$this->root ) {
|
||||
|
@ -374,17 +391,21 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
}
|
||||
|
||||
$ruleNodes = [];
|
||||
$rulesetNodes = [];
|
||||
foreach ( $this->rules as $rule ) {
|
||||
|
||||
$class = get_class( $rule );
|
||||
if (
|
||||
( $class === 'Less_Tree_Media' ) ||
|
||||
( $class === 'Less_Tree_Directive' ) ||
|
||||
( $this->root && $class === 'Less_Tree_Comment' ) ||
|
||||
( $rule instanceof Less_Tree_Ruleset && $rule->rules )
|
||||
) {
|
||||
$rulesetNodes[] = $rule;
|
||||
$charsetNodeIndex = 0;
|
||||
$importNodeIndex = 0;
|
||||
foreach ( $this->rules as $i => $rule ) {
|
||||
if ( $rule instanceof Less_Tree_Comment ) {
|
||||
if ( $importNodeIndex === $i ) {
|
||||
$importNodeIndex++;
|
||||
}
|
||||
$ruleNodes[] = $rule;
|
||||
} elseif ( $rule instanceof Less_Tree_Directive && $rule->isCharset() ) {
|
||||
array_splice( $ruleNodes, $charsetNodeIndex, 0, [ $rule ] );
|
||||
$charsetNodeIndex++;
|
||||
$importNodeIndex++;
|
||||
} elseif ( $rule instanceof Less_Tree_Import ) {
|
||||
array_splice( $ruleNodes, $importNodeIndex, 0, [ $rule ] );
|
||||
$importNodeIndex++;
|
||||
} else {
|
||||
$ruleNodes[] = $rule;
|
||||
}
|
||||
|
@ -393,18 +414,25 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
// If this is the root node, we don't render
|
||||
// a selector, or {}.
|
||||
if ( !$this->root ) {
|
||||
$paths_len = count( $this->paths );
|
||||
for ( $i = 0; $i < $paths_len; $i++ ) {
|
||||
$path = $this->paths[$i];
|
||||
$firstSelector = true;
|
||||
|
||||
foreach ( $path as $p ) {
|
||||
$p->genCSS( $output, $firstSelector );
|
||||
$firstSelector = false;
|
||||
$sep = ',' . $tabSetStr;
|
||||
// TODO: Move to Env object
|
||||
// TODO: Inject Env object to toCSS() and genCSS()
|
||||
$firstSelector = false;
|
||||
|
||||
foreach ( $this->paths as $i => $path ) {
|
||||
$pathSubCnt = count( $path );
|
||||
if ( !$pathSubCnt ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $i + 1 < $paths_len ) {
|
||||
$output->add( ',' . $tabSetStr );
|
||||
if ( $i > 0 ) {
|
||||
$output->add( $sep );
|
||||
}
|
||||
$firstSelector = true;
|
||||
$path[0]->genCSS( $output, $firstSelector );
|
||||
$firstSelector = false;
|
||||
for ( $j = 1; $j < $pathSubCnt; $j++ ) {
|
||||
$path[$j]->genCSS( $output, $firstSelector );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,19 +440,21 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
}
|
||||
|
||||
// Compile rules and rulesets
|
||||
$ruleNodes_len = count( $ruleNodes );
|
||||
$rulesetNodes_len = count( $rulesetNodes );
|
||||
for ( $i = 0; $i < $ruleNodes_len; $i++ ) {
|
||||
$rule = $ruleNodes[$i];
|
||||
foreach ( $ruleNodes as $i => $rule ) {
|
||||
|
||||
// @page{ directive ends up with root elements inside it, a mix of rules and rulesets
|
||||
// In this instance we do not know whether it is the last property
|
||||
if ( $i + 1 === $ruleNodes_len && ( !$this->root || $rulesetNodes_len === 0 || $this->firstRoot ) ) {
|
||||
if ( $i + 1 === count( $ruleNodes ) ) {
|
||||
Less_Environment::$lastRule = true;
|
||||
}
|
||||
$currentLastRule = Less_Environment::$lastRule;
|
||||
|
||||
if ( $this->isRulesetLikeNode( $rule ) ) {
|
||||
Less_Environment::$lastRule = false;
|
||||
}
|
||||
|
||||
$rule->genCSS( $output );
|
||||
|
||||
Less_Environment::$lastRule = $currentLastRule;
|
||||
|
||||
if ( !Less_Environment::$lastRule ) {
|
||||
$output->add( $tabRuleStr );
|
||||
} else {
|
||||
|
@ -437,25 +467,12 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
Less_Environment::$tabLevel--;
|
||||
}
|
||||
|
||||
$firstRuleset = true;
|
||||
$space = ( $this->root ? $tabRuleStr : $tabSetStr );
|
||||
for ( $i = 0; $i < $rulesetNodes_len; $i++ ) {
|
||||
|
||||
if ( $ruleNodes_len && $firstRuleset ) {
|
||||
$output->add( $space );
|
||||
} elseif ( !$firstRuleset ) {
|
||||
$output->add( $space );
|
||||
}
|
||||
$firstRuleset = false;
|
||||
$rulesetNodes[$i]->genCSS( $output );
|
||||
}
|
||||
|
||||
if ( !Less_Parser::$options['compress'] && $this->firstRoot ) {
|
||||
$output->add( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
function markReferenced() {
|
||||
public function markReferenced() {
|
||||
if ( !$this->selectors ) {
|
||||
return;
|
||||
}
|
||||
|
@ -605,9 +622,9 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
foreach ( $newSelectors as &$sel ) {
|
||||
$length = count( $sel );
|
||||
if ( $length ) {
|
||||
$paths[] = $sel;
|
||||
$lastSelector = $sel[$length - 1];
|
||||
$sel[$length - 1] = $lastSelector->createDerived( $lastSelector->elements, $inSelector->extendList );
|
||||
$paths[] = $sel;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -708,7 +725,7 @@ class Less_Tree_Ruleset extends Less_Tree {
|
|||
return $newSelectorPath;
|
||||
}
|
||||
|
||||
function mergeElementsOnToSelectors( $elements, &$selectors ) {
|
||||
public function mergeElementsOnToSelectors( $elements, &$selectors ) {
|
||||
if ( !$elements ) {
|
||||
return;
|
||||
}
|
|
@ -10,7 +10,6 @@ class Less_Tree_Selector extends Less_Tree {
|
|||
public $_css;
|
||||
public $index;
|
||||
public $evaldCondition = false;
|
||||
public $type = 'Selector';
|
||||
public $currentFileInfo = [];
|
||||
public $isReferenced;
|
||||
public $mediaEmpty;
|
||||
|
@ -23,7 +22,12 @@ class Less_Tree_Selector extends Less_Tree {
|
|||
public $cacheable = true;
|
||||
|
||||
/**
|
||||
* @param bool $isReferenced
|
||||
* @param Less_Tree_Element[] $elements
|
||||
* @param Less_Tree_Element[] $extendList
|
||||
* @param Less_Tree_Condition|null $condition
|
||||
* @param int|null $index
|
||||
* @param array|null $currentFileInfo
|
||||
* @param bool|null $isReferenced
|
||||
*/
|
||||
public function __construct( $elements, $extendList = [], $condition = null, $index = null, $currentFileInfo = null, $isReferenced = null ) {
|
||||
$this->elements = $elements;
|
||||
|
@ -54,7 +58,7 @@ class Less_Tree_Selector extends Less_Tree {
|
|||
}
|
||||
|
||||
public function createDerived( $elements, $extendList = null, $evaldCondition = null ) {
|
||||
$newSelector = new Less_Tree_Selector(
|
||||
$newSelector = new self(
|
||||
$elements,
|
||||
( $extendList ?: $this->extendList ),
|
||||
null,
|
||||
|
@ -81,6 +85,9 @@ class Less_Tree_Selector extends Less_Tree {
|
|||
return $other->_oelements_len; // return number of matched elements
|
||||
}
|
||||
|
||||
/**
|
||||
* @see less-2.5.3.js#Selector.prototype.CacheElements
|
||||
*/
|
||||
public function CacheElements() {
|
||||
$this->_oelements = [];
|
||||
$this->_oelements_assoc = [];
|
||||
|
@ -94,15 +101,16 @@ class Less_Tree_Selector extends Less_Tree {
|
|||
$css .= $v->value;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !property_exists( $v->value, 'value' ) || !is_string( $v->value->value ) ) {
|
||||
if ( ( $v->value instanceof Less_Tree_Selector || $v->value instanceof Less_Tree_Variable )
|
||||
|| !is_string( $v->value->value ) ) {
|
||||
$this->cacheable = false;
|
||||
return;
|
||||
}
|
||||
$css .= $v->value->value;
|
||||
if ( isset( $v->value->value ) && !is_object( $v->value->value ) ) {
|
||||
$css .= $v->value->value;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_oelements_len = preg_match_all( '/[,&#\.\w-](?:[\w-]|(?:\\\\.))*/', $css, $matches );
|
||||
$this->_oelements_len = preg_match_all( '/[,&#\*\.\w-](?:[\w-]|(?:\\\\.))*/', $css, $matches );
|
||||
if ( $this->_oelements_len ) {
|
||||
$this->_oelements = $matches[0];
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue