Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.95% covered (success)
90.95%
1307 / 1437
62.73% covered (warning)
62.73%
69 / 110
CRAP
0.00% covered (danger)
0.00%
0 / 1
Less_Parser
90.95% covered (success)
90.95%
1307 / 1437
62.73% covered (warning)
62.73%
69 / 110
927.73
0.00% covered (danger)
0.00%
0 / 1
 __construct
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
3.21
 Reset
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 SetOptions
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 SetOption
96.30% covered (success)
96.30%
26 / 27
0.00% covered (danger)
0.00%
0 / 1
13
 registerFunction
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 unregisterFunction
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getCss
93.10% covered (success)
93.10%
27 / 29
0.00% covered (danger)
0.00%
0 / 1
6.01
 findValueOf
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
30
 getVariables
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 findVarByName
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
30
 getVariableValue
93.10% covered (success)
93.10%
27 / 29
0.00% covered (danger)
0.00%
0 / 1
26.22
 rgb2html
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 PreVisitors
25.00% covered (danger)
25.00%
1 / 4
0.00% covered (danger)
0.00%
0 / 1
10.75
 PostVisitors
57.14% covered (warning)
57.14%
8 / 14
0.00% covered (danger)
0.00%
0 / 1
15.38
 parse
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
3.00
 parseFile
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
8.01
 ModifyVars
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 SetFileInfo
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
5
 SetCacheDir
n/a
0 / 0
n/a
0 / 0
5
 SetImportDirs
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
5.03
 _parse
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 GetRules
74.29% covered (warning)
74.29%
26 / 35
0.00% covered (danger)
0.00%
0 / 1
15.87
 setInput
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 unsetInput
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 cacheFile
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 getParsedFiles
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 save
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 restore
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 forget
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isWhitespace
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 matchChar
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 matchReg
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 matchStr
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 parseQuoted
90.91% covered (success)
90.91%
20 / 22
0.00% covered (danger)
0.00%
0 / 1
10.08
 parseUntil
90.36% covered (success)
90.36%
75 / 83
0.00% covered (danger)
0.00%
0 / 1
23.47
 peekReg
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 peekChar
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 skipWhitespace
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
11
 expect
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
4.07
 expectChar
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
3.58
 parserInputStart
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 parseNode
60.87% covered (warning)
60.87%
14 / 23
0.00% covered (danger)
0.00%
0 / 1
8.16
 parsePrimary
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
9
 parseComment
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 parseEntitiesMixinLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parseEntitiesQuoted
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
 parseEntitiesKeyword
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 parseEntitiesCall
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
6
 parseEntitiesArguments
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 parseEntitiesLiteral
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parseEntitiesAssignment
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
4.03
 parseEntitiesUrl
95.00% covered (success)
95.00%
19 / 20
0.00% covered (danger)
0.00%
0 / 1
7
 parseEntitiesVariable
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
7
 parseEntitiesVariableCurly
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 parseEntitiesProperty
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 parseEntitiesPropertyCurly
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 parseEntitiesColor
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 parseEntitiesDimension
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
7
 parseUnicodeDescriptor
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 parseEntitiesJavascript
66.67% covered (warning)
66.67%
12 / 18
0.00% covered (danger)
0.00%
0 / 1
7.33
 parseVariable
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 parseVariableCall
90.91% covered (success)
90.91%
20 / 22
0.00% covered (danger)
0.00%
0 / 1
11.09
 parseExtend
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
8
 parseMixinCall
96.97% covered (success)
96.97%
32 / 33
0.00% covered (danger)
0.00%
0 / 1
17
 parseMixinCallElements
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 parseMixinArgs
87.65% covered (warning)
87.65%
71 / 81
0.00% covered (danger)
0.00%
0 / 1
35.05
 parseMixinRuleLookups
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
 parseLookupValue
75.00% covered (warning)
75.00%
9 / 12
0.00% covered (danger)
0.00%
0 / 1
5.39
 parseMixinDefinition
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
9
 parseEntity
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 parseEnd
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 parseAlpha
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 parseElement
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
6
 parseCombinator
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
13.03
 parseLessSelector
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parseSelector
95.83% covered (success)
95.83%
23 / 24
0.00% covered (danger)
0.00%
0 / 1
17
 parseAttribute
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 parseBlock
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 parseBlockRuleset
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 parseDetachedRuleset
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 parseRuleset
90.48% covered (success)
90.48%
19 / 21
0.00% covered (danger)
0.00%
0 / 1
9.07
 parseNameValue
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 parseDeclaration
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
23
 parseAnonymousValue
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 parsePermissiveValue
92.59% covered (success)
92.59%
50 / 54
0.00% covered (danger)
0.00%
0 / 1
15.09
 parseImport
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 parseImportOptions
85.00% covered (warning)
85.00%
17 / 20
0.00% covered (danger)
0.00%
0 / 1
6.12
 parseImportOption
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 parseMediaFeature
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
8.01
 parseMediaFeatures
76.92% covered (warning)
76.92%
10 / 13
0.00% covered (danger)
0.00%
0 / 1
6.44
 parseMedia
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
3.10
 parseAtRule
95.59% covered (success)
95.59%
65 / 68
0.00% covered (danger)
0.00%
0 / 1
29
 parseValue
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 parseImportant
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 parseSub
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 parseMultiplication
95.00% covered (success)
95.00%
19 / 20
0.00% covered (danger)
0.00%
0 / 1
6
 parseAddition
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
7.01
 parseConditions
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
6.03
 parseCondition
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
6
 parseOperand
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
6
 parseExpression
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
7.01
 parseProperty
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 parseRuleProperty
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
10
 rulePropertyMatch
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 serializeVars
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 is_method
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 round
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 Error
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 WinPath
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 AbsPath
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
5.12
 CacheEnabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 * Parse and compile Less files into CSS
