summaryrefslogtreecommitdiffstats
path: root/vendor/wikimedia/less.php/lib/Less/Tree
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/wikimedia/less.php/lib/Less/Tree')
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Alpha.php44
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Anonymous.php54
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Assignment.php35
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Attribute.php49
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Call.php116
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Color.php228
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Comment.php43
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Condition.php68
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/DefaultFunc.php30
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/DetachedRuleset.php35
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Dimension.php190
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Directive.php92
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Element.php73
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Expression.php90
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Extend.php76
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Import.php299
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Javascript.php26
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Keyword.php35
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Media.php183
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Call.php197
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Definition.php236
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/NameValue.php49
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Negative.php33
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Operation.php64
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Paren.php35
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Quoted.php75
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Rule.php115
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Ruleset.php730
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/RulesetCall.php26
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Selector.php169
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/UnicodeDescriptor.php20
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Unit.php138
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/UnitConversions.php31
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Url.php77
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Value.php46
-rw-r--r--vendor/wikimedia/less.php/lib/Less/Tree/Variable.php56
36 files changed, 3863 insertions, 0 deletions
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Alpha.php b/vendor/wikimedia/less.php/lib/Less/Tree/Alpha.php
new file mode 100644
index 0000000..bdf5dee
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Alpha.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Alpha extends Less_Tree {
+ public $value;
+ public $type = 'Alpha';
+
+ public function __construct( $val ) {
+ $this->value = $val;
+ }
+
+ // function accept( $visitor ){
+ // $this->value = $visitor->visit( $this->value );
+ //}
+
+ public function compile( $env ) {
+ if ( is_object( $this->value ) ) {
+ $this->value = $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 {
+ $this->value->genCSS( $output );
+ }
+
+ $output->add( ')' );
+ }
+
+ public function toCSS() {
+ return "alpha(opacity=" . ( is_string( $this->value ) ? $this->value : $this->value->toCSS() ) . ")";
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Anonymous.php b/vendor/wikimedia/less.php/lib/Less/Tree/Anonymous.php
new file mode 100644
index 0000000..6d588e9
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Anonymous.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Anonymous extends Less_Tree {
+ public $value;
+ public $quote;
+ public $index;
+ public $mapLines;
+ public $currentFileInfo;
+ public $type = 'Anonymous';
+
+ /**
+ * @param int $index
+ * @param bool|null $mapLines
+ */
+ public function __construct( $value, $index = null, $currentFileInfo = null, $mapLines = null ) {
+ $this->value = $value;
+ $this->index = $index;
+ $this->mapLines = $mapLines;
+ $this->currentFileInfo = $currentFileInfo;
+ }
+
+ public function compile( $env ) {
+ return new Less_Tree_Anonymous( $this->value, $this->index, $this->currentFileInfo, $this->mapLines );
+ }
+
+ public function compare( $x ) {
+ if ( !is_object( $x ) ) {
+ return -1;
+ }
+
+ $left = $this->toCSS();
+ $right = $x->toCSS();
+
+ if ( $left === $right ) {
+ return 0;
+ }
+
+ return $left < $right ? -1 : 1;
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->value, $this->currentFileInfo, $this->index, $this->mapLines );
+ }
+
+ public function toCSS() {
+ return $this->value;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Assignment.php b/vendor/wikimedia/less.php/lib/Less/Tree/Assignment.php
new file mode 100644
index 0000000..1f939a1
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Assignment.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Assignment extends Less_Tree {
+
+ public $key;
+ public $value;
+ public $type = 'Assignment';
+
+ public function __construct( $key, $val ) {
+ $this->key = $key;
+ $this->value = $val;
+ }
+
+ public function accept( $visitor ) {
+ $this->value = $visitor->visitObj( $this->value );
+ }
+
+ public function compile( $env ) {
+ return new Less_Tree_Assignment( $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();
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Attribute.php b/vendor/wikimedia/less.php/lib/Less/Tree/Attribute.php
new file mode 100644
index 0000000..dd36595
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Attribute.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Attribute extends Less_Tree {
+
+ public $key;
+ public $op;
+ public $value;
+ public $type = 'Attribute';
+
+ public function __construct( $key, $op, $value ) {
+ $this->key = $key;
+ $this->op = $op;
+ $this->value = $value;
+ }
+
+ public function compile( $env ) {
+ $key_obj = is_object( $this->key );
+ $val_obj = is_object( $this->value );
+
+ if ( !$key_obj && !$val_obj ) {
+ return $this;
+ }
+
+ return new Less_Tree_Attribute(
+ $key_obj ? $this->key->compile( $env ) : $this->key,
+ $this->op,
+ $val_obj ? $this->value->compile( $env ) : $this->value );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->toCSS() );
+ }
+
+ public function toCSS() {
+ $value = $this->key;
+
+ if ( $this->op ) {
+ $value .= $this->op;
+ $value .= ( is_object( $this->value ) ? $this->value->toCSS() : $this->value );
+ }
+
+ return '[' . $value . ']';
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Call.php b/vendor/wikimedia/less.php/lib/Less/Tree/Call.php
new file mode 100644
index 0000000..28a3a19
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Call.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Call extends Less_Tree {
+ public $value;
+
+ public $name;
+ public $args;
+ public $index;
+ public $currentFileInfo;
+ public $type = 'Call';
+
+ public function __construct( $name, $args, $index, $currentFileInfo = null ) {
+ $this->name = $name;
+ $this->args = $args;
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ }
+
+ public function accept( $visitor ) {
+ $this->args = $visitor->visitArray( $this->args );
+ }
+
+ //
+ // When evaluating a function call,
+ // we either find the function in `tree.functions` [1],
+ // in which case we call it, passing the evaluated arguments,
+ // or we simply print it out as it appeared originally [2].
+ //
+ // The *functions.js* file contains the built-in functions.
+ //
+ // The reason why we evaluate the arguments, is in the case where
+ // we try to pass a variable to a function, like: `saturate(@color)`.
+ // The function should receive the value, not the variable.
+ //
+ public function compile( $env = null ) {
+ $args = [];
+ foreach ( $this->args as $a ) {
+ $args[] = $a->compile( $env );
+ }
+
+ $nameLC = strtolower( $this->name );
+ switch ( $nameLC ) {
+ case '%':
+ $nameLC = '_percent';
+ break;
+
+ case 'get-unit':
+ $nameLC = 'getunit';
+ break;
+
+ case 'data-uri':
+ $nameLC = 'datauri';
+ break;
+
+ case 'svg-gradient':
+ $nameLC = 'svggradient';
+ break;
+ }
+
+ $result = null;
+ if ( $nameLC === 'default' ) {
+ $result = Less_Tree_DefaultFunc::compile();
+ } else {
+ $func = null;
+ if ( method_exists( 'Less_Functions', $nameLC ) ) {
+ $functions = new Less_Functions( $env, $this->currentFileInfo );
+ $func = [ $functions, $nameLC ];
+ } 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 = call_user_func_array( $func, $args );
+ } catch ( Exception $e ) {
+ // Preserve original trace, especially from custom functions.
+ // https://github.com/wikimedia/less.php/issues/38
+ throw new Less_Exception_Compiler(
+ 'error evaluating function `' . $this->name . '` ' . $e->getMessage()
+ . ' index: ' . $this->index,
+ $e
+ );
+ }
+ }
+ }
+
+ if ( $result !== null ) {
+ return $result;
+ }
+
+ return new Less_Tree_Call( $this->name, $args, $this->index, $this->currentFileInfo );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->name . '(', $this->currentFileInfo, $this->index );
+ $args_len = count( $this->args );
+ for ( $i = 0; $i < $args_len; $i++ ) {
+ $this->args[$i]->genCSS( $output );
+ if ( $i + 1 < $args_len ) {
+ $output->add( ', ' );
+ }
+ }
+
+ $output->add( ')' );
+ }
+
+ // public function toCSS(){
+ // return $this->compile()->toCSS();
+ //}
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Color.php b/vendor/wikimedia/less.php/lib/Less/Tree/Color.php
new file mode 100644
index 0000000..427f47d
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Color.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Color extends Less_Tree {
+ public $rgb;
+ public $alpha;
+ public $isTransparentKeyword;
+ public $type = 'Color';
+
+ public function __construct( $rgb, $a = 1, $isTransparentKeyword = null ) {
+ if ( $isTransparentKeyword ) {
+ $this->rgb = $rgb;
+ $this->alpha = $a;
+ $this->isTransparentKeyword = true;
+ return;
+ }
+
+ $this->rgb = [];
+ if ( is_array( $rgb ) ) {
+ $this->rgb = $rgb;
+ } elseif ( strlen( $rgb ) == 6 ) {
+ foreach ( str_split( $rgb, 2 ) as $c ) {
+ $this->rgb[] = hexdec( $c );
+ }
+ } else {
+ foreach ( str_split( $rgb, 1 ) as $c ) {
+ $this->rgb[] = hexdec( $c . $c );
+ }
+ }
+ $this->alpha = is_numeric( $a ) ? $a : 1;
+ }
+
+ public function luma() {
+ $r = $this->rgb[0] / 255;
+ $g = $this->rgb[1] / 255;
+ $b = $this->rgb[2] / 255;
+
+ $r = ( $r <= 0.03928 ) ? $r / 12.92 : pow( ( ( $r + 0.055 ) / 1.055 ), 2.4 );
+ $g = ( $g <= 0.03928 ) ? $g / 12.92 : pow( ( ( $g + 0.055 ) / 1.055 ), 2.4 );
+ $b = ( $b <= 0.03928 ) ? $b / 12.92 : pow( ( ( $b + 0.055 ) / 1.055 ), 2.4 );
+
+ return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->toCSS() );
+ }
+
+ public function toCSS( $doNotCompress = false ) {
+ $compress = Less_Parser::$options['compress'] && !$doNotCompress;
+ $alpha = Less_Functions::fround( $this->alpha );
+
+ //
+ // If we have some transparency, the only way to represent it
+ // is via `rgba`. Otherwise, we use the hex representation,
+ // which has better compatibility with older browsers.
+ // Values are capped between `0` and `255`, rounded and zero-padded.
+ //
+ if ( $alpha < 1 ) {
+ if ( ( $alpha === 0 || $alpha === 0.0 ) && isset( $this->isTransparentKeyword ) && $this->isTransparentKeyword ) {
+ return 'transparent';
+ }
+
+ $values = [];
+ foreach ( $this->rgb as $c ) {
+ $values[] = Less_Functions::clamp( round( $c ), 255 );
+ }
+ $values[] = $alpha;
+
+ $glue = ( $compress ? ',' : ', ' );
+ return "rgba(" . implode( $glue, $values ) . ")";
+ } else {
+
+ $color = $this->toRGB();
+
+ if ( $compress ) {
+
+ // Convert color to short format
+ if ( $color[1] === $color[2] && $color[3] === $color[4] && $color[5] === $color[6] ) {
+ $color = '#' . $color[1] . $color[3] . $color[5];
+ }
+ }
+
+ return $color;
+ }
+ }
+
+ //
+ // Operations have to be done per-channel, if not,
+ // channels will spill onto each other. Once we have
+ // our result, in the form of an integer triplet,
+ // we create a new Color node to hold the result.
+ //
+
+ /**
+ * @param string $op
+ */
+ public function operate( $op, $other ) {
+ $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] );
+ }
+ return new Less_Tree_Color( $rgb, $alpha );
+ }
+
+ public function toRGB() {
+ return $this->toHex( $this->rgb );
+ }
+
+ public function toHSL() {
+ $r = $this->rgb[0] / 255;
+ $g = $this->rgb[1] / 255;
+ $b = $this->rgb[2] / 255;
+ $a = $this->alpha;
+
+ $max = max( $r, $g, $b );
+ $min = min( $r, $g, $b );
+ $l = ( $max + $min ) / 2;
+ $d = $max - $min;
+
+ $h = $s = 0;
+ if ( $max !== $min ) {
+ $s = $l > 0.5 ? $d / ( 2 - $max - $min ) : $d / ( $max + $min );
+
+ switch ( $max ) {
+ case $r:
+ $h = ( $g - $b ) / $d + ( $g < $b ? 6 : 0 );
+ break;
+ case $g:
+ $h = ( $b - $r ) / $d + 2;
+ break;
+ case $b:
+ $h = ( $r - $g ) / $d + 4;
+ break;
+ }
+ $h /= 6;
+ }
+ return [ 'h' => $h * 360, 's' => $s, 'l' => $l, 'a' => $a ];
+ }
+
+ // Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+ public function toHSV() {
+ $r = $this->rgb[0] / 255;
+ $g = $this->rgb[1] / 255;
+ $b = $this->rgb[2] / 255;
+ $a = $this->alpha;
+
+ $max = max( $r, $g, $b );
+ $min = min( $r, $g, $b );
+
+ $v = $max;
+
+ $d = $max - $min;
+ if ( $max === 0 ) {
+ $s = 0;
+ } else {
+ $s = $d / $max;
+ }
+
+ $h = 0;
+ if ( $max !== $min ) {
+ switch ( $max ) {
+ case $r:
+ $h = ( $g - $b ) / $d + ( $g < $b ? 6 : 0 );
+ break;
+ case $g:
+ $h = ( $b - $r ) / $d + 2;
+ break;
+ case $b:
+ $h = ( $r - $g ) / $d + 4;
+ break;
+ }
+ $h /= 6;
+ }
+ return [ 'h' => $h * 360, 's' => $s, 'v' => $v, 'a' => $a ];
+ }
+
+ public function toARGB() {
+ $argb = array_merge( (array)Less_Parser::round( $this->alpha * 255 ), $this->rgb );
+ return $this->toHex( $argb );
+ }
+
+ public function compare( $x ) {
+ if ( !property_exists( $x, 'rgb' ) ) {
+ 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;
+ }
+
+ public function toHex( $v ) {
+ $ret = '#';
+ foreach ( $v as $c ) {
+ $c = Less_Functions::clamp( Less_Parser::round( $c ), 255 );
+ if ( $c < 16 ) {
+ $ret .= '0';
+ }
+ $ret .= dechex( $c );
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @param string $keyword
+ */
+ public static 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 );
+ }
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Comment.php b/vendor/wikimedia/less.php/lib/Less/Tree/Comment.php
new file mode 100644
index 0000000..b4dd68c
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Comment.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Comment extends Less_Tree {
+
+ public $value;
+ public $silent;
+ public $isReferenced;
+ public $currentFileInfo;
+ public $type = 'Comment';
+
+ public function __construct( $value, $silent, $index = null, $currentFileInfo = null ) {
+ $this->value = $value;
+ $this->silent = (bool)$silent;
+ $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
+ }
+
+ public function toCSS() {
+ return Less_Parser::$options['compress'] ? '' : $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;
+ }
+
+ public function markReferenced() {
+ $this->isReferenced = true;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Condition.php b/vendor/wikimedia/less.php/lib/Less/Tree/Condition.php
new file mode 100644
index 0000000..5204e83
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Condition.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Condition extends Less_Tree {
+
+ public $op;
+ public $lvalue;
+ public $rvalue;
+ public $index;
+ public $negate;
+ public $type = 'Condition';
+
+ public function __construct( $op, $l, $r, $i = 0, $negate = false ) {
+ $this->op = trim( $op );
+ $this->lvalue = $l;
+ $this->rvalue = $r;
+ $this->index = $i;
+ $this->negate = $negate;
+ }
+
+ public function accept( $visitor ) {
+ $this->lvalue = $visitor->visitObj( $this->lvalue );
+ $this->rvalue = $visitor->visitObj( $this->rvalue );
+ }
+
+ public function compile( $env ) {
+ $a = $this->lvalue->compile( $env );
+ $b = $this->rvalue->compile( $env );
+
+ switch ( $this->op ) {
+ case 'and':
+ $result = $a && $b;
+ break;
+
+ case 'or':
+ $result = $a || $b;
+ 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 ) {
+ 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;
+ }
+ break;
+ }
+
+ return $this->negate ? !$result : $result;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/DefaultFunc.php b/vendor/wikimedia/less.php/lib/Less/Tree/DefaultFunc.php
new file mode 100644
index 0000000..66f0008
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/DefaultFunc.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_DefaultFunc {
+
+ static $error_;
+ static $value_;
+
+ public static function compile() {
+ if ( self::$error_ ) {
+ throw new Exception( self::$error_ );
+ }
+ if ( self::$value_ !== null ) {
+ return self::$value_ ? new Less_Tree_Keyword( 'true' ) : new Less_Tree_Keyword( 'false' );
+ }
+ }
+
+ public static function value( $v ) {
+ self::$value_ = $v;
+ }
+
+ public static function error( $e ) {
+ self::$error_ = $e;
+ }
+
+ public static function reset() {
+ self::$value_ = self::$error_ = null;
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/DetachedRuleset.php b/vendor/wikimedia/less.php/lib/Less/Tree/DetachedRuleset.php
new file mode 100644
index 0000000..6ba1ef3
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/DetachedRuleset.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_DetachedRuleset extends Less_Tree {
+
+ public $ruleset;
+ public $frames;
+ public $type = 'DetachedRuleset';
+
+ public function __construct( $ruleset, $frames = null ) {
+ $this->ruleset = $ruleset;
+ $this->frames = $frames;
+ }
+
+ public function accept( $visitor ) {
+ $this->ruleset = $visitor->visitObj( $this->ruleset );
+ }
+
+ public function compile( $env ) {
+ if ( $this->frames ) {
+ $frames = $this->frames;
+ } else {
+ $frames = $env->frames;
+ }
+ return new Less_Tree_DetachedRuleset( $this->ruleset, $frames );
+ }
+
+ public function callEval( $env ) {
+ if ( $this->frames ) {
+ return $this->ruleset->compile( $env->copyEvalEnv( array_merge( $this->frames, $env->frames ) ) );
+ }
+ return $this->ruleset->compile( $env );
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Dimension.php b/vendor/wikimedia/less.php/lib/Less/Tree/Dimension.php
new file mode 100644
index 0000000..4dd7198
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Dimension.php
@@ -0,0 +1,190 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Dimension extends Less_Tree {
+
+ public $value;
+ public $unit;
+ public $type = 'Dimension';
+
+ public function __construct( $value, $unit = null ) {
+ $this->value = floatval( $value );
+
+ if ( $unit && ( $unit instanceof Less_Tree_Unit ) ) {
+ $this->unit = $unit;
+ } elseif ( $unit ) {
+ $this->unit = new Less_Tree_Unit( [ $unit ] );
+ } else {
+ $this->unit = new Less_Tree_Unit();
+ }
+ }
+
+ public function accept( $visitor ) {
+ $this->unit = $visitor->visitObj( $this->unit );
+ }
+
+ public function toColor() {
+ return new Less_Tree_Color( [ $this->value, $this->value, $this->value ] );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ if ( Less_Parser::$options['strictUnits'] && !$this->unit->isSingular() ) {
+ 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 );
+ $strValue = (string)$value;
+
+ if ( $value !== 0 && $value < 0.000001 && $value > -0.000001 ) {
+ // would be output 1e-6 etc.
+ $strValue = number_format( (float)$strValue, 10 );
+ $strValue = preg_replace( '/\.?0+$/', '', $strValue );
+ }
+
+ if ( Less_Parser::$options['compress'] ) {
+ // Zero values doesn't need a unit
+ if ( $value === 0 && $this->unit->isLength() ) {
+ $output->add( $strValue );
+ return;
+ }
+
+ // Float values doesn't need a leading zero
+ if ( $value > 0 && $value < 1 && $strValue[0] === '0' ) {
+ $strValue = substr( $strValue, 1 );
+ }
+ }
+
+ $output->add( $strValue );
+ $this->unit->genCSS( $output );
+ }
+
+ public function __toString() {
+ return $this->toCSS();
+ }
+
+ // In an operation between two Dimensions,
+ // we default to the first Dimension's unit,
+ // so `1px + 2em` will yield `3px`.
+
+ /**
+ * @param string $op
+ */
+ public function operate( $op, $other ) {
+ $value = Less_Functions::operate( $op, $this->value, $other->value );
+ $unit = clone $this->unit;
+
+ if ( $op === '+' || $op === '-' ) {
+
+ if ( !$unit->numerator && !$unit->denominator ) {
+ $unit->numerator = $other->unit->numerator;
+ $unit->denominator = $other->unit->denominator;
+ } elseif ( !$other->unit->numerator && !$other->unit->denominator ) {
+ // do nothing
+ } else {
+ $other = $other->convertTo( $this->unit->usedUnits() );
+
+ if ( Less_Parser::$options['strictUnits'] && $other->unit->toString() !== $unit->toCSS() ) {
+ 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 );
+ }
+ } elseif ( $op === '*' ) {
+ $unit->numerator = array_merge( $unit->numerator, $other->unit->numerator );
+ $unit->denominator = array_merge( $unit->denominator, $other->unit->denominator );
+ sort( $unit->numerator );
+ sort( $unit->denominator );
+ $unit->cancel();
+ } elseif ( $op === '/' ) {
+ $unit->numerator = array_merge( $unit->numerator, $other->unit->denominator );
+ $unit->denominator = array_merge( $unit->denominator, $other->unit->numerator );
+ sort( $unit->numerator );
+ sort( $unit->denominator );
+ $unit->cancel();
+ }
+ return new Less_Tree_Dimension( $value, $unit );
+ }
+
+ 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;
+ }
+ }
+
+ public function unify() {
+ return $this->convertTo( [ 'length' => 'px', 'duration' => 's', 'angle' => 'rad' ] );
+ }
+
+ public function convertTo( $conversions ) {
+ $value = $this->value;
+ $unit = clone $this->unit;
+
+ if ( is_string( $conversions ) ) {
+ $derivedConversions = [];
+ foreach ( Less_Tree_UnitConversions::$groups as $i ) {
+ if ( isset( Less_Tree_UnitConversions::${$i}[$conversions] ) ) {
+ $derivedConversions = [ $i => $conversions ];
+ }
+ }
+ $conversions = $derivedConversions;
+ }
+
+ foreach ( $conversions as $groupName => $targetUnit ) {
+ $group = Less_Tree_UnitConversions::${$groupName};
+
+ // numerator
+ foreach ( $unit->numerator as $i => $atomicUnit ) {
+ $atomicUnit = $unit->numerator[$i];
+ if ( !isset( $group[$atomicUnit] ) ) {
+ continue;
+ }
+
+ $value = $value * ( $group[$atomicUnit] / $group[$targetUnit] );
+
+ $unit->numerator[$i] = $targetUnit;
+ }
+
+ // denominator
+ foreach ( $unit->denominator as $i => $atomicUnit ) {
+ $atomicUnit = $unit->denominator[$i];
+ if ( !isset( $group[$atomicUnit] ) ) {
+ continue;
+ }
+
+ $value = $value / ( $group[$atomicUnit] / $group[$targetUnit] );
+
+ $unit->denominator[$i] = $targetUnit;
+ }
+ }
+
+ $unit->cancel();
+
+ return new Less_Tree_Dimension( $value, $unit );
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Directive.php b/vendor/wikimedia/less.php/lib/Less/Tree/Directive.php
new file mode 100644
index 0000000..dfada84
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Directive.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Directive extends Less_Tree {
+
+ public $name;
+ public $value;
+ public $rules;
+ public $index;
+ public $isReferenced;
+ public $currentFileInfo;
+ public $debugInfo;
+ public $type = 'Directive';
+
+ public function __construct( $name, $value = null, $rules = null, $index = null, $currentFileInfo = null, $debugInfo = null ) {
+ $this->name = $name;
+ $this->value = $value;
+ if ( $rules ) {
+ $this->rules = $rules;
+ $this->rules->allowImports = true;
+ }
+
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ $this->debugInfo = $debugInfo;
+ }
+
+ public function accept( $visitor ) {
+ if ( $this->rules ) {
+ $this->rules = $visitor->visitObj( $this->rules );
+ }
+ if ( $this->value ) {
+ $this->value = $visitor->visitObj( $this->value );
+ }
+ }
+
+ /**
+ * @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 ) {
+ Less_Tree::outputRuleset( $output, [ $this->rules ] );
+ } else {
+ $output->add( ';' );
+ }
+ }
+
+ public function compile( $env ) {
+ $value = $this->value;
+ $rules = $this->rules;
+ if ( $value ) {
+ $value = $value->compile( $env );
+ }
+
+ if ( $rules ) {
+ $rules = $rules->compile( $env );
+ $rules->root = true;
+ }
+
+ return new Less_Tree_Directive( $this->name, $value, $rules, $this->index, $this->currentFileInfo, $this->debugInfo );
+ }
+
+ public function variable( $name ) {
+ if ( $this->rules ) {
+ return $this->rules->variable( $name );
+ }
+ }
+
+ public function find( $selector ) {
+ if ( $this->rules ) {
+ return $this->rules->find( $selector, $this );
+ }
+ }
+
+ // rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
+
+ public function markReferenced() {
+ $this->isReferenced = true;
+ if ( $this->rules ) {
+ Less_Tree::ReferencedArray( $this->rules->rules );
+ }
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Element.php b/vendor/wikimedia/less.php/lib/Less/Tree/Element.php
new file mode 100644
index 0000000..11b9ce4
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Element.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Element extends Less_Tree {
+
+ /** @var string */
+ public $combinator;
+ /** @var bool Whether combinator is null (represented by empty string) or child (single space) */
+ public $combinatorIsEmptyOrWhitespace;
+ /** @var string|Less_Tree */
+ public $value;
+ public $index;
+ public $currentFileInfo;
+ public $type = 'Element';
+
+ public $value_is_object = false;
+
+ /**
+ * @param null|string $combinator
+ * @param string|Less_Tree $value
+ * @param int|null $index
+ * @param array|null $currentFileInfo
+ */
+ public function __construct( $combinator, $value, $index = null, $currentFileInfo = null ) {
+ $this->value = $value;
+ $this->value_is_object = is_object( $value );
+
+ // see less-2.5.3.js#Combinator
+ $this->combinator = $combinator ?? '';
+ $this->combinatorIsEmptyOrWhitespace = ( $combinator === null || trim( $combinator ) === '' );
+
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ }
+
+ public function accept( $visitor ) {
+ if ( $this->value_is_object ) { // object or string
+ $this->value = $visitor->visitObj( $this->value );
+ }
+ }
+
+ public function compile( $env ) {
+ return new Less_Tree_Element(
+ $this->combinator,
+ ( $this->value_is_object ? $this->value->compile( $env ) : $this->value ),
+ $this->index,
+ $this->currentFileInfo
+ );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->toCSS(), $this->currentFileInfo, $this->index );
+ }
+
+ public function toCSS() {
+ if ( $this->value_is_object ) {
+ $value = $this->value->toCSS();
+ } else {
+ $value = $this->value;
+ }
+
+ if ( $value === '' && $this->combinator && $this->combinator === '&' ) {
+ return '';
+ }
+
+ return Less_Environment::$_outputMap[$this->combinator] . $value;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Expression.php b/vendor/wikimedia/less.php/lib/Less/Tree/Expression.php
new file mode 100644
index 0000000..8324141
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Expression.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Expression extends Less_Tree {
+ /** @var array */
+ public $value = [];
+ public $parens = false;
+ public $type = 'Expression';
+
+ public function __construct( $value, $parens = null ) {
+ $this->value = $value;
+ $this->parens = $parens;
+ }
+
+ public function accept( $visitor ) {
+ $this->value = $visitor->visitArray( $this->value );
+ }
+
+ public function compile( $env ) {
+ $doubleParen = false;
+
+ if ( $this->parens && !$this->parensInOp ) {
+ Less_Environment::$parensStack++;
+ }
+
+ $returnValue = null;
+ if ( $this->value ) {
+
+ $count = count( $this->value );
+
+ if ( $count > 1 ) {
+
+ $ret = [];
+ foreach ( $this->value as $e ) {
+ $ret[] = $e->compile( $env );
+ }
+ $returnValue = new Less_Tree_Expression( $ret );
+
+ } else {
+
+ if ( ( $this->value[0] instanceof Less_Tree_Expression ) && $this->value[0]->parens && !$this->value[0]->parensInOp ) {
+ $doubleParen = true;
+ }
+
+ $returnValue = $this->value[0]->compile( $env );
+ }
+
+ } else {
+ $returnValue = $this;
+ }
+
+ if ( $this->parens ) {
+ if ( !$this->parensInOp ) {
+ Less_Environment::$parensStack--;
+
+ } elseif ( !Less_Environment::isMathOn() && !$doubleParen ) {
+ $returnValue = new Less_Tree_Paren( $returnValue );
+
+ }
+ }
+ return $returnValue;
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $val_len = count( $this->value );
+ for ( $i = 0; $i < $val_len; $i++ ) {
+ $this->value[$i]->genCSS( $output );
+ if ( $i + 1 < $val_len ) {
+ $output->add( ' ' );
+ }
+ }
+ }
+
+ public function throwAwayComments() {
+ if ( is_array( $this->value ) ) {
+ $new_value = [];
+ foreach ( $this->value as $v ) {
+ if ( $v instanceof Less_Tree_Comment ) {
+ continue;
+ }
+ $new_value[] = $v;
+ }
+ $this->value = $new_value;
+ }
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Extend.php b/vendor/wikimedia/less.php/lib/Less/Tree/Extend.php
new file mode 100644
index 0000000..362e284
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Extend.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Extend extends Less_Tree {
+
+ public $selector;
+ public $option;
+ public $index;
+ public $selfSelectors = [];
+ public $allowBefore;
+ public $allowAfter;
+ public $firstExtendOnThisSelectorPath;
+ public $type = 'Extend';
+ public $ruleset;
+
+ public $object_id;
+ public $parent_ids = [];
+
+ /**
+ * @param int $index
+ */
+ public function __construct( $selector, $option, $index ) {
+ static $i = 0;
+ $this->selector = $selector;
+ $this->option = $option;
+ $this->index = $index;
+
+ switch ( $option ) {
+ case "all":
+ $this->allowBefore = true;
+ $this->allowAfter = true;
+ break;
+ default:
+ $this->allowBefore = false;
+ $this->allowAfter = false;
+ break;
+ }
+
+ // This must use a string (instead of int) so that array_merge()
+ // preserves keys on arrays that use IDs in their keys.
+ $this->object_id = 'id_' . $i++;
+
+ $this->parent_ids = [
+ $this->object_id => true
+ ];
+ }
+
+ public function accept( $visitor ) {
+ $this->selector = $visitor->visitObj( $this->selector );
+ }
+
+ public function compile( $env ) {
+ 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);
+ }
+
+ public function findSelfSelectors( $selectors ) {
+ $selfElements = [];
+
+ for ( $i = 0, $selectors_len = count( $selectors ); $i < $selectors_len; $i++ ) {
+ $selectorElements = $selectors[$i]->elements;
+ // duplicate the logic in genCSS function inside the selector node.
+ // future TODO - move both logics into the selector joiner visitor
+ if ( $i && $selectorElements && $selectorElements[0]->combinator === "" ) {
+ $selectorElements[0]->combinator = ' ';
+ }
+ $selfElements = array_merge( $selfElements, $selectors[$i]->elements );
+ }
+
+ $this->selfSelectors = [ new Less_Tree_Selector( $selfElements ) ];
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Import.php b/vendor/wikimedia/less.php/lib/Less/Tree/Import.php
new file mode 100644
index 0000000..fc5e81d
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Import.php
@@ -0,0 +1,299 @@
+<?php
+/**
+ * CSS `@import` node
+ *
+ * The general strategy here is that we don't want to wait
+ * for the parsing to be completed, before we start importing
+ * the file. That's because in the context of a browser,
+ * most of the time will be spent waiting for the server to respond.
+ *
+ * On creation, we push the import path to our import queue, though
+ * `import,push`, we also pass it a callback, which it'll call once
+ * the file has been fetched, and parsed.
+ *
+ * @private
+ */
+class Less_Tree_Import extends Less_Tree {
+
+ public $options;
+ public $index;
+ public $path;
+ public $features;
+ public $currentFileInfo;
+ public $css;
+ public $skip;
+ public $root;
+ public $type = 'Import';
+
+ public function __construct( $path, $features, $options, $index, $currentFileInfo = null ) {
+ $this->options = $options;
+ $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;
+ }
+ }
+ }
+ }
+
+//
+// The actual import node doesn't return anything, when converted to CSS.
+// The reason is that it's used at the evaluation stage, so that the rules
+// it imports can be treated like any other rules.
+//
+// In `eval`, we make sure all Import nodes get evaluated, recursively, so
+// we end up with a flat structure, which can easily be imported in the parent
+// ruleset.
+//
+
+ public function accept( $visitor ) {
+ if ( $this->features ) {
+ $this->features = $visitor->visitObj( $this->features );
+ }
+ $this->path = $visitor->visitObj( $this->path );
+
+ if ( !$this->options['inline'] && $this->root ) {
+ $this->root = $visitor->visit( $this->root );
+ }
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ if ( $this->css ) {
+
+ $output->add( '@import ', $this->currentFileInfo, $this->index );
+
+ $this->path->genCSS( $output );
+ if ( $this->features ) {
+ $output->add( ' ' );
+ $this->features->genCSS( $output );
+ }
+ $output->add( ';' );
+ }
+ }
+
+ 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;
+ }
+
+ // remove query string and fragment
+ return preg_replace( '/[\?#][^\?]*$/', '', $path );
+ }
+
+ public function compileForImport( $env ) {
+ return new Less_Tree_Import( $this->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'];
+ }
+
+ if ( !( $path instanceof Less_Tree_URL ) ) {
+ if ( $rootpath ) {
+ $pathValue = $path->value;
+ // Add the base path if the import is relative
+ if ( $pathValue && Less_Environment::isPathRelative( $pathValue ) ) {
+ $path->value = $this->currentFileInfo['uri_root'] . $pathValue;
+ }
+ }
+ $path->value = Less_Environment::normalizePath( $path->value );
+ }
+
+ return $path;
+ }
+
+ 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 );
+ }
+
+ if ( !$path_and_uri ) {
+ $path_and_uri = $evald->PathAndUri();
+ }
+
+ if ( $path_and_uri ) {
+ list( $full_path, $uri ) = $path_and_uri;
+ } else {
+ $full_path = $uri = $evald->getPath();
+ }
+
+ // import once
+ if ( $evald->skip( $full_path, $env ) ) {
+ return [];
+ }
+ '@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 );
+
+ 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 ) ) ) {
+ return [];
+ }
+
+ // 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 $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 ) ) {
+ list( $path, $uri ) = call_user_func( $rooturi, $evald_path );
+ if ( is_string( $path ) ) {
+ $full_path = $path;
+ return [ $full_path, $uri ];
+ }
+ } elseif ( !empty( $rootpath ) ) {
+
+ $path = rtrim( $rootpath, '/\\' ) . '/' . ltrim( $evald_path, '/\\' );
+
+ if ( file_exists( $path ) ) {
+ $full_path = Less_Environment::normalizePath( $path );
+ $uri = Less_Environment::normalizePath( dirname( $rooturi . $evald_path ) );
+ return [ $full_path, $uri ];
+ } elseif ( file_exists( $path . '.less' ) ) {
+ $full_path = Less_Environment::normalizePath( $path . '.less' );
+ $uri = Less_Environment::normalizePath( dirname( $rooturi . $evald_path . '.less' ) );
+ return [ $full_path, $uri ];
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Should the import be skipped?
+ *
+ * @param string|null $path
+ * @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;
+ }
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Javascript.php b/vendor/wikimedia/less.php/lib/Less/Tree/Javascript.php
new file mode 100644
index 0000000..218d481
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Javascript.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Javascript extends Less_Tree {
+
+ public $type = 'Javascript';
+ public $escaped;
+ public $expression;
+ public $index;
+
+ /**
+ * @param bool $index
+ * @param bool $escaped
+ */
+ public function __construct( $string, $index, $escaped ) {
+ $this->escaped = $escaped;
+ $this->expression = $string;
+ $this->index = $index;
+ }
+
+ public function compile( $env ) {
+ return new Less_Tree_Anonymous( '/* Sorry, can not do JavaScript evaluation in PHP... :( */' );
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Keyword.php b/vendor/wikimedia/less.php/lib/Less/Tree/Keyword.php
new file mode 100644
index 0000000..60663f0
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Keyword.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Keyword extends Less_Tree {
+
+ public $value;
+ public $type = 'Keyword';
+
+ /**
+ * @param string $value
+ */
+ public function __construct( $value ) {
+ $this->value = $value;
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ if ( $this->value === '%' ) {
+ throw new Less_Exception_Compiler( "Invalid % without number" );
+ }
+
+ $output->add( $this->value );
+ }
+
+ public function compare( $other ) {
+ if ( $other instanceof Less_Tree_Keyword ) {
+ return $other->value === $this->value ? 0 : 1;
+ } else {
+ return -1;
+ }
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Media.php b/vendor/wikimedia/less.php/lib/Less/Tree/Media.php
new file mode 100644
index 0000000..3cb1fc4
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Media.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Media extends Less_Tree {
+
+ public $features;
+ public $rules;
+ public $index;
+ public $currentFileInfo;
+ public $isReferenced;
+ public $type = 'Media';
+
+ public function __construct( $value = [], $features = [], $index = null, $currentFileInfo = null ) {
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+
+ $selectors = $this->emptySelectors();
+
+ $this->features = new Less_Tree_Value( $features );
+
+ $this->rules = [ new Less_Tree_Ruleset( $selectors, $value ) ];
+ $this->rules[0]->allowImports = true;
+ }
+
+ public function accept( $visitor ) {
+ $this->features = $visitor->visitObj( $this->features );
+ $this->rules = $visitor->visitArray( $this->rules );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( '@media ', $this->currentFileInfo, $this->index );
+ $this->features->genCSS( $output );
+ Less_Tree::outputRuleset( $output, $this->rules );
+ }
+
+ /**
+ * @param Less_Environment $env
+ * @return Less_Tree_Media|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 );
+
+ $strictMathBypass = false;
+ if ( Less_Parser::$options['strictMath'] === false ) {
+ $strictMathBypass = true;
+ Less_Parser::$options['strictMath'] = true;
+ }
+
+ $media->features = $this->features->compile( $env );
+
+ if ( $strictMathBypass ) {
+ Less_Parser::$options['strictMath'] = false;
+ }
+
+ $env->mediaPath[] = $media;
+ $env->mediaBlocks[] = $media;
+
+ array_unshift( $env->frames, $this->rules[0] );
+ $media->rules = [ $this->rules[0]->compile( $env ) ];
+ array_shift( $env->frames );
+
+ array_pop( $env->mediaPath );
+
+ return !$env->mediaPath ? $media->compileTop( $env ) : $media->compileNested( $env );
+ }
+
+ public function variable( $name ) {
+ return $this->rules[0]->variable( $name );
+ }
+
+ public function find( $selector ) {
+ return $this->rules[0]->find( $selector, $this );
+ }
+
+ public function emptySelectors() {
+ $el = new Less_Tree_Element( '', '&', $this->index, $this->currentFileInfo );
+ $sels = [ new Less_Tree_Selector( [ $el ], [], null, $this->index, $this->currentFileInfo ) ];
+ $sels[0]->mediaEmpty = true;
+ return $sels;
+ }
+
+ public function markReferenced() {
+ $this->rules[0]->markReferenced();
+ $this->isReferenced = true;
+ Less_Tree::ReferencedArray( $this->rules[0]->rules );
+ }
+
+ // evaltop
+ public function compileTop( $env ) {
+ $result = $this;
+
+ if ( count( $env->mediaBlocks ) > 1 ) {
+ $selectors = $this->emptySelectors();
+ $result = new Less_Tree_Ruleset( $selectors, $env->mediaBlocks );
+ $result->multiMedia = true;
+ }
+
+ $env->mediaBlocks = [];
+ $env->mediaPath = [];
+
+ return $result;
+ }
+
+ /**
+ * @param Less_Environment $env
+ * @return Less_Tree_Ruleset
+ */
+ public function compileNested( $env ) {
+ $path = array_merge( $env->mediaPath, [ $this ] );
+ '@phan-var array<Less_Tree_Media> $path';
+
+ // Extract the media-query conditions separated with `,` (OR).
+ foreach ( $path as $key => $p ) {
+ $value = $p->features instanceof Less_Tree_Value ? $p->features->value : $p->features;
+ $path[$key] = is_array( $value ) ? $value : [ $value ];
+ }
+ '@phan-var array<array<Less_Tree>> $path';
+
+ // Trace all permutations to generate the resulting media-query.
+ //
+ // (a, b and c) with nested (d, e) ->
+ // a and d
+ // a and e
+ // b and c and d
+ // b and c and e
+
+ $permuted = $this->permute( $path );
+ $expressions = [];
+ foreach ( $permuted as $path ) {
+
+ for ( $i = 0, $len = count( $path ); $i < $len; $i++ ) {
+ $path[$i] = Less_Parser::is_method( $path[$i], 'toCSS' ) ? $path[$i] : new Less_Tree_Anonymous( $path[$i] );
+ }
+
+ for ( $i = count( $path ) - 1; $i > 0; $i-- ) {
+ array_splice( $path, $i, 0, [ new Less_Tree_Anonymous( 'and' ) ] );
+ }
+
+ $expressions[] = new Less_Tree_Expression( $path );
+ }
+ $this->features = new Less_Tree_Value( $expressions );
+
+ // Fake a tree-node that doesn't output anything.
+ return new Less_Tree_Ruleset( [], [] );
+ }
+
+ public function permute( $arr ) {
+ if ( !$arr ) {
+ return [];
+ }
+
+ if ( count( $arr ) == 1 ) {
+ return $arr[0];
+ }
+
+ $result = [];
+ $rest = $this->permute( array_slice( $arr, 1 ) );
+ foreach ( $rest as $r ) {
+ foreach ( $arr[0] as $a ) {
+ $result[] = array_merge(
+ is_array( $a ) ? $a : [ $a ],
+ is_array( $r ) ? $r : [ $r ]
+ );
+ }
+ }
+
+ return $result;
+ }
+
+ public function bubbleSelectors( $selectors ) {
+ if ( !$selectors ) {
+ return;
+ }
+
+ $this->rules = [ new Less_Tree_Ruleset( $selectors, [ $this->rules[0] ] ) ];
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Call.php b/vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Call.php
new file mode 100644
index 0000000..61e10fe
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Call.php
@@ -0,0 +1,197 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Mixin_Call extends Less_Tree {
+
+ public $selector;
+ public $arguments;
+ public $index;
+ 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;
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ $this->important = $important;
+ }
+
+ // function accept($visitor){
+ // $this->selector = $visitor->visit($this->selector);
+ // $this->arguments = $visitor->visit($this->arguments);
+ //}
+
+ public function compile( $env ) {
+ $rules = [];
+ $match = false;
+ $isOneFound = false;
+ $candidates = [];
+ $defaultUsed = false;
+ $conditionResult = [];
+
+ $args = [];
+ foreach ( $this->arguments as $a ) {
+ $args[] = [ 'name' => $a['name'], 'value' => $a['value']->compile( $env ) ];
+ }
+
+ 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`),
+ // and build candidate list with corresponding flags. Then, when we know all possible matches,
+ // we make a final decision.
+
+ $mixins_len = count( $mixins );
+ for ( $m = 0; $m < $mixins_len; $m++ ) {
+ $mixin = $mixins[$m];
+
+ if ( $this->IsRecursive( $env, $mixin ) ) {
+ continue;
+ }
+
+ 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;
+ }
+
+ $candidates[] = $candidate;
+ }
+ } else {
+ $candidates[] = $candidate;
+ }
+
+ $match = true;
+ }
+ }
+
+ Less_Tree_DefaultFunc::reset();
+
+ $count = [ 0, 0, 0 ];
+ for ( $m = 0; $m < count( $candidates ); $m++ ) {
+ $count[ $candidates[$m]['group'] ]++;
+ }
+
+ if ( $count[$defNone] > 0 ) {
+ $defaultResult = $defFalse;
+ } else {
+ $defaultResult = $defTrue;
+ if ( ( $count[$defTrue] + $count[$defFalse] ) > 1 ) {
+ throw new Exception( 'Ambiguous use of `default()` found when matching for `' . $this->format( $args ) . '`' );
+ }
+ }
+
+ $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{
+ $mixin = $candidates[$m]['mixin'];
+ if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) {
+ $mixin = new Less_Tree_Mixin_Definition( '', [], $mixin->rules, null, false );
+ $mixin->originalRuleset = $mixins[$m]->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 );
+ }
+ }
+ }
+
+ if ( $match ) {
+ if ( !$this->currentFileInfo || !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] ) {
+ Less_Tree::ReferencedArray( $rules );
+ }
+
+ return $rules;
+ }
+ }
+
+ if ( $isOneFound ) {
+ throw new Less_Exception_Compiler( 'No matching definition was found for `' . $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 );
+ }
+ }
+
+ /**
+ * Format the args for use in exception messages
+ *
+ */
+ private function Format( $args ) {
+ $message = [];
+ if ( $args ) {
+ foreach ( $args as $a ) {
+ $argValue = '';
+ if ( $a['name'] ) {
+ $argValue .= $a['name'] . ':';
+ }
+ if ( is_object( $a['value'] ) ) {
+ $argValue .= $a['value']->toCSS();
+ } else {
+ $argValue .= '???';
+ }
+ $message[] = $argValue;
+ }
+ }
+ return implode( ', ', $message );
+ }
+
+ /**
+ * Are we in a recursive mixin call?
+ *
+ * @return bool
+ */
+ private function IsRecursive( $env, $mixin ) {
+ foreach ( $env->frames as $recur_frame ) {
+ if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) {
+
+ if ( $mixin === $recur_frame ) {
+ return true;
+ }
+
+ if ( isset( $recur_frame->originalRuleset ) && $mixin->ruleset_id === $recur_frame->originalRuleset ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Definition.php b/vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Definition.php
new file mode 100644
index 0000000..08bcd7a
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Mixin/Definition.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
+ public $name;
+ public $selectors;
+ public $params;
+ public $arity = 0;
+ public $rules;
+ public $lookups = [];
+ public $required = 0;
+ 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 ) ] ) ];
+
+ $this->params = $params;
+ $this->condition = $condition;
+ $this->variadic = $variadic;
+ $this->rules = $rules;
+
+ if ( $params ) {
+ $this->arity = count( $params );
+ foreach ( $params as $p ) {
+ if ( !isset( $p['name'] ) || ( $p['name'] && !isset( $p['value'] ) ) ) {
+ $this->required++;
+ }
+ }
+ }
+
+ $this->frames = $frames;
+ $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
+ public function compileParams( $env, $mixinFrames, $args = [], &$evaldArguments = [] ) {
+ $frame = new Less_Tree_Ruleset( null, [] );
+ $params = $this->params;
+ $mixinEnv = null;
+ $argsLength = 0;
+
+ if ( $args ) {
+ $argsLength = count( $args );
+ for ( $i = 0; $i < $argsLength; $i++ ) {
+ $arg = $args[$i];
+
+ if ( $arg && $arg['name'] ) {
+ $isNamedFound = false;
+
+ foreach ( $params as $j => $param ) {
+ if ( !isset( $evaldArguments[$j] ) && $arg['name'] === $params[$j]['name'] ) {
+ $evaldArguments[$j] = $arg['value']->compile( $env );
+ array_unshift( $frame->rules, new Less_Tree_Rule( $arg['name'], $arg['value']->compile( $env ) ) );
+ $isNamedFound = true;
+ break;
+ }
+ }
+ if ( $isNamedFound ) {
+ array_splice( $args, $i, 1 );
+ $i--;
+ $argsLength--;
+ continue;
+ } else {
+ throw new Less_Exception_Compiler( "Named argument for " . $this->name . ' ' . $args[$i]['name'] . ' not found' );
+ }
+ }
+ }
+ }
+
+ $argIndex = 0;
+ foreach ( $params as $i => $param ) {
+
+ if ( isset( $evaldArguments[$i] ) ) { continue;
+ }
+
+ $arg = null;
+ if ( isset( $args[$argIndex] ) ) {
+ $arg = $args[$argIndex];
+ }
+
+ if ( isset( $param['name'] ) && $param['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 ) ) );
+ } else {
+ $val = ( $arg && $arg['value'] ) ? $arg['value'] : false;
+
+ if ( $val ) {
+ $val = $val->compile( $env );
+ } elseif ( isset( $param['value'] ) ) {
+
+ if ( !$mixinEnv ) {
+ $mixinEnv = new Less_Environment();
+ $mixinEnv->frames = array_merge( [ $frame ], $mixinFrames );
+ }
+
+ $val = $param['value']->compile( $mixinEnv );
+ $frame->resetCache();
+ } else {
+ 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 ) );
+ $evaldArguments[$i] = $val;
+ }
+ }
+
+ if ( isset( $param['variadic'] ) && $args ) {
+ for ( $j = $argIndex; $j < $argsLength; $j++ ) {
+ $evaldArguments[$j] = $args[$j]['value']->compile( $env );
+ }
+ }
+ $argIndex++;
+ }
+
+ ksort( $evaldArguments );
+ $evaldArguments = array_values( $evaldArguments );
+
+ return $frame;
+ }
+
+ 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 Less_Tree_Mixin_Definition( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
+ }
+
+ public function evalCall( $env, $args = null, $important = null ) {
+ Less_Environment::$mixin_stack++;
+
+ $_arguments = [];
+
+ if ( $this->frames ) {
+ $mixinFrames = array_merge( $this->frames, $env->frames );
+ } else {
+ $mixinFrames = $env->frames;
+ }
+
+ $frame = $this->compileParams( $env, $mixinFrames, $args, $_arguments );
+
+ $ex = new Less_Tree_Expression( $_arguments );
+ array_unshift( $frame->rules, new Less_Tree_Rule( '@arguments', $ex->compile( $env ) ) );
+
+ $ruleset = new Less_Tree_Ruleset( null, $this->rules );
+ $ruleset->originalRuleset = $this->ruleset_id;
+
+ $ruleSetEnv = new Less_Environment();
+ $ruleSetEnv->frames = array_merge( [ $this, $frame ], $mixinFrames );
+ $ruleset = $ruleset->compile( $ruleSetEnv );
+
+ if ( $important ) {
+ $ruleset = $ruleset->makeImportant();
+ }
+
+ Less_Environment::$mixin_stack--;
+
+ return $ruleset;
+ }
+
+ /** @return bool */
+ public function matchCondition( $args, $env ) {
+ if ( !$this->condition ) {
+ return true;
+ }
+
+ // set array to prevent error on array_merge
+ if ( !is_array( $this->frames ) ) {
+ $this->frames = [];
+ }
+
+ $frame = $this->compileParams( $env, array_merge( $this->frames, $env->frames ), $args );
+
+ $compile_env = new Less_Environment();
+ $compile_env->frames = array_merge(
+ [ $frame ], // the parameter variables
+ $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 );
+ }
+
+ public function matchArgs( $args, $env = null ) {
+ $argsLength = count( $args );
+
+ if ( !$this->variadic ) {
+ if ( $argsLength < $this->required ) {
+ return false;
+ }
+ if ( $argsLength > count( $this->params ) ) {
+ return false;
+ }
+ } else {
+ if ( $argsLength < ( $this->required - 1 ) ) {
+ return false;
+ }
+ }
+
+ $len = min( $argsLength, $this->arity );
+
+ for ( $i = 0; $i < $len; $i++ ) {
+ if ( !isset( $this->params[$i]['name'] ) && !isset( $this->params[$i]['variadic'] ) ) {
+ if ( $args[$i]['value']->compile( $env )->toCSS() != $this->params[$i]['value']->compile( $env )->toCSS() ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/NameValue.php b/vendor/wikimedia/less.php/lib/Less/Tree/NameValue.php
new file mode 100644
index 0000000..88a2296
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/NameValue.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * A simple CSS name-value pair, e.g. `width: 100px;`
+ *
+ * In bootstrap, there are about 600-1000 simple name-value pairs (depending on
+ * how forgiving the match is) -vs- 6,020 dynamic rules (Less_Tree_Rule).
+ *
+ * Using the name-value object can speed up bootstrap compilation slightly, but
+ * it breaks color keyword interpretation: `color: red` -> `color: #FF0000`.
+ *
+ * @private
+ */
+class Less_Tree_NameValue extends Less_Tree {
+
+ public $name;
+ public $value;
+ public $index;
+ public $currentFileInfo;
+ public $type = 'NameValue';
+ public $important = '';
+
+ public function __construct( $name, $value = null, $index = null, $currentFileInfo = null ) {
+ $this->name = $name;
+ $this->value = $value;
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ }
+
+ public function genCSS( $output ) {
+ $output->add(
+ $this->name
+ . Less_Environment::$_outputMap[': ']
+ . $this->value
+ . $this->important
+ . ( ( ( Less_Environment::$lastRule && Less_Parser::$options['compress'] ) ) ? "" : ";" ),
+ $this->currentFileInfo, $this->index );
+ }
+
+ public function compile( $env ) {
+ return $this;
+ }
+
+ public function makeImportant() {
+ $new = new Less_Tree_NameValue( $this->name, $this->value, $this->index, $this->currentFileInfo );
+ $new->important = ' !important';
+ return $new;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Negative.php b/vendor/wikimedia/less.php/lib/Less/Tree/Negative.php
new file mode 100644
index 0000000..516f1ee
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Negative.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Negative extends Less_Tree {
+
+ public $value;
+ public $type = 'Negative';
+
+ public function __construct( $node ) {
+ $this->value = $node;
+ }
+
+ // function accept($visitor) {
+ // $this->value = $visitor->visit($this->value);
+ //}
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( '-' );
+ $this->value->genCSS( $output );
+ }
+
+ public function compile( $env ) {
+ if ( Less_Environment::isMathOn() ) {
+ $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 ) );
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Operation.php b/vendor/wikimedia/less.php/lib/Less/Tree/Operation.php
new file mode 100644
index 0000000..4d79dc0
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Operation.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Operation extends Less_Tree {
+
+ public $op;
+ public $operands;
+ public $isSpaced;
+ public $type = 'Operation';
+
+ /**
+ * @param string $op
+ */
+ public function __construct( $op, $operands, $isSpaced = false ) {
+ $this->op = trim( $op );
+ $this->operands = $operands;
+ $this->isSpaced = $isSpaced;
+ }
+
+ public function accept( $visitor ) {
+ $this->operands = $visitor->visitArray( $this->operands );
+ }
+
+ public function compile( $env ) {
+ $a = $this->operands[0]->compile( $env );
+ $b = $this->operands[1]->compile( $env );
+
+ if ( Less_Environment::isMathOn() ) {
+
+ if ( $a instanceof Less_Tree_Dimension && $b instanceof Less_Tree_Color ) {
+ $a = $a->toColor();
+
+ } elseif ( $b instanceof Less_Tree_Dimension && $a instanceof Less_Tree_Color ) {
+ $b = $b->toColor();
+
+ }
+
+ if ( !method_exists( $a, 'operate' ) ) {
+ throw new Less_Exception_Compiler( "Operation on an invalid type" );
+ }
+
+ return $a->operate( $this->op, $b );
+ }
+
+ return new Less_Tree_Operation( $this->op, [ $a, $b ], $this->isSpaced );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $this->operands[0]->genCSS( $output );
+ if ( $this->isSpaced ) {
+ $output->add( " " );
+ }
+ $output->add( $this->op );
+ if ( $this->isSpaced ) {
+ $output->add( ' ' );
+ }
+ $this->operands[1]->genCSS( $output );
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Paren.php b/vendor/wikimedia/less.php/lib/Less/Tree/Paren.php
new file mode 100644
index 0000000..d659b84
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Paren.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Paren extends Less_Tree {
+
+ /** @var Less_Tree $value */
+ public $value;
+ public $type = 'Paren';
+
+ /**
+ * @param Less_Tree $value
+ */
+ public function __construct( $value ) {
+ $this->value = $value;
+ }
+
+ public function accept( $visitor ) {
+ $this->value = $visitor->visitObj( $this->value );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( '(' );
+ $this->value->genCSS( $output );
+ $output->add( ')' );
+ }
+
+ public function compile( $env ) {
+ return new Less_Tree_Paren( $this->value->compile( $env ) );
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Quoted.php b/vendor/wikimedia/less.php/lib/Less/Tree/Quoted.php
new file mode 100644
index 0000000..0c5e190
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Quoted.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Quoted extends Less_Tree {
+ public $escaped;
+ public $value;
+ public $quote;
+ public $index;
+ public $currentFileInfo;
+ public $type = 'Quoted';
+
+ /**
+ * @param string $str
+ */
+ public function __construct( $str, $content = '', $escaped = false, $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 as $i => $match ) {
+ $js = new Less_Tree_JavaScript( $matches[1], $this->index, true );
+ $js = $js->compile( $env )->value;
+ $value = str_replace( $matches[0][$i], $js, $value );
+ }
+ }
+
+ 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 Less_Tree_Quoted ) ? $v->value : $v->toCSS();
+ $value = str_replace( $matches[0][$i], $v, $value );
+ }
+ }
+
+ return new Less_Tree_Quoted( $this->quote . $value . $this->quote, $value, $this->escaped, $this->index, $this->currentFileInfo );
+ }
+
+ public function compare( $x ) {
+ if ( !Less_Parser::is_method( $x, 'toCSS' ) ) {
+ return -1;
+ }
+
+ $left = $this->toCSS();
+ $right = $x->toCSS();
+
+ if ( $left === $right ) {
+ return 0;
+ }
+
+ return $left < $right ? -1 : 1;
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Rule.php b/vendor/wikimedia/less.php/lib/Less/Tree/Rule.php
new file mode 100644
index 0000000..842ad0c
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Rule.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Rule extends Less_Tree {
+
+ public $name;
+ /** @var Less_Tree $value */
+ public $value;
+ public $important;
+ public $merge;
+ public $index;
+ public $inline;
+ public $variable;
+ public $currentFileInfo;
+ public $type = 'Rule';
+
+ /**
+ * @param string $important
+ */
+ public function __construct( $name, $value = null, $important = null, $merge = null, $index = null, $currentFileInfo = null, $inline = false ) {
+ $this->name = $name;
+ $this->value = ( $value instanceof Less_Tree )
+ ? $value
+ : new Less_Tree_Value( [ $value ] );
+ $this->important = $important ? ' ' . trim( $important ) : '';
+ $this->merge = $merge;
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ $this->inline = $inline;
+ $this->variable = ( is_string( $name ) && $name[0] === '@' );
+ }
+
+ public function accept( $visitor ) {
+ $this->value = $visitor->visitObj( $this->value );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->name . Less_Environment::$_outputMap[': '], $this->currentFileInfo, $this->index );
+ try{
+ $this->value->genCSS( $output );
+
+ }catch ( Less_Exception_Parser $e ) {
+ $e->index = $this->index;
+ $e->currentFile = $this->currentFileInfo;
+ throw $e;
+ }
+ $output->add( $this->important . ( ( $this->inline || ( Less_Environment::$lastRule && Less_Parser::$options['compress'] ) ) ? "" : ";" ), $this->currentFileInfo, $this->index );
+ }
+
+ /**
+ * @param Less_Environment $env
+ * @return Less_Tree_Rule
+ */
+ public function compile( $env ) {
+ $name = $this->name;
+ if ( is_array( $name ) ) {
+ // expand 'primitive' name directly to get
+ // things faster (~10% for benchmark.less):
+ if ( count( $name ) === 1 && $name[0] instanceof Less_Tree_Keyword ) {
+ $name = $name[0]->value;
+ } else {
+ $name = $this->CompileName( $env, $name );
+ }
+ }
+
+ $strictMathBypass = Less_Parser::$options['strictMath'];
+ if ( $name === "font" && !Less_Parser::$options['strictMath'] ) {
+ Less_Parser::$options['strictMath'] = true;
+ }
+
+ try {
+ $evaldValue = $this->value->compile( $env );
+
+ if ( !$this->variable && $evaldValue->type === "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 );
+ } else {
+ $this->name = $name;
+ $this->value = $evaldValue;
+ $return = $this;
+ }
+
+ } catch ( Less_Exception_Parser $e ) {
+ if ( !is_numeric( $e->index ) ) {
+ $e->index = $this->index;
+ $e->currentFile = $this->currentFileInfo;
+ }
+ throw $e;
+ }
+
+ Less_Parser::$options['strictMath'] = $strictMathBypass;
+
+ return $return;
+ }
+
+ public function CompileName( $env, $name ) {
+ $output = new Less_Output();
+ foreach ( $name as $n ) {
+ $n->compile( $env )->genCSS( $output );
+ }
+ return $output->toString();
+ }
+
+ public function makeImportant() {
+ return new Less_Tree_Rule( $this->name, $this->value, '!important', $this->merge, $this->index, $this->currentFileInfo, $this->inline );
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Ruleset.php b/vendor/wikimedia/less.php/lib/Less/Tree/Ruleset.php
new file mode 100644
index 0000000..7acc6af
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Ruleset.php
@@ -0,0 +1,730 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Ruleset extends Less_Tree {
+
+ protected $lookups;
+ public $_variables;
+ public $_rulesets;
+
+ public $strictImports;
+
+ public $selectors;
+ public $rules;
+ public $root;
+ public $allowImports;
+ public $paths;
+ public $firstRoot;
+ public $type = 'Ruleset';
+ public $multiMedia;
+ public $allExtends;
+
+ public $ruleset_id;
+ public $originalRuleset;
+
+ public $first_oelements;
+
+ public function SetRulesetIndex() {
+ $this->ruleset_id = Less_Parser::$next_id++;
+ $this->originalRuleset = $this->ruleset_id;
+
+ if ( $this->selectors ) {
+ foreach ( $this->selectors as $sel ) {
+ if ( $sel->_oelements ) {
+ $this->first_oelements[$sel->_oelements[0]] = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param null|Less_Tree_Selector[] $selectors
+ * @param Less_Tree[] $rules
+ * @param null|bool $strictImports
+ */
+ public function __construct( $selectors, $rules, $strictImports = null ) {
+ $this->selectors = $selectors;
+ $this->rules = $rules;
+ $this->lookups = [];
+ $this->strictImports = $strictImports;
+ $this->SetRulesetIndex();
+ }
+
+ public function accept( $visitor ) {
+ if ( $this->paths !== null ) {
+ $paths_len = count( $this->paths );
+ for ( $i = 0; $i < $paths_len; $i++ ) {
+ $this->paths[$i] = $visitor->visitArray( $this->paths[$i] );
+ }
+ } elseif ( $this->selectors ) {
+ $this->selectors = $visitor->visitArray( $this->selectors );
+ }
+
+ if ( $this->rules ) {
+ $this->rules = $visitor->visitArray( $this->rules );
+ }
+ }
+
+ /**
+ * @param Less_Environment $env
+ * @return Less_Tree_Ruleset
+ * @see less-2.5.3.js#Ruleset.prototype.eval
+ */
+ public function compile( $env ) {
+ $ruleset = $this->PrepareRuleset( $env );
+
+ // Store the frames around mixin definitions,
+ // so they can be evaluated like closures when the time comes.
+ $rsRuleCnt = count( $ruleset->rules );
+ for ( $i = 0; $i < $rsRuleCnt; $i++ ) {
+ // These checks are the equivalent of the rule.evalFirst property in less.js
+ if ( $ruleset->rules[$i] instanceof Less_Tree_Mixin_Definition || $ruleset->rules[$i] instanceof Less_Tree_DetachedRuleset ) {
+ $ruleset->rules[$i] = $ruleset->rules[$i]->compile( $env );
+ }
+ }
+
+ $mediaBlockCount = count( $env->mediaBlocks );
+
+ // Evaluate mixin calls.
+ $this->EvalMixinCalls( $ruleset, $env, $rsRuleCnt );
+
+ // Evaluate everything else
+ for ( $i = 0; $i < $rsRuleCnt; $i++ ) {
+ if ( !( $ruleset->rules[$i] instanceof Less_Tree_Mixin_Definition || $ruleset->rules[$i] instanceof Less_Tree_DetachedRuleset ) ) {
+ $ruleset->rules[$i] = $ruleset->rules[$i]->compile( $env );
+ }
+ }
+
+ // Evaluate everything else
+ for ( $i = 0; $i < $rsRuleCnt; $i++ ) {
+ $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 ) {
+
+ // check if it can be folded in (e.g. & where)
+ if ( $rule->selectors[0]->isJustParentSelector() ) {
+ array_splice( $ruleset->rules, $i--, 1 );
+ $rsRuleCnt--;
+
+ for ( $j = 0; $j < count( $rule->rules ); $j++ ) {
+ $subRule = $rule->rules[$j];
+ if ( !( $subRule instanceof Less_Tree_Rule ) || !$subRule->variable ) {
+ array_splice( $ruleset->rules, ++$i, 0, [ $subRule ] );
+ $rsRuleCnt++;
+ }
+ }
+
+ }
+ }
+ }
+
+ // Pop the stack
+ $env->shiftFrame();
+
+ if ( $mediaBlockCount ) {
+ $len = count( $env->mediaBlocks );
+ for ( $i = $mediaBlockCount; $i < $len; $i++ ) {
+ $env->mediaBlocks[$i]->bubbleSelectors( $ruleset->selectors );
+ }
+ }
+
+ return $ruleset;
+ }
+
+ /**
+ * Compile Less_Tree_Mixin_Call objects
+ *
+ * @param Less_Tree_Ruleset $ruleset
+ * @param int $rsRuleCnt
+ */
+ private function EvalMixinCalls( $ruleset, $env, &$rsRuleCnt ) {
+ for ( $i = 0; $i < $rsRuleCnt; $i++ ) {
+ $rule = $ruleset->rules[$i];
+
+ if ( $rule instanceof Less_Tree_Mixin_Call ) {
+ $rule = $rule->compile( $env );
+
+ $temp = [];
+ foreach ( $rule as $r ) {
+ if ( ( $r instanceof Less_Tree_Rule ) && $r->variable ) {
+ // do not pollute the scope if the variable is
+ // already there. consider returning false here
+ // but we need a way to "return" variable from mixins
+ if ( !$ruleset->variable( $r->name ) ) {
+ $temp[] = $r;
+ }
+ } else {
+ $temp[] = $r;
+ }
+ }
+ $temp_count = count( $temp ) - 1;
+ array_splice( $ruleset->rules, $i, 1, $temp );
+ $rsRuleCnt += $temp_count;
+ $i += $temp_count;
+ $ruleset->resetCache();
+
+ } elseif ( $rule instanceof Less_Tree_RulesetCall ) {
+
+ $rule = $rule->compile( $env );
+ $rules = [];
+ foreach ( $rule->rules as $r ) {
+ if ( ( $r instanceof Less_Tree_Rule ) && $r->variable ) {
+ continue;
+ }
+ $rules[] = $r;
+ }
+
+ array_splice( $ruleset->rules, $i, 1, $rules );
+ $temp_count = count( $rules );
+ $rsRuleCnt += $temp_count - 1;
+ $i += $temp_count - 1;
+ $ruleset->resetCache();
+ }
+
+ }
+ }
+
+ /**
+ * Compile the selectors and create a new ruleset object for the compile() method
+ *
+ * @param Less_Environment $env
+ * @return Less_Tree_Ruleset
+ */
+ private function PrepareRuleset( $env ) {
+ // NOTE: Preserve distinction between null and empty array when compiling
+ // $this->selectors to $selectors
+ $thisSelectors = $this->selectors;
+ $selectors = null;
+ $hasOnePassingSelector = false;
+
+ if ( $thisSelectors ) {
+ Less_Tree_DefaultFunc::error( "it is currently only allowed in parametric mixin guards," );
+
+ $selectors = [];
+ foreach ( $thisSelectors as $s ) {
+ $selector = $s->compile( $env );
+ $selectors[] = $selector;
+ if ( $selector->evaldCondition ) {
+ $hasOnePassingSelector = true;
+ }
+ }
+
+ Less_Tree_DefaultFunc::reset();
+ } else {
+ $hasOnePassingSelector = true;
+ }
+
+ if ( $this->rules && $hasOnePassingSelector ) {
+ // Copy the array (no need for slice in PHP)
+ $rules = $this->rules;
+ } else {
+ $rules = [];
+ }
+
+ $ruleset = new Less_Tree_Ruleset( $selectors, $rules, $this->strictImports );
+
+ $ruleset->originalRuleset = $this->ruleset_id;
+ $ruleset->root = $this->root;
+ $ruleset->firstRoot = $this->firstRoot;
+ $ruleset->allowImports = $this->allowImports;
+
+ // push the current ruleset to the frames stack
+ $env->unshiftFrame( $ruleset );
+
+ // Evaluate imports
+ if ( $ruleset->root || $ruleset->allowImports || !$ruleset->strictImports ) {
+ $ruleset->evalImports( $env );
+ }
+
+ return $ruleset;
+ }
+
+ function evalImports( $env ) {
+ $rules_len = count( $this->rules );
+ for ( $i = 0; $i < $rules_len; $i++ ) {
+ $rule = $this->rules[$i];
+
+ if ( $rule instanceof Less_Tree_Import ) {
+ $rules = $rule->compile( $env );
+ if ( is_array( $rules ) ) {
+ array_splice( $this->rules, $i, 1, $rules );
+ $temp_count = count( $rules ) - 1;
+ $i += $temp_count;
+ $rules_len += $temp_count;
+ } else {
+ array_splice( $this->rules, $i, 1, [ $rules ] );
+ }
+
+ $this->resetCache();
+ }
+ }
+ }
+
+ 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 ) {
+ $important_rules[] = $rule->makeImportant();
+ } else {
+ $important_rules[] = $rule;
+ }
+ }
+
+ return new Less_Tree_Ruleset( $this->selectors, $important_rules, $this->strictImports );
+ }
+
+ public function matchArgs( $args, $env = null ) {
+ return !$args;
+ }
+
+ // lets you call a css selector with a guard
+ public function matchCondition( $args, $env ) {
+ $lastSelector = end( $this->selectors );
+
+ if ( !$lastSelector->evaldCondition ) {
+ return false;
+ }
+ if ( $lastSelector->condition && !$lastSelector->condition->compile( $env->copyEvalEnv( $env->frames ) ) ) {
+ return false;
+ }
+ return true;
+ }
+
+ function resetCache() {
+ $this->_rulesets = null;
+ $this->_variables = null;
+ $this->lookups = [];
+ }
+
+ public function variables() {
+ $this->_variables = [];
+ foreach ( $this->rules as $r ) {
+ if ( $r instanceof Less_Tree_Rule && $r->variable === true ) {
+ $this->_variables[$r->name] = $r;
+ }
+ }
+ }
+
+ /**
+ * @param string $name
+ * @return Less_Tree_Rule|null
+ */
+ public function variable( $name ) {
+ if ( $this->_variables === null ) {
+ $this->variables();
+ }
+ return $this->_variables[$name] ?? null;
+ }
+
+ public function find( $selector, $self = null ) {
+ $key = implode( ' ', $selector->_oelements );
+
+ if ( !isset( $this->lookups[$key] ) ) {
+
+ if ( !$self ) {
+ $self = $this->ruleset_id;
+ }
+
+ $this->lookups[$key] = [];
+
+ $first_oelement = $selector->_oelements[0];
+
+ foreach ( $this->rules as $rule ) {
+ if ( $rule instanceof Less_Tree_Ruleset && $rule->ruleset_id != $self ) {
+
+ if ( isset( $rule->first_oelements[$first_oelement] ) ) {
+
+ foreach ( $rule->selectors as $ruleSelector ) {
+ $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 ) );
+ } else {
+ $this->lookups[$key][] = $rule;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return $this->lookups[$key];
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ if ( !$this->root ) {
+ Less_Environment::$tabLevel++;
+ }
+
+ $tabRuleStr = $tabSetStr = '';
+ if ( !Less_Parser::$options['compress'] ) {
+ if ( Less_Environment::$tabLevel ) {
+ $tabRuleStr = "\n" . str_repeat( Less_Parser::$options['indentation'], Less_Environment::$tabLevel );
+ $tabSetStr = "\n" . str_repeat( Less_Parser::$options['indentation'], Less_Environment::$tabLevel - 1 );
+ } else {
+ $tabSetStr = $tabRuleStr = "\n";
+ }
+ }
+
+ $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;
+ } else {
+ $ruleNodes[] = $rule;
+ }
+ }
+
+ // 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;
+ }
+
+ if ( $i + 1 < $paths_len ) {
+ $output->add( ',' . $tabSetStr );
+ }
+ }
+
+ $output->add( ( Less_Parser::$options['compress'] ? '{' : " {" ) . $tabRuleStr );
+ }
+
+ // Compile rules and rulesets
+ $ruleNodes_len = count( $ruleNodes );
+ $rulesetNodes_len = count( $rulesetNodes );
+ for ( $i = 0; $i < $ruleNodes_len; $i++ ) {
+ $rule = $ruleNodes[$i];
+
+ // @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 ) ) {
+ Less_Environment::$lastRule = true;
+ }
+
+ $rule->genCSS( $output );
+
+ if ( !Less_Environment::$lastRule ) {
+ $output->add( $tabRuleStr );
+ } else {
+ Less_Environment::$lastRule = false;
+ }
+ }
+
+ if ( !$this->root ) {
+ $output->add( $tabSetStr . '}' );
+ 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() {
+ if ( !$this->selectors ) {
+ return;
+ }
+ foreach ( $this->selectors as $selector ) {
+ $selector->markReferenced();
+ }
+ }
+
+ /**
+ * @param Less_Tree_Selector[][] $context
+ * @param Less_Tree_Selector[]|null $selectors
+ * @return Less_Tree_Selector[][]
+ */
+ public function joinSelectors( $context, $selectors ) {
+ $paths = [];
+ if ( $selectors !== null ) {
+ foreach ( $selectors as $selector ) {
+ $this->joinSelector( $paths, $context, $selector );
+ }
+ }
+ return $paths;
+ }
+
+ public function joinSelector( array &$paths, array $context, Less_Tree_Selector $selector ) {
+ $newPaths = [];
+ $hadParentSelector = $this->replaceParentSelector( $newPaths, $context, $selector );
+
+ if ( !$hadParentSelector ) {
+ if ( $context ) {
+ $newPaths = [];
+ foreach ( $context as $path ) {
+ $newPaths[] = array_merge( $path, [ $selector ] );
+ }
+ } else {
+ $newPaths = [ [ $selector ] ];
+ }
+ }
+
+ foreach ( $newPaths as $newPath ) {
+ $paths[] = $newPath;
+ }
+ }
+
+ /**
+ * Replace all parent selectors inside $inSelector with $context.
+ *
+ * @param array &$paths Resulting selectors are appended to $paths.
+ * @param mixed $context
+ * @param Less_Tree_Selector $inSelector Inner selector from Less_Tree_Paren
+ * @return bool True if $inSelector contained at least one parent selector
+ */
+ private function replaceParentSelector( array &$paths, $context, Less_Tree_Selector $inSelector ) {
+ $hadParentSelector = false;
+
+ // The paths are [[Selector]]
+ // The first list is a list of comma separated selectors
+ // The inner list is a list of inheritance separated selectors
+ // e.g.
+ // .a, .b {
+ // .c {
+ // }
+ // }
+ // == [[.a] [.c]] [[.b] [.c]]
+ //
+
+ // the elements from the current selector so far
+ $currentElements = [];
+ // the current list of new selectors to add to the path.
+ // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
+ // by the parents
+ $newSelectors = [
+ []
+ ];
+
+ foreach ( $inSelector->elements as $el ) {
+ // non-parent reference elements just get added
+ if ( $el->value !== '&' ) {
+ $nestedSelector = $this->findNestedSelector( $el );
+ if ( $nestedSelector !== null ) {
+ $this->mergeElementsOnToSelectors( $currentElements, $newSelectors );
+
+ $nestedPaths = [];
+ $replacedNewSelectors = [];
+ $replaced = $this->replaceParentSelector( $nestedPaths, $context, $nestedSelector );
+ $hadParentSelector = $hadParentSelector || $replaced;
+ // $nestedPaths is populated by replaceParentSelector()
+ // $nestedPaths should have exactly one TODO, replaceParentSelector does not multiply selectors
+ foreach ( $nestedPaths as $nestedPath ) {
+ $replacementSelector = $this->createSelector( $nestedPath, $el );
+
+ // join selector path from $newSelectors with every selector path in $addPaths array.
+ // $el contains the element that is being replaced by $addPaths
+ //
+ // @see less-2.5.3.js#Ruleset-addAllReplacementsIntoPath
+ $addPaths = [ $replacementSelector ];
+ foreach ( $newSelectors as $newSelector ) {
+ $replacedNewSelectors[] = $this->addReplacementIntoPath( $newSelector, $addPaths, $el, $inSelector );
+ }
+ }
+ $newSelectors = $replacedNewSelectors;
+ $currentElements = [];
+ } else {
+ $currentElements[] = $el;
+ }
+ } else {
+ $hadParentSelector = true;
+
+ // the new list of selectors to add
+ $selectorsMultiplied = [];
+
+ // merge the current list of non parent selector elements
+ // on to the current list of selectors to add
+ $this->mergeElementsOnToSelectors( $currentElements, $newSelectors );
+
+ foreach ( $newSelectors as $sel ) {
+ // if we don't have any parent paths, the & might be in a mixin so that it can be used
+ // whether there are parents or not
+ if ( !$context ) {
+ // the combinator used on el should now be applied to the next element instead so that
+ // it is not lost
+ if ( $sel ) {
+ $sel[0]->elements[] = new Less_Tree_Element( $el->combinator, '', $el->index, $el->currentFileInfo );
+ }
+ $selectorsMultiplied[] = $sel;
+ } else {
+ // and the parent selectors
+ foreach ( $context as $parentSel ) {
+ // We need to put the current selectors
+ // then join the last selector's elements on to the parents selectors
+ $newSelectorPath = $this->addReplacementIntoPath( $sel, $parentSel, $el, $inSelector );
+ // add that to our new set of selectors
+ $selectorsMultiplied[] = $newSelectorPath;
+ }
+ }
+ }
+
+ // our new selectors has been multiplied, so reset the state
+ $newSelectors = $selectorsMultiplied;
+ $currentElements = [];
+ }
+ }
+
+ // if we have any elements left over (e.g. .a& .b == .b)
+ // add them on to all the current selectors
+ $this->mergeElementsOnToSelectors( $currentElements, $newSelectors );
+
+ foreach ( $newSelectors as &$sel ) {
+ $length = count( $sel );
+ if ( $length ) {
+ $paths[] = $sel;
+ $lastSelector = $sel[$length - 1];
+ $sel[$length - 1] = $lastSelector->createDerived( $lastSelector->elements, $inSelector->extendList );
+ }
+ }
+
+ return $hadParentSelector;
+ }
+
+ /**
+ * @param array $elementsToPak
+ * @param Less_Tree_Element $originalElement
+ * @return Less_Tree_Selector
+ */
+ private function createSelector( array $elementsToPak, $originalElement ) {
+ if ( !$elementsToPak ) {
+ // This is an invalid call. Kept to match less.js. Appears unreachable.
+ // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal
+ $containedElement = new Less_Tree_Paren( null );
+ } else {
+ $insideParent = [];
+ foreach ( $elementsToPak as $elToPak ) {
+ $insideParent[] = new Less_Tree_Element( null, $elToPak, $originalElement->index, $originalElement->currentFileInfo );
+ }
+ $containedElement = new Less_Tree_Paren( new Less_Tree_Selector( $insideParent ) );
+ }
+
+ $element = new Less_Tree_Element( null, $containedElement, $originalElement->index, $originalElement->currentFileInfo );
+ return new Less_Tree_Selector( [ $element ] );
+ }
+
+ /**
+ * @param Less_Tree_Element $element
+ * @return Less_Tree_Selector|null
+ */
+ private function findNestedSelector( $element ) {
+ $maybeParen = $element->value;
+ if ( !( $maybeParen instanceof Less_Tree_Paren ) ) {
+ return null;
+ }
+ $maybeSelector = $maybeParen->value;
+ if ( !( $maybeSelector instanceof Less_Tree_Selector ) ) {
+ return null;
+ }
+ return $maybeSelector;
+ }
+
+ /**
+ * joins selector path from $beginningPath with selector path in $addPath.
+ *
+ * $replacedElement contains the element that is being replaced by $addPath
+ *
+ * @param Less_Tree_Selector[] $beginningPath
+ * @param Less_Tree_Selector[] $addPath
+ * @param Less_Tree_Element $replacedElement
+ * @param Less_Tree_Selector $originalSelector
+ * @return Less_Tree_Selector[] Concatenated path
+ * @see less-2.5.3.js#Ruleset-addReplacementIntoPath
+ */
+ private function addReplacementIntoPath( array $beginningPath, array $addPath, $replacedElement, $originalSelector ) {
+ // our new selector path
+ $newSelectorPath = [];
+
+ // construct the joined selector - if `&` is the first thing this will be empty,
+ // if not newJoinedSelector will be the last set of elements in the selector
+ if ( $beginningPath ) {
+ // NOTE: less.js uses Array slice() to copy. In PHP, arrays are naturally copied by value.
+ $newSelectorPath = $beginningPath;
+ $lastSelector = array_pop( $newSelectorPath );
+ $newJoinedSelector = $originalSelector->createDerived( $lastSelector->elements );
+ } else {
+ $newJoinedSelector = $originalSelector->createDerived( [] );
+ }
+
+ if ( $addPath ) {
+ // if the & does not have a combinator that is "" or " " then
+ // and there is a combinator on the parent, then grab that.
+ // this also allows `+ a { & .b { .a & { ...`
+ $combinator = $replacedElement->combinator;
+ $parentEl = $addPath[0]->elements[0];
+ if ( $replacedElement->combinatorIsEmptyOrWhitespace && !$parentEl->combinatorIsEmptyOrWhitespace ) {
+ $combinator = $parentEl->combinator;
+ }
+ // join the elements so far with the first part of the parent
+ $newJoinedSelector->elements[] = new Less_Tree_Element( $combinator, $parentEl->value, $replacedElement->index, $replacedElement->currentFileInfo );
+ $newJoinedSelector->elements = array_merge(
+ $newJoinedSelector->elements,
+ array_slice( $addPath[0]->elements, 1 )
+ );
+ }
+
+ // now add the joined selector - but only if it is not empty
+ if ( $newJoinedSelector->elements ) {
+ $newSelectorPath[] = $newJoinedSelector;
+ }
+
+ // put together the parent selectors after the join (e.g. the rest of the parent)
+ if ( count( $addPath ) > 1 ) {
+ $newSelectorPath = array_merge( $newSelectorPath, array_slice( $addPath, 1 ) );
+ }
+ return $newSelectorPath;
+ }
+
+ function mergeElementsOnToSelectors( $elements, &$selectors ) {
+ if ( !$elements ) {
+ return;
+ }
+ if ( !$selectors ) {
+ $selectors[] = [ new Less_Tree_Selector( $elements ) ];
+ return;
+ }
+
+ foreach ( $selectors as &$sel ) {
+ // if the previous thing in sel is a parent this needs to join on to it
+ if ( $sel ) {
+ $last = count( $sel ) - 1;
+ $sel[$last] = $sel[$last]->createDerived( array_merge( $sel[$last]->elements, $elements ) );
+ } else {
+ $sel[] = new Less_Tree_Selector( $elements );
+ }
+ }
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/RulesetCall.php b/vendor/wikimedia/less.php/lib/Less/Tree/RulesetCall.php
new file mode 100644
index 0000000..9c162b8
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/RulesetCall.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_RulesetCall extends Less_Tree {
+
+ public $variable;
+ public $type = "RulesetCall";
+
+ /**
+ * @param string $variable
+ */
+ public function __construct( $variable ) {
+ $this->variable = $variable;
+ }
+
+ public function accept( $visitor ) {
+ }
+
+ public function compile( $env ) {
+ $variable = new Less_Tree_Variable( $this->variable );
+ $detachedRuleset = $variable->compile( $env );
+ '@phan-var Less_Tree_DetachedRuleset $detachedRuleset';
+ return $detachedRuleset->callEval( $env );
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Selector.php b/vendor/wikimedia/less.php/lib/Less/Tree/Selector.php
new file mode 100644
index 0000000..71182da
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Selector.php
@@ -0,0 +1,169 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Selector extends Less_Tree {
+
+ public $elements;
+ public $condition;
+ public $extendList = [];
+ public $_css;
+ public $index;
+ public $evaldCondition = false;
+ public $type = 'Selector';
+ public $currentFileInfo = [];
+ public $isReferenced;
+ public $mediaEmpty;
+
+ public $elements_len = 0;
+
+ public $_oelements;
+ public $_oelements_assoc;
+ public $_oelements_len;
+ public $cacheable = true;
+
+ /**
+ * @param bool $isReferenced
+ */
+ public function __construct( $elements, $extendList = [], $condition = null, $index = null, $currentFileInfo = null, $isReferenced = null ) {
+ $this->elements = $elements;
+ $this->elements_len = count( $elements );
+ $this->extendList = $extendList;
+ $this->condition = $condition;
+ if ( $currentFileInfo ) {
+ $this->currentFileInfo = $currentFileInfo;
+ }
+ $this->isReferenced = $isReferenced;
+ if ( !$condition ) {
+ $this->evaldCondition = true;
+ }
+
+ $this->CacheElements();
+ }
+
+ public function accept( $visitor ) {
+ $this->elements = $visitor->visitArray( $this->elements );
+ $this->extendList = $visitor->visitArray( $this->extendList );
+ if ( $this->condition ) {
+ $this->condition = $visitor->visitObj( $this->condition );
+ }
+
+ if ( $visitor instanceof Less_Visitor_extendFinder ) {
+ $this->CacheElements();
+ }
+ }
+
+ public function createDerived( $elements, $extendList = null, $evaldCondition = null ) {
+ $newSelector = new Less_Tree_Selector(
+ $elements,
+ ( $extendList ?: $this->extendList ),
+ null,
+ $this->index,
+ $this->currentFileInfo,
+ $this->isReferenced
+ );
+ $newSelector->evaldCondition = $evaldCondition ?: $this->evaldCondition;
+ $newSelector->mediaEmpty = $this->mediaEmpty;
+ return $newSelector;
+ }
+
+ public function match( $other ) {
+ if ( !$other->_oelements || ( $this->elements_len < $other->_oelements_len ) ) {
+ return 0;
+ }
+
+ for ( $i = 0; $i < $other->_oelements_len; $i++ ) {
+ if ( $this->elements[$i]->value !== $other->_oelements[$i] ) {
+ return 0;
+ }
+ }
+
+ return $other->_oelements_len; // return number of matched elements
+ }
+
+ public function CacheElements() {
+ $this->_oelements = [];
+ $this->_oelements_assoc = [];
+
+ $css = '';
+
+ foreach ( $this->elements as $v ) {
+
+ $css .= $v->combinator;
+ if ( !$v->value_is_object ) {
+ $css .= $v->value;
+ continue;
+ }
+
+ if ( !property_exists( $v->value, 'value' ) || !is_string( $v->value->value ) ) {
+ $this->cacheable = false;
+ return;
+ }
+ $css .= $v->value->value;
+ }
+
+ $this->_oelements_len = preg_match_all( '/[,&#\.\w-](?:[\w-]|(?:\\\\.))*/', $css, $matches );
+ if ( $this->_oelements_len ) {
+ $this->_oelements = $matches[0];
+
+ if ( $this->_oelements[0] === '&' ) {
+ array_shift( $this->_oelements );
+ $this->_oelements_len--;
+ }
+
+ $this->_oelements_assoc = array_fill_keys( $this->_oelements, true );
+ }
+ }
+
+ public function isJustParentSelector() {
+ return !$this->mediaEmpty &&
+ count( $this->elements ) === 1 &&
+ $this->elements[0]->value === '&' &&
+ ( $this->elements[0]->combinator === ' ' || $this->elements[0]->combinator === '' );
+ }
+
+ public function compile( $env ) {
+ $elements = [];
+ foreach ( $this->elements as $el ) {
+ $elements[] = $el->compile( $env );
+ }
+
+ $extendList = [];
+ foreach ( $this->extendList as $el ) {
+ $extendList[] = $el->compile( $el );
+ }
+
+ $evaldCondition = false;
+ if ( $this->condition ) {
+ $evaldCondition = $this->condition->compile( $env );
+ }
+
+ return $this->createDerived( $elements, $extendList, $evaldCondition );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output, $firstSelector = true ) {
+ if ( !$firstSelector && $this->elements[0]->combinator === "" ) {
+ $output->add( ' ', $this->currentFileInfo, $this->index );
+ }
+
+ foreach ( $this->elements as $element ) {
+ $element->genCSS( $output );
+ }
+ }
+
+ public function markReferenced() {
+ $this->isReferenced = true;
+ }
+
+ public function getIsReferenced() {
+ return !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] || $this->isReferenced;
+ }
+
+ public function getIsOutput() {
+ return $this->evaldCondition;
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/UnicodeDescriptor.php b/vendor/wikimedia/less.php/lib/Less/Tree/UnicodeDescriptor.php
new file mode 100644
index 0000000..304d191
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/UnicodeDescriptor.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_UnicodeDescriptor extends Less_Tree {
+
+ public $value;
+ public $type = 'UnicodeDescriptor';
+
+ public function __construct( $value ) {
+ $this->value = $value;
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( $this->value );
+ }
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Unit.php b/vendor/wikimedia/less.php/lib/Less/Tree/Unit.php
new file mode 100644
index 0000000..2fd8927
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Unit.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Unit extends Less_Tree {
+
+ var $numerator = [];
+ var $denominator = [];
+ public $backupUnit;
+ public $type = 'Unit';
+
+ public function __construct( $numerator = [], $denominator = [], $backupUnit = null ) {
+ $this->numerator = $numerator;
+ $this->denominator = $denominator;
+ $this->backupUnit = $backupUnit;
+ }
+
+ public function __clone() {
+ }
+
+ /**
+ * @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 ) {
+ $output->add( $this->backupUnit );
+ return;
+ }
+ }
+
+ public function toString() {
+ $returnStr = implode( '*', $this->numerator );
+ foreach ( $this->denominator as $d ) {
+ $returnStr .= '/' . $d;
+ }
+ return $returnStr;
+ }
+
+ public function __toString() {
+ return $this->toString();
+ }
+
+ /**
+ * @param Less_Tree_Unit $other
+ */
+ public function compare( $other ) {
+ return $this->is( $other->toString() ) ? 0 : -1;
+ }
+
+ public function is( $unitString ) {
+ return $this->toString() === $unitString;
+ }
+
+ public function isLength() {
+ $css = $this->toCSS();
+ return (bool)preg_match( '/px|em|%|in|cm|mm|pc|pt|ex/', $css );
+ }
+
+ public function isAngle() {
+ return isset( Less_Tree_UnitConversions::$angle[$this->toCSS()] );
+ }
+
+ public function isEmpty() {
+ return !$this->numerator && !$this->denominator;
+ }
+
+ public function isSingular() {
+ return count( $this->numerator ) <= 1 && !$this->denominator;
+ }
+
+ public function usedUnits() {
+ $result = [];
+
+ foreach ( Less_Tree_UnitConversions::$groups as $groupName ) {
+ $group = Less_Tree_UnitConversions::${$groupName};
+
+ foreach ( $this->numerator as $atomicUnit ) {
+ if ( isset( $group[$atomicUnit] ) && !isset( $result[$groupName] ) ) {
+ $result[$groupName] = $atomicUnit;
+ }
+ }
+
+ foreach ( $this->denominator as $atomicUnit ) {
+ if ( isset( $group[$atomicUnit] ) && !isset( $result[$groupName] ) ) {
+ $result[$groupName] = $atomicUnit;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ 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;
+ }
+
+ $this->numerator = [];
+ $this->denominator = [];
+
+ foreach ( $counter as $atomicUnit => $count ) {
+ if ( $count > 0 ) {
+ for ( $i = 0; $i < $count; $i++ ) {
+ $this->numerator[] = $atomicUnit;
+ }
+ } elseif ( $count < 0 ) {
+ for ( $i = 0; $i < -$count; $i++ ) {
+ $this->denominator[] = $atomicUnit;
+ }
+ }
+ }
+
+ if ( !$this->numerator && !$this->denominator && $backup ) {
+ $this->backupUnit = $backup;
+ }
+
+ sort( $this->numerator );
+ sort( $this->denominator );
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/UnitConversions.php b/vendor/wikimedia/less.php/lib/Less/Tree/UnitConversions.php
new file mode 100644
index 0000000..31efe1c
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/UnitConversions.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_UnitConversions {
+
+ public static $groups = [ 'length','duration','angle' ];
+
+ public static $length = [
+ 'm' => 1,
+ '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
+ ];
+
+ public static $duration = [
+ 's' => 1,
+ 'ms' => 0.001
+ ];
+
+ public static $angle = [
+ 'rad' => 0.1591549430919, // 1/(2*M_PI),
+ 'deg' => 0.002777778, // 1/360,
+ 'grad' => 0.0025, // 1/400,
+ 'turn' => 1
+ ];
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Url.php b/vendor/wikimedia/less.php/lib/Less/Tree/Url.php
new file mode 100644
index 0000000..6ae3518
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Url.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Url extends Less_Tree {
+
+ public $attrs;
+ public $value;
+ public $currentFileInfo;
+ public $isEvald;
+ public $type = 'Url';
+
+ /**
+ * @param Less_Tree_Variable|Less_Tree_Quoted|Less_Tree_Anonymous $value
+ * @param array|null $currentFileInfo
+ * @param bool|null $isEvald
+ */
+ public function __construct( $value, $currentFileInfo = null, $isEvald = null ) {
+ $this->value = $value;
+ $this->currentFileInfo = $currentFileInfo;
+ $this->isEvald = $isEvald;
+ }
+
+ public function accept( $visitor ) {
+ $this->value = $visitor->visitObj( $this->value );
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ public function genCSS( $output ) {
+ $output->add( 'url(' );
+ $this->value->genCSS( $output );
+ $output->add( ')' );
+ }
+
+ /**
+ * @param Less_Environment $ctx
+ */
+ public function compile( $ctx ) {
+ $val = $this->value->compile( $ctx );
+
+ if ( !$this->isEvald ) {
+ // Add the base path if the URL is relative
+ if ( Less_Parser::$options['relativeUrls']
+ && $this->currentFileInfo
+ && is_string( $val->value )
+ && Less_Environment::isPathRelative( $val->value )
+ ) {
+ $rootpath = $this->currentFileInfo['uri_root'];
+ if ( !$val->quote ) {
+ $rootpath = preg_replace( '/[\(\)\'"\s]/', '\\$1', $rootpath );
+ }
+ $val->value = $rootpath . $val->value;
+ }
+
+ $val->value = Less_Environment::normalizePath( $val->value );
+ }
+
+ // Add cache buster if enabled
+ if ( Less_Parser::$options['urlArgs'] ) {
+ if ( !preg_match( '/^\s*data:/', $val->value ) ) {
+ $delimiter = strpos( $val->value, '?' ) === false ? '?' : '&';
+ $urlArgs = $delimiter . Less_Parser::$options['urlArgs'];
+ $hash_pos = strpos( $val->value, '#' );
+ if ( $hash_pos !== false ) {
+ $val->value = substr_replace( $val->value, $urlArgs, $hash_pos, 0 );
+ } else {
+ $val->value .= $urlArgs;
+ }
+ }
+ }
+
+ return new Less_Tree_URL( $val, $this->currentFileInfo, true );
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Value.php b/vendor/wikimedia/less.php/lib/Less/Tree/Value.php
new file mode 100644
index 0000000..bf45caf
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Value.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Value extends Less_Tree {
+
+ public $type = 'Value';
+ public $value;
+
+ /**
+ * @param array<Less_Tree> $value
+ */
+ public function __construct( $value ) {
+ $this->value = $value;
+ }
+
+ public function accept( $visitor ) {
+ $this->value = $visitor->visitArray( $this->value );
+ }
+
+ public function compile( $env ) {
+ $ret = [];
+ $i = 0;
+ foreach ( $this->value as $i => $v ) {
+ $ret[] = $v->compile( $env );
+ }
+ if ( $i > 0 ) {
+ return new Less_Tree_Value( $ret );
+ }
+ return $ret[0];
+ }
+
+ /**
+ * @see Less_Tree::genCSS
+ */
+ 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[','] );
+ }
+ }
+ }
+
+}
diff --git a/vendor/wikimedia/less.php/lib/Less/Tree/Variable.php b/vendor/wikimedia/less.php/lib/Less/Tree/Variable.php
new file mode 100644
index 0000000..dcb1823
--- /dev/null
+++ b/vendor/wikimedia/less.php/lib/Less/Tree/Variable.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @private
+ */
+class Less_Tree_Variable extends Less_Tree {
+
+ public $name;
+ public $index;
+ public $currentFileInfo;
+ public $evaluating = false;
+ public $type = 'Variable';
+
+ /**
+ * @param string $name
+ */
+ public function __construct( $name, $index = null, $currentFileInfo = null ) {
+ $this->name = $name;
+ $this->index = $index;
+ $this->currentFileInfo = $currentFileInfo;
+ }
+
+ /**
+ * @param Less_Environment $env
+ * @return Less_Tree
+ * @see less-2.5.3.js#Ruleset.prototype.eval
+ */
+ public function compile( $env ) {
+ if ( $this->name[1] === '@' ) {
+ $v = new Less_Tree_Variable( substr( $this->name, 1 ), $this->index + 1, $this->currentFileInfo );
+ // While some Less_Tree nodes have no 'value', we know these can't ocurr after a variable
+ // assignment (would have been a ParseError).
+ // TODO: Solve better (https://phabricator.wikimedia.org/T327082).
+ // @phan-suppress-next-line PhanUndeclaredProperty
+ $name = '@' . $v->compile( $env )->value;
+ } else {
+ $name = $this->name;
+ }
+
+ if ( $this->evaluating ) {
+ throw new Less_Exception_Compiler( "Recursive variable definition for " . $name, null, $this->index, $this->currentFileInfo );
+ }
+
+ $this->evaluating = true;
+
+ foreach ( $env->frames as $frame ) {
+ if ( $v = $frame->variable( $name ) ) {
+ $r = $v->value->compile( $env );
+ $this->evaluating = false;
+ return $r;
+ }
+ }
+
+ throw new Less_Exception_Compiler( "variable " . $name . " is undefined in file " . $this->currentFileInfo["filename"], null, $this->index, $this->currentFileInfo );
+ }
+
+}