5 */
6class Less_Parser {
7
8    /**
9     * Default parser options
10     * @var array<string,mixed>
11     */
12    public static $default_options = [
13        'compress'                => false, // option - whether to compress
14        'strictUnits'            => false, // whether units need to evaluate correctly
15        /* How to process math
16         *   always           - eagerly try to solve all operations
17         *   parens-division  - require parens for division "/"
18         *   parens | strict  - require parens for all operations
19         */
20        // NOTE: We use the default of Less.js 4.0 (parens-division)
21        //       instead of Less.js 3.13 (always).
22        'math'                    => 'parens-division',
23        'relativeUrls'            => true, // option - whether to adjust URL's to be relative
24        'urlArgs'                => '', // whether to add args into url tokens
25        'numPrecision'            => 8,
26
27        'import_dirs'            => [],
28
29        'cache_dir'                => null,
30        'cache_method'            => 'serialize', // false, 'serialize', 'callback';
31        'cache_callback_get'    => null,
32        'cache_callback_set'    => null,
33
34        'sourceMap'                => false, // whether to output a source map
35        'sourceMapBasepath'        => null,
36        'sourceMapWriteTo'        => null,
37        'sourceMapURL'            => null,
38
39        'indentation'             => '  ',
40
41        'plugins'                => [],
42        'functions'             => [],
43
44    ];
45
46    /** @var array{compress:bool,strictUnits:bool,relativeUrls:bool,urlArgs:string,numPrecision:int,import_dirs:array,indentation:string} */
47    public static $options = [];
48
49    private $input;                    // Less input string
50    private $input_len;                // input string length
51    private $pos;                    // current index in `input`
52    private $saveStack = [];    // holds state for backtracking
53    private $furthest;
54    private $mb_internal_encoding = ''; // for remember exists value of mbstring.internal_encoding
55
56    private $autoCommentAbsorb = true;
57    /**
58     * @var array<array{index:int,text:string,isLineComment:bool}>
59     */
60    private $commentStore = [];
61
62    /**
63     * @var Less_Environment
64     */
65    private $env;
66
67    protected $rules = [];
68
69    /**
70     * Evaluated ruleset created by `getCss()`. Stored for potential use in `getVariables()`
71     * @var Less_Tree[]|null
72     */
73    private $cachedEvaldRules;
74
75    public static $has_extends = false;
76
77    public static $next_id = 0;
78
79    /**
80     * Filename to contents of all parsed the files
81     *
82     * @var array
83     */
84    public static $contentsMap = [];
85
86    /**
87     * @param Less_Environment|array|null $env
88     */
89    public function __construct( $env = null ) {
90        // Top parser on an import tree must be sure there is one "env"
91        // which will then be passed around by reference.
92        if ( $env instanceof Less_Environment ) {
93            $this->env = $env;
94        } else {
95            $this->Reset( $env );
96        }
97
98        // mbstring.func_overload > 1 bugfix
99        // The encoding value must be set for each source file,
100        // therefore, to conserve resources and improve the speed of this design is taken here
101        if ( ini_get( 'mbstring.func_overload' ) ) {
102            $this->mb_internal_encoding = ini_get( 'mbstring.internal_encoding' );
103            @ini_set( 'mbstring.internal_encoding', 'ascii' );
104        }
105        Less_Tree::$parse = $this;
106    }
107
108    /**
109     * Reset the parser state completely
110     */
111    public function Reset( $options = null ) {
112        $this->rules = [];
113        $this->cachedEvaldRules = null;
114        self::$has_extends = false;
115        self::$contentsMap = [];
116
117        $this->env = new Less_Environment();
118
119        // set new options
120        $this->SetOptions( self::$default_options );
121        if ( is_array( $options ) ) {
122            $this->SetOptions( $options );
123        }
124
125        $this->env->Init();
126    }
127
128    /**
129     * Set one or more compiler options
130     *  options: import_dirs, cache_dir, cache_method
131     */
132    public function SetOptions( $options ) {
133        foreach ( $options as $option => $value ) {
134            $this->SetOption( $option, $value );
135        }
136    }
137
138    /**
139     * Set one compiler option
140     */
141    public function SetOption( $option, $value ) {
142        switch ( $option ) {
143            case 'strictMath':
144                if ( $value ) {
145                    $this->env->math = Less_Environment::MATH_PARENS;
146                } else {
147                    $this->env->math = Less_Environment::MATH_ALWAYS;
148                }
149                break;
150
151            case 'math':
152                $value = strtolower( $value );
153                if ( $value === 'always' ) {
154                    $this->env->math = Less_Environment::MATH_ALWAYS;
155                } elseif ( $value === 'parens-division' ) {
156                    $this->env->math = Less_Environment::MATH_PARENS_DIVISION;
157                } elseif ( $value === 'parens' || $value === 'strict' ) {
158                    $this->env->math = Less_Environment::MATH_PARENS;
159                }
160                return;
161
162            case 'import_dirs':
163                $this->SetImportDirs( $value );
164                return;
165
166            case 'cache_dir':
167                if ( is_string( $value ) ) {
168                    Less_Cache::SetCacheDir( $value );
169                    Less_Cache::CheckCacheDir();
170                }
171                return;