diff --git a/less.php/CHANGES.md b/less.php/CHANGES.md deleted file mode 100755 index 92f82f8..0000000 --- a/less.php/CHANGES.md +++ /dev/null @@ -1,70 +0,0 @@ -# 3.1.0 -- [All Changes](https://github.com/wikimedia/less.php/compare/v3.0.0...v3.1.0) -* PHP 8.0 support: Drop use of curly braces for sub-string eval (James D. Forrester) -* Make `Directive::__construct` $rules arg optional (fix PHP 7.4 warning) (Sam Reed) -* ProcessExtends: Improve performance by using a map for selectors and parents (Andrey Legayev) -* build: Run CI tests on PHP 8.0 too (James D. Forrester) -* code: Fix PSR12.Properties.ConstantVisibility.NotFound (Sam Reed) - -# 3.0.0 -- [All Changes](https://github.com/wikimedia/less.php/compare/v2.0.0...v3.0.0) -- Raise PHP requirement from 7.1 to 7.2.9 (James Forrester) -- build: Upgrade phpunit to ^8.5 and make pass (James Forrester) -- build: Install php-parallel-lint (James Forrester) -- build: Install minus-x and make pass (James Forrester) - -# 2.0.0 -- [All Changes](https://github.com/wikimedia/less.php/compare/1.8.2...v2.0.0) -- Relax PHP requirement down to 7.1, from 7.2.9 (Franz Liedke) -- Reflect recent breaking changes properly with the semantic versioning (James Forrester) - -# 1.8.2 -- [All Changes](https://github.com/wikimedia/less.php/compare/1.8.1...1.8.2) -- Require PHP 7.2.9+, up from 5.3+ (James Forrester) -- Release: Update Version.php with the current release ID (COBadger) -- Fix access array offset on value of type null (Michele Locati) -- Fixed test suite on PHP 7.4 (Sergei Morozov) -- docs: Fix 1.8.1 "All changes" link (Timo Tijhof) - -# 1.8.1 -- [All Changes](https://github.com/wikimedia/less.php/compare/v1.8.0...1.8.1) -- Another PHP 7.3 compatibility tweak - -# 1.8.0 -- [All Changes](https://github.com/Asenar/less.php/compare/v1.7.0.13...v1.8.0) -- Wikimedia fork -- Supports up to PHP 7.3 -- No longer tested against PHP 5, though it's still remains allowed in `composer.json` for HHVM compatibility -- Switched to [semantic versioning](https://semver.org/), hence version numbers now use 3 digits - -# 1.7.0.13 - - [All Changes](https://github.com/Asenar/less.php/compare/v1.7.0.12...v1.7.0.13) - - Fix composer.json (PSR-4 was invalid) - -# 1.7.0.12 - - [All Changes](https://github.com/Asenar/less.php/compare/v1.7.0.11...v1.7.0.12) - - set bin/lessc bit executable - - Add 'gettingVariables' method in Less_Parser - -# 1.7.0.11 - - [All Changes](https://github.com/Asenar/less.php/compare/v1.7.0.10...v1.7.0.11) - - Fix realpath issue (windows) - - Set Less_Tree_Call property back to public ( Fix 258 266 267 issues from oyejorge/less.php) - -# 1.7.0.10 - - - [All Changes](https://github.com/oyejorge/less.php/compare/v1.7.0.9...v1.7.10) - - Add indentation option - - Add 'optional' modifier for @import - - fix $color in Exception messages - - don't use set_time_limit when running cli - - take relative-url into account when building the cache filename - - urlArgs should be string no array() - - add bug-report fixtures [#6dc898f](https://github.com/oyejorge/less.php/commit/6dc898f5d75b447464906bdf19d79c2e19d95e33) - - fix #269, missing on NameValue type [#a8dac63](https://github.com/oyejorge/less.php/commit/a8dac63d93fb941c54fb78b12588abf635747c1b) - -# 1.7.0.9 - - - [All Changes](https://github.com/oyejorge/less.php/compare/v1.7.0.8...v1.7.0.9) - - Remove space at beginning of Version.php - - Revert require() paths in test interface diff --git a/less.php/LICENSE b/less.php/LICENSE deleted file mode 100755 index 82216a5..0000000 --- a/less.php/LICENSE +++ /dev/null @@ -1,178 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - diff --git a/less.php/README.md b/less.php/README.md deleted file mode 100755 index 5d6c0af..0000000 --- a/less.php/README.md +++ /dev/null @@ -1,314 +0,0 @@ -[![Continuous Integration](https://github.com/wikimedia/less.php/workflows/PHP%20Test/badge.svg)](https://github.com/wikimedia/less.php/actions) - -[Less.php](http://lessphp.typesettercms.com) -======== - -This is the Wikimedia fork of a PHP port of the official LESS processor . - -* [About](#about) -* [Installation](#installation) -* [Basic Use](#basic-use) -* [Caching](#caching) -* [Source Maps](#source-maps) -* [Command Line](#command-line) -* [Integration with other projects](#integration-with-other-projects) -* [Transitioning from Leafo/lessphp](#transitioning-from-leafolessphp) -* [Credits](#credits) - - - -About ---- -The code structure of less.php mirrors that of the official processor which helps us ensure compatibility and allows for easy maintenance. - -Please note, there are a few unsupported LESS features: - -- Evaluation of JavaScript expressions within back-ticks (for obvious reasons). -- Definition of custom functions. - - -Installation ---- - -You can install the library with Composer or manually. - -#### Composer - -1. [Install Composer](https://getcomposer.org/download/) -2. Run `composer require wikimedia/less.php` - -#### Manually From Release - -Step 1. [Download a release](https://github.com/wikimedia/less.php/releases) and upload the PHP files to your server. - -Step 2. Include the library: - -```php -require_once '[path to less.php]/lib/Less/Autoloader.php'; -Less_Autoloader::register(); -``` - -Basic Use ---- - -#### Parsing Strings - -```php -$parser = new Less_Parser(); -$parser->parse( '@color: #4D926F; #header { color: @color; } h2 { color: @color; }' ); -$css = $parser->getCss(); -``` - - -#### Parsing LESS Files -The parseFile() function takes two arguments: - -1. The absolute path of the .less file to be parsed -2. The url root to prepend to any relative image or @import urls in the .less file. - -```php -$parser = new Less_Parser(); -$parser->parseFile( '/var/www/mysite/bootstrap.less', 'http://example.com/mysite/' ); -$css = $parser->getCss(); -``` - - -#### Handling Invalid LESS -An exception will be thrown if the compiler encounters invalid LESS. - -```php -try{ - $parser = new Less_Parser(); - $parser->parseFile( '/var/www/mysite/bootstrap.less', 'http://example.com/mysite/' ); - $css = $parser->getCss(); -}catch(Exception $e){ - $error_message = $e->getMessage(); -} -``` - - -#### Parsing Multiple Sources -less.php can parse multiple sources to generate a single CSS file. - -```php -$parser = new Less_Parser(); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$parser->parse( '@color: #4D926F; #header { color: @color; } h2 { color: @color; }' ); -$css = $parser->getCss(); -``` - -#### Getting Info About The Parsed Files -less.php can tell you which .less files were imported and parsed. - -```php -$parser = new Less_Parser(); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$css = $parser->getCss(); -$imported_files = $parser->allParsedFiles(); -``` - - -#### Compressing Output -You can tell less.php to remove comments and whitespace to generate minimized CSS files. - -```php -$options = array( 'compress'=>true ); -$parser = new Less_Parser( $options ); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$css = $parser->getCss(); -``` - -#### Getting Variables -You can use the getVariables() method to get an all variables defined and -their value in a php associative array. Note that LESS has to be previously -compiled. -```php -$parser = new Less_Parser; -$parser->parseFile( '/var/www/mysite/bootstrap.less'); -$css = $parser->getCss(); -$variables = $parser->getVariables(); - -``` - - - -#### Setting Variables -You can use the ModifyVars() method to customize your CSS if you have variables stored in PHP associative arrays. - -```php -$parser = new Less_Parser(); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$parser->ModifyVars( array('font-size-base'=>'16px') ); -$css = $parser->getCss(); -``` - - -#### Import Directories -By default, less.php will look for @imports in the directory of the file passed to parseFile(). -If you're using parse() or if @imports reside in different directories, you can tell less.php where to look. - -```php -$directories = array( '/var/www/mysite/bootstrap/' => '/mysite/bootstrap/' ); -$parser = new Less_Parser(); -$parser->SetImportDirs( $directories ); -$parser->parseFile( '/var/www/mysite/theme.less', '/mysite/' ); -$css = $parser->getCss(); -``` - - -Caching ---- -Compiling LESS code into CSS is a time consuming process, caching your results is highly recommended. - - -#### Caching CSS -Use the Less_Cache class to save and reuse the results of compiled LESS files. -This method will check the modified time and size of each LESS file (including imported files) and regenerate a new CSS file when changes are found. -Note: When changes are found, this method will return a different file name for the new cached content. - -```php -$less_files = array( '/var/www/mysite/bootstrap.less' => '/mysite/' ); -$options = array( 'cache_dir' => '/var/www/writable_folder' ); -$css_file_name = Less_Cache::Get( $less_files, $options ); -$compiled = file_get_contents( '/var/www/writable_folder/'.$css_file_name ); -``` - -#### Caching CSS With Variables -Passing options to Less_Cache::Get() - -```php -$less_files = array( '/var/www/mysite/bootstrap.less' => '/mysite/' ); -$options = array( 'cache_dir' => '/var/www/writable_folder' ); -$variables = array( 'width' => '100px' ); -$css_file_name = Less_Cache::Get( $less_files, $options, $variables ); -$compiled = file_get_contents( '/var/www/writable_folder/'.$css_file_name ); -``` - - -#### Parser Caching -less.php will save serialized parser data for each .less file if a writable folder is passed to the SetCacheDir() method. -Note: This feature only caches intermediate parsing results to improve the performance of repeated CSS generation. -Your application should cache any CSS generated by less.php. - -```php -$options = array('cache_dir'=>'/var/www/writable_folder'); -$parser = new Less_Parser( $options ); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$css = $parser->getCss(); -``` - -You can specify the caching technique used by changing the ```cache_method``` option. Supported methods are: -* ```php```: Creates valid PHP files which can be included without any changes (default method). -* ```var_export```: Like "php", but using PHP's ```var_export()``` function without any optimizations. - It's recommended to use "php" instead. -* ```serialize```: Faster, but pretty memory-intense. -* ```callback```: Use custom callback functions to implement your own caching method. Give the "cache_callback_get" and - "cache_callback_set" options with callables (see PHP's ```call_user_func()``` and ```is_callable()``` functions). less.php - will pass the parser object (class ```Less_Parser```), the path to the parsed .less file ("/some/path/to/file.less") and - an identifier that will change every time the .less file is modified. The ```get``` callback must return the ruleset - (an array with ```Less_Tree``` objects) provided as fourth parameter of the ```set``` callback. If something goes wrong, - return ```NULL``` (cache doesn't exist) or ```FALSE```. - - - -Source Maps ---- -Less.php supports v3 sourcemaps - -#### Inline -The sourcemap will be appended to the generated CSS file. - -```php -$options = array( 'sourceMap' => true ); -$parser = new Less_Parser($options); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$css = $parser->getCss(); -``` - -#### Saving to Map File - -```php -$options = array( - 'sourceMap' => true, - 'sourceMapWriteTo' => '/var/www/mysite/writable_folder/filename.map', - 'sourceMapURL' => '/mysite/writable_folder/filename.map', - ); -$parser = new Less_Parser($options); -$parser->parseFile( '/var/www/mysite/bootstrap.less', '/mysite/' ); -$css = $parser->getCss(); -``` - - -Command line ---- -An additional script has been included to use the compiler from the command line. -In the simplest invocation, you specify an input file and the compiled CSS is written to standard out: - -``` -$ lessc input.less > output.css -``` - -By using the -w flag you can watch a specified input file and have it compile as needed to the output file: - -``` -$ lessc -w input.less output.css -``` - -Errors from watch mode are written to standard out. - -For more help, run `lessc --help` - - -Integration with other projects ---- - -#### Drupal 7 - -This library can be used as drop-in replacement of lessphp to work with [Drupal 7 less module](https://drupal.org/project/less). - -How to install: - -1. [Download the less.php source code](https://github.com/wikimedia/less.php/archive/master.zip) and unzip it so that 'lessc.inc.php' is located at 'sites/all/libraries/lessphp/lessc.inc.php'. -2. Download and install [Drupal 7 less module](https://drupal.org/project/less) as usual. -3. That's it :) - -#### JBST WordPress theme - -JBST has a built-in LESS compiler based on lessphp. Customize your WordPress theme with LESS. - -How to use / install: - -1. [Download the latest release](https://github.com/bassjobsen/jamedo-bootstrap-start-theme) copy the files to your {wordpress/}wp-content/themes folder and activate it. -2. Find the compiler under Appearance > LESS Compiler in your WordPress dashboard -3. Enter your LESS code in the text area and press (re)compile - -Use the built-in compiler to: -- set any [Bootstrap](http://getbootstrap.com/customize/) variable or use Bootstrap's mixins: - -`@navbar-default-color: blue;` - - create a custom button: `.btn-custom { - .button-variant(white; red; blue); -}` -- set any built-in LESS variable: for example `@footer_bg_color: black;` sets the background color of the footer to black -- use built-in mixins: - add a custom font: `.include-custom-font(@family: arial,@font-path, @path: @custom-font-dir, @weight: normal, @style: normal);` - -The compiler can also be downloaded as [plugin](http://wordpress.org/plugins/wp-less-to-css/) - -#### WordPress - -This simple plugin will simply make the library available to other plugins and themes and can be used as a dependency using the [TGM Library](http://tgmpluginactivation.com/) - -How to install: - -1. Install the plugin from your WordPress Dashboard: http://wordpress.org/plugins/lessphp/ -2. That's it :) - - -Transitioning from Leafo/lessphp ---- -Projects looking for an easy transition from leafo/lessphp can use the lessc.inc.php adapter. To use, [Download the less.php source code](https://github.com/wikimedia/less.php/archive/master.zip) and unzip the files into your project so that the new 'lessc.inc.php' replaces the existing 'lessc.inc.php'. - -Note, the 'setPreserveComments' will no longer have any effect on the compiled LESS. - -Credits ---- -less.php was originally ported to PHP by [Matt Agar](https://github.com/agar) and then updated by [Martin Jantošovič](https://github.com/Mordred). This Wikimedia-maintained fork was split off from [Josh Schmidt's version](https://github.com/oyejorge/less.php). diff --git a/less.php/bin/lessc b/less.php/bin/lessc deleted file mode 100755 index fa1fb95..0000000 --- a/less.php/bin/lessc +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env php - false, 'relativeUrls' => false); -$silent = false; -$watch = false; -$rootpath = ''; - -// Check for arguments -array_shift($argv); -if (!count($argv)) { - $argv[] = '-h'; -} - -// parse arguments -foreach ($argv as $key => $arg) { - if (preg_match('/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i', $arg, $matches)) { - $option = $matches[1]; - $value = isset($matches[2]) ? $matches[2] : false; - unset($argv[$key]); - - switch ($option) { - case 'h': - case 'help': - echo << 1) { - $output = array_pop($argv); - $inputs = $argv; -} -else { - $inputs = $argv; - $output = false; -} - -if (!count($inputs)) { - echo("lessc: no input files\n"); - exit; -} - -if ($watch) { - if (!$output) { - echo("lessc: you must specify the output file if --watch is given\n"); - exit; - } - - $lastAction = 0; - - echo("lessc: watching input files\n"); - - while (1) { - clearstatcache(); - - $updated = false; - foreach ($inputs as $input) { - if ($input == '-') { - if (count($inputs) == 1) { - echo("lessc: during watching files is not possible to watch stdin\n"); - exit; - } - else { - continue; - } - } - - if (filemtime($input) > $lastAction) { - $updated = true; - break; - } - } - - if ($updated) { - $lastAction = time(); - $parser = new Less_Parser($env); - foreach ($inputs as $input) { - try { - $parser->parseFile($input, $rootpath); - } - catch (Exception $e) { - echo("lessc: " . $e->getMessage() . " \n"); - continue; // Invalid processing - } - } - - file_put_contents($output, $parser->getCss()); - echo("lessc: output file recompiled\n"); - } - - sleep(1); - } -} -else { - $parser = new Less_Parser($env); - foreach ($inputs as $input) { - if ($input == '-') { - $content = file_get_contents('php://stdin'); - $parser->parse($content); - } - else { - try { - $parser->parseFile($input); - } - catch (Exception $e) { - if (!$silent) { - echo("lessc: " . ((string)$e) . " \n"); - } - } - } - } - - if ($output) { - file_put_contents($output, $parser->getCss()); - } - else { - echo $parser->getCss(); - } -} diff --git a/less.php/lessc.inc.php b/less.php/lessc.inc.php deleted file mode 100755 index 284445f..0000000 --- a/less.php/lessc.inc.php +++ /dev/null @@ -1,274 +0,0 @@ -importDir = (array)$dirs; - } - - public function addImportDir( $dir ) { - $this->importDir = (array)$this->importDir; - $this->importDir[] = $dir; - } - - public function setFormatter( $name ) { - $this->formatterName = $name; - } - - public function setPreserveComments( $preserve ) { - } - - public function registerFunction( $name, $func ) { - $this->libFunctions[$name] = $func; - } - - public function unregisterFunction( $name ) { - unset( $this->libFunctions[$name] ); - } - - public function setVariables( $variables ) { - foreach ( $variables as $name => $value ) { - $this->setVariable( $name, $value ); - } - } - - public function setVariable( $name, $value ) { - $this->registeredVars[$name] = $value; - } - - public function unsetVariable( $name ) { - unset( $this->registeredVars[$name] ); - } - - public function setOptions( $options ) { - foreach ( $options as $name => $value ) { - $this->setOption( $name, $value ); - } - } - - public function setOption( $name, $value ) { - $this->options[$name] = $value; - } - - public function parse( $buffer, $presets = array() ) { - $this->setVariables( $presets ); - - $parser = new Less_Parser( $this->getOptions() ); - $parser->setImportDirs( $this->getImportDirs() ); - foreach ( $this->libFunctions as $name => $func ) { - $parser->registerFunction( $name, $func ); - } - $parser->parse( $buffer ); - if ( count( $this->registeredVars ) ) { - $parser->ModifyVars( $this->registeredVars ); - } - - return $parser->getCss(); - } - - protected function getOptions() { - $options = array( 'relativeUrls' => false ); - switch ( $this->formatterName ) { - case 'compressed': - $options['compress'] = true; - break; - } - if ( is_array( $this->options ) ) { - $options = array_merge( $options, $this->options ); - } - return $options; - } - - protected function getImportDirs() { - $dirs_ = (array)$this->importDir; - $dirs = array(); - foreach ( $dirs_ as $dir ) { - $dirs[$dir] = ''; - } - return $dirs; - } - - public function compile( $string, $name = null ) { - $oldImport = $this->importDir; - $this->importDir = (array)$this->importDir; - - $this->allParsedFiles = array(); - - $parser = new Less_Parser( $this->getOptions() ); - $parser->SetImportDirs( $this->getImportDirs() ); - if ( count( $this->registeredVars ) ) { - $parser->ModifyVars( $this->registeredVars ); - } - foreach ( $this->libFunctions as $name => $func ) { - $parser->registerFunction( $name, $func ); - } - $parser->parse( $string ); - $out = $parser->getCss(); - - $parsed = Less_Parser::AllParsedFiles(); - foreach ( $parsed as $file ) { - $this->addParsedFile( $file ); - } - - $this->importDir = $oldImport; - - return $out; - } - - public function compileFile( $fname, $outFname = null ) { - if ( !is_readable( $fname ) ) { - throw new Exception( 'load error: failed to find '.$fname ); - } - - $pi = pathinfo( $fname ); - - $oldImport = $this->importDir; - - $this->importDir = (array)$this->importDir; - $this->importDir[] = Less_Parser::AbsPath( $pi['dirname'] ).'/'; - - $this->allParsedFiles = array(); - $this->addParsedFile( $fname ); - - $parser = new Less_Parser( $this->getOptions() ); - $parser->SetImportDirs( $this->getImportDirs() ); - if ( count( $this->registeredVars ) ) { - $parser->ModifyVars( $this->registeredVars ); - } - foreach ( $this->libFunctions as $name => $func ) { - $parser->registerFunction( $name, $func ); - } - $parser->parseFile( $fname ); - $out = $parser->getCss(); - - $parsed = Less_Parser::AllParsedFiles(); - foreach ( $parsed as $file ) { - $this->addParsedFile( $file ); - } - - $this->importDir = $oldImport; - - if ( $outFname !== null ) { - return file_put_contents( $outFname, $out ); - } - - return $out; - } - - public function checkedCompile( $in, $out ) { - if ( !is_file( $out ) || filemtime( $in ) > filemtime( $out ) ) { - $this->compileFile( $in, $out ); - return true; - } - return false; - } - - /** - * Execute lessphp on a .less file or a lessphp cache structure - * - * The lessphp cache structure contains information about a specific - * less file having been parsed. It can be used as a hint for future - * calls to determine whether or not a rebuild is required. - * - * The cache structure contains two important keys that may be used - * externally: - * - * compiled: The final compiled CSS - * updated: The time (in seconds) the CSS was last compiled - * - * The cache structure is a plain-ol' PHP associative array and can - * be serialized and unserialized without a hitch. - * - * @param mixed $in Input - * @param bool $force Force rebuild? - * @return array lessphp cache structure - */ - public function cachedCompile( $in, $force = false ) { - // assume no root - $root = null; - - if ( is_string( $in ) ) { - $root = $in; - } elseif ( is_array( $in ) and isset( $in['root'] ) ) { - if ( $force or !isset( $in['files'] ) ) { - // If we are forcing a recompile or if for some reason the - // structure does not contain any file information we should - // specify the root to trigger a rebuild. - $root = $in['root']; - } elseif ( isset( $in['files'] ) and is_array( $in['files'] ) ) { - foreach ( $in['files'] as $fname => $ftime ) { - if ( !file_exists( $fname ) or filemtime( $fname ) > $ftime ) { - // One of the files we knew about previously has changed - // so we should look at our incoming root again. - $root = $in['root']; - break; - } - } - } - } else { - // TODO: Throw an exception? We got neither a string nor something - // that looks like a compatible lessphp cache structure. - return null; - } - - if ( $root !== null ) { - // If we have a root value which means we should rebuild. - $out = array(); - $out['root'] = $root; - $out['compiled'] = $this->compileFile( $root ); - $out['files'] = $this->allParsedFiles(); - $out['updated'] = time(); - return $out; - } else { - // No changes, pass back the structure - // we were given initially. - return $in; - } - } - - public function ccompile( $in, $out, $less = null ) { - if ( $less === null ) { - $less = new self; - } - return $less->checkedCompile( $in, $out ); - } - - public static function cexecute( $in, $force = false, $less = null ) { - if ( $less === null ) { - $less = new self; - } - return $less->cachedCompile( $in, $force ); - } - - public function allParsedFiles() { - return $this->allParsedFiles; - } - - protected function addParsedFile( $file ) { - $this->allParsedFiles[Less_Parser::AbsPath( $file )] = filemtime( $file ); - } -} diff --git a/less.php/lib/Less/.easymin/ignore_prefixes b/less.php/lib/Less/.easymin/ignore_prefixes deleted file mode 100755 index ca953b2..0000000 --- a/less.php/lib/Less/.easymin/ignore_prefixes +++ /dev/null @@ -1,2 +0,0 @@ -.easymin -Autoloader.php diff --git a/less.php/lib/Less/Autoloader.php b/less.php/lib/Less/Autoloader.php deleted file mode 100755 index 00116f7..0000000 --- a/less.php/lib/Less/Autoloader.php +++ /dev/null @@ -1,77 +0,0 @@ - '/' ); - } - - // generate name for compiled css file - $hash = md5( json_encode( $less_files ) ); - $list_file = Less_Cache::$cache_dir . Less_Cache::$prefix . $hash . '.list'; - - // check cached content - if ( !isset( $parser_options['use_cache'] ) || $parser_options['use_cache'] === true ) { - if ( file_exists( $list_file ) ) { - - self::ListFiles( $list_file, $list, $cached_name ); - $compiled_name = self::CompiledName( $list, $hash ); - - // if $cached_name is the same as the $compiled name, don't regenerate - if ( !$cached_name || $cached_name === $compiled_name ) { - - $output_file = self::OutputFile( $compiled_name, $parser_options ); - - if ( $output_file && file_exists( $output_file ) ) { - @touch( $list_file ); - return basename( $output_file ); // for backwards compatibility, we just return the name of the file - } - } - } - } - - $compiled = self::Cache( $less_files, $parser_options ); - if ( !$compiled ) { - return false; - } - - $compiled_name = self::CompiledName( $less_files, $hash ); - $output_file = self::OutputFile( $compiled_name, $parser_options ); - - // save the file list - $list = $less_files; - $list[] = $compiled_name; - $cache = implode( "\n", $list ); - file_put_contents( $list_file, $cache ); - - // save the css - file_put_contents( $output_file, $compiled ); - - // clean up - self::CleanCache(); - - return basename( $output_file ); - } - - /** - * Force the compiler to regenerate the cached css file - * - * @param array $less_files Array of .less files to compile - * @param array $parser_options Array of compiler options - * @param array $modify_vars Array of variables - * @return string Name of the css file - */ - public static function Regen( $less_files, $parser_options = array(), $modify_vars = array() ) { - $parser_options['use_cache'] = false; - return self::Get( $less_files, $parser_options, $modify_vars ); - } - - public static function Cache( &$less_files, $parser_options = array() ) { - // get less.php if it exists - $file = dirname( __FILE__ ) . '/Less.php'; - if ( file_exists( $file ) && !class_exists( 'Less_Parser' ) ) { - require_once $file; - } - - $parser_options['cache_dir'] = Less_Cache::$cache_dir; - $parser = new Less_Parser( $parser_options ); - - // combine files - foreach ( $less_files as $file_path => $uri_or_less ) { - - // treat as less markup if there are newline characters - if ( strpos( $uri_or_less, "\n" ) !== false ) { - $parser->Parse( $uri_or_less ); - continue; - } - - $parser->ParseFile( $file_path, $uri_or_less ); - } - - $compiled = $parser->getCss(); - - $less_files = $parser->allParsedFiles(); - - return $compiled; - } - - private static function OutputFile( $compiled_name, $parser_options ) { - // custom output file - if ( !empty( $parser_options['output'] ) ) { - - // relative to cache directory? - if ( preg_match( '#[\\\\/]#', $parser_options['output'] ) ) { - return $parser_options['output']; - } - - return Less_Cache::$cache_dir.$parser_options['output']; - } - - return Less_Cache::$cache_dir.$compiled_name; - } - - private static function CompiledName( $files, $extrahash ) { - // save the file list - $temp = array( Less_Version::cache_version ); - foreach ( $files as $file ) { - $temp[] = filemtime( $file )."\t".filesize( $file )."\t".$file; - } - - return Less_Cache::$prefix.sha1( json_encode( $temp ).$extrahash ).'.css'; - } - - public static function SetCacheDir( $dir ) { - Less_Cache::$cache_dir = $dir; - self::CheckCacheDir(); - } - - public static function CheckCacheDir() { - Less_Cache::$cache_dir = str_replace( '\\', '/', Less_Cache::$cache_dir ); - Less_Cache::$cache_dir = rtrim( Less_Cache::$cache_dir, '/' ).'/'; - - if ( !file_exists( Less_Cache::$cache_dir ) ) { - if ( !mkdir( Less_Cache::$cache_dir ) ) { - throw new Less_Exception_Parser( 'Less.php cache directory couldn\'t be created: '.Less_Cache::$cache_dir ); - } - - } elseif ( !is_dir( Less_Cache::$cache_dir ) ) { - throw new Less_Exception_Parser( 'Less.php cache directory doesn\'t exist: '.Less_Cache::$cache_dir ); - - } elseif ( !is_writable( Less_Cache::$cache_dir ) ) { - throw new Less_Exception_Parser( 'Less.php cache directory isn\'t writable: '.Less_Cache::$cache_dir ); - - } - - } - - /** - * Delete unused less.php files - * - */ - public static function CleanCache() { - static $clean = false; - - if ( $clean || empty( Less_Cache::$cache_dir ) ) { - return; - } - - $clean = true; - - // only remove files with extensions created by less.php - // css files removed based on the list files - $remove_types = array( 'lesscache' => 1,'list' => 1,'less' => 1,'map' => 1 ); - - $files = scandir( Less_Cache::$cache_dir ); - if ( !$files ) { - return; - } - - $check_time = time() - self::$gc_lifetime; - foreach ( $files as $file ) { - - // don't delete if the file wasn't created with less.php - if ( strpos( $file, Less_Cache::$prefix ) !== 0 ) { - continue; - } - - $parts = explode( '.', $file ); - $type = array_pop( $parts ); - - if ( !isset( $remove_types[$type] ) ) { - continue; - } - - $full_path = Less_Cache::$cache_dir . $file; - $mtime = filemtime( $full_path ); - - // don't delete if it's a relatively new file - if ( $mtime > $check_time ) { - continue; - } - - // delete the list file and associated css file - if ( $type === 'list' ) { - self::ListFiles( $full_path, $list, $css_file_name ); - if ( $css_file_name ) { - $css_file = Less_Cache::$cache_dir . $css_file_name; - if ( file_exists( $css_file ) ) { - unlink( $css_file ); - } - } - } - - unlink( $full_path ); - } - - } - - /** - * Get the list of less files and generated css file from a list file - * - */ - static function ListFiles( $list_file, &$list, &$css_file_name ) { - $list = explode( "\n", file_get_contents( $list_file ) ); - - // pop the cached name that should match $compiled_name - $css_file_name = array_pop( $list ); - - if ( !preg_match( '/^' . Less_Cache::$prefix . '[a-f0-9]+\.css$/', $css_file_name ) ) { - $list[] = $css_file_name; - $css_file_name = false; - } - - } - -} diff --git a/less.php/lib/Less/Colors.php b/less.php/lib/Less/Colors.php deleted file mode 100755 index 9be76cb..0000000 --- a/less.php/lib/Less/Colors.php +++ /dev/null @@ -1,169 +0,0 @@ - '#f0f8ff', - 'antiquewhite' => '#faebd7', - 'aqua' => '#00ffff', - 'aquamarine' => '#7fffd4', - 'azure' => '#f0ffff', - 'beige' => '#f5f5dc', - 'bisque' => '#ffe4c4', - 'black' => '#000000', - 'blanchedalmond' => '#ffebcd', - 'blue' => '#0000ff', - 'blueviolet' => '#8a2be2', - 'brown' => '#a52a2a', - 'burlywood' => '#deb887', - 'cadetblue' => '#5f9ea0', - 'chartreuse' => '#7fff00', - 'chocolate' => '#d2691e', - 'coral' => '#ff7f50', - 'cornflowerblue' => '#6495ed', - 'cornsilk' => '#fff8dc', - 'crimson' => '#dc143c', - 'cyan' => '#00ffff', - 'darkblue' => '#00008b', - 'darkcyan' => '#008b8b', - 'darkgoldenrod' => '#b8860b', - 'darkgray' => '#a9a9a9', - 'darkgrey' => '#a9a9a9', - 'darkgreen' => '#006400', - 'darkkhaki' => '#bdb76b', - 'darkmagenta' => '#8b008b', - 'darkolivegreen' => '#556b2f', - 'darkorange' => '#ff8c00', - 'darkorchid' => '#9932cc', - 'darkred' => '#8b0000', - 'darksalmon' => '#e9967a', - 'darkseagreen' => '#8fbc8f', - 'darkslateblue' => '#483d8b', - 'darkslategray' => '#2f4f4f', - 'darkslategrey' => '#2f4f4f', - 'darkturquoise' => '#00ced1', - 'darkviolet' => '#9400d3', - 'deeppink' => '#ff1493', - 'deepskyblue' => '#00bfff', - 'dimgray' => '#696969', - 'dimgrey' => '#696969', - 'dodgerblue' => '#1e90ff', - 'firebrick' => '#b22222', - 'floralwhite' => '#fffaf0', - 'forestgreen' => '#228b22', - 'fuchsia' => '#ff00ff', - 'gainsboro' => '#dcdcdc', - 'ghostwhite' => '#f8f8ff', - 'gold' => '#ffd700', - 'goldenrod' => '#daa520', - 'gray' => '#808080', - 'grey' => '#808080', - 'green' => '#008000', - 'greenyellow' => '#adff2f', - 'honeydew' => '#f0fff0', - 'hotpink' => '#ff69b4', - 'indianred' => '#cd5c5c', - 'indigo' => '#4b0082', - 'ivory' => '#fffff0', - 'khaki' => '#f0e68c', - 'lavender' => '#e6e6fa', - 'lavenderblush' => '#fff0f5', - 'lawngreen' => '#7cfc00', - 'lemonchiffon' => '#fffacd', - 'lightblue' => '#add8e6', - 'lightcoral' => '#f08080', - 'lightcyan' => '#e0ffff', - 'lightgoldenrodyellow' => '#fafad2', - 'lightgray' => '#d3d3d3', - 'lightgrey' => '#d3d3d3', - 'lightgreen' => '#90ee90', - 'lightpink' => '#ffb6c1', - 'lightsalmon' => '#ffa07a', - 'lightseagreen' => '#20b2aa', - 'lightskyblue' => '#87cefa', - 'lightslategray' => '#778899', - 'lightslategrey' => '#778899', - 'lightsteelblue' => '#b0c4de', - 'lightyellow' => '#ffffe0', - 'lime' => '#00ff00', - 'limegreen' => '#32cd32', - 'linen' => '#faf0e6', - 'magenta' => '#ff00ff', - 'maroon' => '#800000', - 'mediumaquamarine' => '#66cdaa', - 'mediumblue' => '#0000cd', - 'mediumorchid' => '#ba55d3', - 'mediumpurple' => '#9370d8', - 'mediumseagreen' => '#3cb371', - 'mediumslateblue' => '#7b68ee', - 'mediumspringgreen' => '#00fa9a', - 'mediumturquoise' => '#48d1cc', - 'mediumvioletred' => '#c71585', - 'midnightblue' => '#191970', - 'mintcream' => '#f5fffa', - 'mistyrose' => '#ffe4e1', - 'moccasin' => '#ffe4b5', - 'navajowhite' => '#ffdead', - 'navy' => '#000080', - 'oldlace' => '#fdf5e6', - 'olive' => '#808000', - 'olivedrab' => '#6b8e23', - 'orange' => '#ffa500', - 'orangered' => '#ff4500', - 'orchid' => '#da70d6', - 'palegoldenrod' => '#eee8aa', - 'palegreen' => '#98fb98', - 'paleturquoise' => '#afeeee', - 'palevioletred' => '#d87093', - 'papayawhip' => '#ffefd5', - 'peachpuff' => '#ffdab9', - 'peru' => '#cd853f', - 'pink' => '#ffc0cb', - 'plum' => '#dda0dd', - 'powderblue' => '#b0e0e6', - 'purple' => '#800080', - 'red' => '#ff0000', - 'rosybrown' => '#bc8f8f', - 'royalblue' => '#4169e1', - 'saddlebrown' => '#8b4513', - 'salmon' => '#fa8072', - 'sandybrown' => '#f4a460', - 'seagreen' => '#2e8b57', - 'seashell' => '#fff5ee', - 'sienna' => '#a0522d', - 'silver' => '#c0c0c0', - 'skyblue' => '#87ceeb', - 'slateblue' => '#6a5acd', - 'slategray' => '#708090', - 'slategrey' => '#708090', - 'snow' => '#fffafa', - 'springgreen' => '#00ff7f', - 'steelblue' => '#4682b4', - 'tan' => '#d2b48c', - 'teal' => '#008080', - 'thistle' => '#d8bfd8', - 'tomato' => '#ff6347', - 'turquoise' => '#40e0d0', - 'violet' => '#ee82ee', - 'wheat' => '#f5deb3', - 'white' => '#ffffff', - 'whitesmoke' => '#f5f5f5', - 'yellow' => '#ffff00', - 'yellowgreen' => '#9acd32' - ); - - public static function hasOwnProperty( $color ) { - return isset( self::$colors[$color] ); - } - - public static function color( $color ) { - return self::$colors[$color]; - } - -} diff --git a/less.php/lib/Less/Configurable.php b/less.php/lib/Less/Configurable.php deleted file mode 100755 index 7f1348b..0000000 --- a/less.php/lib/Less/Configurable.php +++ /dev/null @@ -1,66 +0,0 @@ -defaultOptions ); - $this->options = array_merge( $this->defaultOptions, $this->options, $options ); - } - - /** - * Get an option value by name - * - * If the option is empty or not set a NULL value will be returned. - * - * @param string $name - * @param mixed $default Default value if confiuration of $name is not present - * @return mixed - */ - public function getOption( $name, $default = null ) { - if ( isset( $this->options[$name] ) ) { - return $this->options[$name]; - } - return $default; - } - - /** - * Set an option - * - * @param string $name - * @param mixed $value - */ - public function setOption( $name, $value ) { - $this->options[$name] = $value; - } - -} diff --git a/less.php/lib/Less/Environment.php b/less.php/lib/Less/Environment.php deleted file mode 100755 index 2555d03..0000000 --- a/less.php/lib/Less/Environment.php +++ /dev/null @@ -1,157 +0,0 @@ - ',', - ': ' => ':', - '' => '', - ' ' => ' ', - ':' => ' :', - '+' => '+', - '~' => '~', - '>' => '>', - '|' => '|', - '^' => '^', - '^^' => '^^' - ); - - } else { - - Less_Environment::$_outputMap = array( - ',' => ', ', - ': ' => ': ', - '' => '', - ' ' => ' ', - ':' => ' :', - '+' => ' + ', - '~' => ' ~ ', - '>' => ' > ', - '|' => '|', - '^' => ' ^ ', - '^^' => ' ^^ ' - ); - - } - } - - public function copyEvalEnv( $frames = array() ) { - $new_env = new Less_Environment(); - $new_env->frames = $frames; - return $new_env; - } - - public static function isMathOn() { - return !Less_Parser::$options['strictMath'] || Less_Environment::$parensStack; - } - - public static function isPathRelative( $path ) { - return !preg_match( '/^(?:[a-z-]+:|\/)/', $path ); - } - - /** - * Canonicalize a path by resolving references to '/./', '/../' - * Does not remove leading "../" - * @param string path or url - * @return string Canonicalized path - * - */ - public static function normalizePath( $path ) { - $segments = explode( '/', $path ); - $segments = array_reverse( $segments ); - - $path = array(); - $path_len = 0; - - while ( $segments ) { - $segment = array_pop( $segments ); - switch ( $segment ) { - - case '.': - break; - - case '..': - if ( !$path_len || ( $path[$path_len - 1] === '..' ) ) { - $path[] = $segment; - $path_len++; - } else { - array_pop( $path ); - $path_len--; - } - break; - - default: - $path[] = $segment; - $path_len++; - break; - } - } - - return implode( '/', $path ); - } - - public function unshiftFrame( $frame ) { - array_unshift( $this->frames, $frame ); - } - - public function shiftFrame() { - return array_shift( $this->frames ); - } - -} diff --git a/less.php/lib/Less/Exception/Chunk.php b/less.php/lib/Less/Exception/Chunk.php deleted file mode 100755 index 1f1dddb..0000000 --- a/less.php/lib/Less/Exception/Chunk.php +++ /dev/null @@ -1,203 +0,0 @@ -message = 'ParseError: Unexpected input'; // default message - - $this->index = $index; - - $this->currentFile = $currentFile; - - $this->input = $input; - $this->input_len = strlen( $input ); - - $this->Chunks(); - $this->genMessage(); - } - - /** - * See less.js chunks() - * We don't actually need the chunks - * - */ - protected function Chunks() { - $level = 0; - $parenLevel = 0; - $lastMultiCommentEndBrace = null; - $lastOpening = null; - $lastMultiComment = null; - $lastParen = null; - - for ( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ) { - $cc = $this->CharCode( $this->parserCurrentIndex ); - if ( ( ( $cc >= 97 ) && ( $cc <= 122 ) ) || ( $cc < 34 ) ) { - // a-z or whitespace - continue; - } - - switch ( $cc ) { - - // ( - case 40: - $parenLevel++; - $lastParen = $this->parserCurrentIndex; - break; - - // ) - case 41: - $parenLevel--; - if ( $parenLevel < 0 ) { - return $this->fail( "missing opening `(`" ); - } - break; - - // ; - case 59: - // if (!$parenLevel) { $this->emitChunk(); } - break; - - // { - case 123: - $level++; - $lastOpening = $this->parserCurrentIndex; - break; - - // } - case 125: - $level--; - if ( $level < 0 ) { - return $this->fail( "missing opening `{`" ); - - } - // if (!$level && !$parenLevel) { $this->emitChunk(); } - break; - // \ - case 92: - if ( $this->parserCurrentIndex < $this->input_len - 1 ) { $this->parserCurrentIndex++; break; - } - return $this->fail( "unescaped `\\`" ); - - // ", ' and ` - case 34: - case 39: - case 96: - $matched = 0; - $currentChunkStartIndex = $this->parserCurrentIndex; - for ( $this->parserCurrentIndex = $this->parserCurrentIndex + 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ) { - $cc2 = $this->CharCode( $this->parserCurrentIndex ); - if ( $cc2 > 96 ) { continue; - } - if ( $cc2 == $cc ) { $matched = 1; break; - } - if ( $cc2 == 92 ) { // \ - if ( $this->parserCurrentIndex == $this->input_len - 1 ) { - return $this->fail( "unescaped `\\`" ); - } - $this->parserCurrentIndex++; - } - } - if ( $matched ) { break; - } - return $this->fail( "unmatched `" . chr( $cc ) . "`", $currentChunkStartIndex ); - - // /, check for comment - case 47: - if ( $parenLevel || ( $this->parserCurrentIndex == $this->input_len - 1 ) ) { break; - } - $cc2 = $this->CharCode( $this->parserCurrentIndex + 1 ); - if ( $cc2 == 47 ) { - // //, find lnfeed - for ( $this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ) { - $cc2 = $this->CharCode( $this->parserCurrentIndex ); - if ( ( $cc2 <= 13 ) && ( ( $cc2 == 10 ) || ( $cc2 == 13 ) ) ) { break; - } - } - } else if ( $cc2 == 42 ) { - // /*, find */ - $lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex; - for ( $this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++ ) { - $cc2 = $this->CharCode( $this->parserCurrentIndex ); - if ( $cc2 == 125 ) { $lastMultiCommentEndBrace = $this->parserCurrentIndex; - } - if ( $cc2 != 42 ) { continue; - } - if ( $this->CharCode( $this->parserCurrentIndex + 1 ) == 47 ) { break; - } - } - if ( $this->parserCurrentIndex == $this->input_len - 1 ) { - return $this->fail( "missing closing `*/`", $currentChunkStartIndex ); - } - } - break; - - // *, check for unmatched */ - case 42: - if ( ( $this->parserCurrentIndex < $this->input_len - 1 ) && ( $this->CharCode( $this->parserCurrentIndex + 1 ) == 47 ) ) { - return $this->fail( "unmatched `/*`" ); - } - break; - } - } - - if ( $level !== 0 ) { - if ( ( $lastMultiComment > $lastOpening ) && ( $lastMultiCommentEndBrace > $lastMultiComment ) ) { - return $this->fail( "missing closing `}` or `*/`", $lastOpening ); - } else { - return $this->fail( "missing closing `}`", $lastOpening ); - } - } else if ( $parenLevel !== 0 ) { - return $this->fail( "missing closing `)`", $lastParen ); - } - - // chunk didn't fail - - //$this->emitChunk(true); - } - - public function CharCode( $pos ) { - return ord( $this->input[$pos] ); - } - - public function fail( $msg, $index = null ) { - if ( !$index ) { - $this->index = $this->parserCurrentIndex; - } else { - $this->index = $index; - } - $this->message = 'ParseError: '.$msg; - } - - /* - function emitChunk( $force = false ){ - $len = $this->parserCurrentIndex - $this->emitFrom; - if ((($len < 512) && !$force) || !$len) { - return; - } - $chunks[] = substr($this->input, $this->emitFrom, $this->parserCurrentIndex + 1 - $this->emitFrom ); - $this->emitFrom = $this->parserCurrentIndex + 1; - } - */ - -} diff --git a/less.php/lib/Less/Exception/Compiler.php b/less.php/lib/Less/Exception/Compiler.php deleted file mode 100755 index 1c3727a..0000000 --- a/less.php/lib/Less/Exception/Compiler.php +++ /dev/null @@ -1,11 +0,0 @@ -previous = $previous; - parent::__construct( $message, $code ); - } else { - parent::__construct( $message, $code, $previous ); - } - - $this->currentFile = $currentFile; - $this->index = $index; - - $this->genMessage(); - } - - protected function getInput() { - if ( !$this->input && $this->currentFile && $this->currentFile['filename'] && file_exists( $this->currentFile['filename'] ) ) { - $this->input = file_get_contents( $this->currentFile['filename'] ); - } - } - - /** - * Converts the exception to string - * - * @return string - */ - public function genMessage() { - if ( $this->currentFile && $this->currentFile['filename'] ) { - $this->message .= ' in '.basename( $this->currentFile['filename'] ); - } - - if ( $this->index !== null ) { - $this->getInput(); - if ( $this->input ) { - $line = self::getLineNumber(); - $this->message .= ' on line '.$line.', column '.self::getColumn(); - - $lines = explode( "\n", $this->input ); - - $count = count( $lines ); - $start_line = max( 0, $line - 3 ); - $last_line = min( $count, $start_line + 6 ); - $num_len = strlen( $last_line ); - for ( $i = $start_line; $i < $last_line; $i++ ) { - $this->message .= "\n".str_pad( $i + 1, $num_len, '0', STR_PAD_LEFT ).'| '.$lines[$i]; - } - } - } - - } - - /** - * Returns the line number the error was encountered - * - * @return integer - */ - public function getLineNumber() { - if ( $this->index ) { - // https://bugs.php.net/bug.php?id=49790 - if ( ini_get( "mbstring.func_overload" ) ) { - return substr_count( substr( $this->input, 0, $this->index ), "\n" ) + 1; - } else { - return substr_count( $this->input, "\n", 0, $this->index ) + 1; - } - } - return 1; - } - - /** - * Returns the column the error was encountered - * - * @return integer - */ - public function getColumn() { - $part = substr( $this->input, 0, $this->index ); - $pos = strrpos( $part, "\n" ); - return $this->index - $pos; - } - -} diff --git a/less.php/lib/Less/Functions.php b/less.php/lib/Less/Functions.php deleted file mode 100755 index c9e97bd..0000000 --- a/less.php/lib/Less/Functions.php +++ /dev/null @@ -1,1186 +0,0 @@ -env = $env; - $this->currentFileInfo = $currentFileInfo; - } - - /** - * @param string $op - */ - public static function operate( $op, $a, $b ) { - switch ( $op ) { - case '+': -return $a + $b; - case '-': -return $a - $b; - case '*': -return $a * $b; - case '/': -return $a / $b; - } - } - - public static function clamp( $val, $max = 1 ) { - return min( max( $val, 0 ), $max ); - } - - public static function fround( $value ) { - if ( $value === 0 ) { - return $value; - } - - if ( Less_Parser::$options['numPrecision'] ) { - $p = pow( 10, Less_Parser::$options['numPrecision'] ); - return round( $value * $p ) / $p; - } - return $value; - } - - public static function number( $n ) { - if ( $n instanceof Less_Tree_Dimension ) { - return floatval( $n->unit->is( '%' ) ? $n->value / 100 : $n->value ); - } else if ( is_numeric( $n ) ) { - return $n; - } else { - throw new Less_Exception_Compiler( "color functions take numbers as parameters" ); - } - } - - public static function scaled( $n, $size = 255 ) { - if ( $n instanceof Less_Tree_Dimension && $n->unit->is( '%' ) ) { - return (float)$n->value * $size / 100; - } else { - return Less_Functions::number( $n ); - } - } - - public function rgb( $r = null, $g = null, $b = null ) { - if ( is_null( $r ) || is_null( $g ) || is_null( $b ) ) { - throw new Less_Exception_Compiler( "rgb expects three parameters" ); - } - return $this->rgba( $r, $g, $b, 1.0 ); - } - - public function rgba( $r = null, $g = null, $b = null, $a = null ) { - $rgb = array( $r, $g, $b ); - $rgb = array_map( array( 'Less_Functions','scaled' ), $rgb ); - - $a = self::number( $a ); - return new Less_Tree_Color( $rgb, $a ); - } - - public function hsl( $h, $s, $l ) { - return $this->hsla( $h, $s, $l, 1.0 ); - } - - public function hsla( $h, $s, $l, $a ) { - $h = fmod( self::number( $h ), 360 ) / 360; // Classic % operator will change float to int - $s = self::clamp( self::number( $s ) ); - $l = self::clamp( self::number( $l ) ); - $a = self::clamp( self::number( $a ) ); - - $m2 = $l <= 0.5 ? $l * ( $s + 1 ) : $l + $s - $l * $s; - - $m1 = $l * 2 - $m2; - - return $this->rgba( self::hsla_hue( $h + 1 / 3, $m1, $m2 ) * 255, - self::hsla_hue( $h, $m1, $m2 ) * 255, - self::hsla_hue( $h - 1 / 3, $m1, $m2 ) * 255, - $a ); - } - - /** - * @param double $h - */ - public function hsla_hue( $h, $m1, $m2 ) { - $h = $h < 0 ? $h + 1 : ( $h > 1 ? $h - 1 : $h ); - if ( $h * 6 < 1 ) return $m1 + ( $m2 - $m1 ) * $h * 6; else if ( $h * 2 < 1 ) return $m2; else if ( $h * 3 < 2 ) return $m1 + ( $m2 - $m1 ) * ( 2 / 3 - $h ) * 6; else return $m1; - } - - public function hsv( $h, $s, $v ) { - return $this->hsva( $h, $s, $v, 1.0 ); - } - - /** - * @param double $a - */ - public function hsva( $h, $s, $v, $a ) { - $h = ( ( Less_Functions::number( $h ) % 360 ) / 360 ) * 360; - $s = Less_Functions::number( $s ); - $v = Less_Functions::number( $v ); - $a = Less_Functions::number( $a ); - - $i = floor( ( $h / 60 ) % 6 ); - $f = ( $h / 60 ) - $i; - - $vs = array( $v, - $v * ( 1 - $s ), - $v * ( 1 - $f * $s ), - $v * ( 1 - ( 1 - $f ) * $s ) ); - - $perm = array( array( 0, 3, 1 ), - array( 2, 0, 1 ), - array( 1, 0, 3 ), - array( 1, 2, 0 ), - array( 3, 1, 0 ), - array( 0, 1, 2 ) ); - - return $this->rgba( $vs[$perm[$i][0]] * 255, - $vs[$perm[$i][1]] * 255, - $vs[$perm[$i][2]] * 255, - $a ); - } - - public function hue( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to hue must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $c = $color->toHSL(); - return new Less_Tree_Dimension( Less_Parser::round( $c['h'] ) ); - } - - public function saturation( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to saturation must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $c = $color->toHSL(); - return new Less_Tree_Dimension( Less_Parser::round( $c['s'] * 100 ), '%' ); - } - - public function lightness( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to lightness must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $c = $color->toHSL(); - return new Less_Tree_Dimension( Less_Parser::round( $c['l'] * 100 ), '%' ); - } - - public function hsvhue( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to hsvhue must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsv = $color->toHSV(); - return new Less_Tree_Dimension( Less_Parser::round( $hsv['h'] ) ); - } - - public function hsvsaturation( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to hsvsaturation must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsv = $color->toHSV(); - return new Less_Tree_Dimension( Less_Parser::round( $hsv['s'] * 100 ), '%' ); - } - - public function hsvvalue( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to hsvvalue must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsv = $color->toHSV(); - return new Less_Tree_Dimension( Less_Parser::round( $hsv['v'] * 100 ), '%' ); - } - - public function red( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to red must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return new Less_Tree_Dimension( $color->rgb[0] ); - } - - public function green( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to green must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return new Less_Tree_Dimension( $color->rgb[1] ); - } - - public function blue( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to blue must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return new Less_Tree_Dimension( $color->rgb[2] ); - } - - public function alpha( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to alpha must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $c = $color->toHSL(); - return new Less_Tree_Dimension( $c['a'] ); - } - - public function luma( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to luma must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return new Less_Tree_Dimension( Less_Parser::round( $color->luma() * $color->alpha * 100 ), '%' ); - } - - public function luminance( $color = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to luminance must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $luminance = - ( 0.2126 * $color->rgb[0] / 255 ) - + ( 0.7152 * $color->rgb[1] / 255 ) - + ( 0.0722 * $color->rgb[2] / 255 ); - - return new Less_Tree_Dimension( Less_Parser::round( $luminance * $color->alpha * 100 ), '%' ); - } - - public function saturate( $color = null, $amount = null ) { - // filter: saturate(3.2); - // should be kept as is, so check for color - if ( $color instanceof Less_Tree_Dimension ) { - return null; - } - - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to saturate must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to saturate must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - - $hsl['s'] += $amount->value / 100; - $hsl['s'] = self::clamp( $hsl['s'] ); - - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - /** - * @param Less_Tree_Dimension $amount - */ - public function desaturate( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to desaturate must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to desaturate must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - - $hsl['s'] -= $amount->value / 100; - $hsl['s'] = self::clamp( $hsl['s'] ); - - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - public function lighten( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to lighten must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to lighten must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - - $hsl['l'] += $amount->value / 100; - $hsl['l'] = self::clamp( $hsl['l'] ); - - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - public function darken( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to darken must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to darken must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - $hsl['l'] -= $amount->value / 100; - $hsl['l'] = self::clamp( $hsl['l'] ); - - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - public function fadein( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to fadein must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to fadein must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - $hsl['a'] += $amount->value / 100; - $hsl['a'] = self::clamp( $hsl['a'] ); - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - public function fadeout( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to fadeout must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to fadeout must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - $hsl['a'] -= $amount->value / 100; - $hsl['a'] = self::clamp( $hsl['a'] ); - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - public function fade( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to fade must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to fade must be a percentage' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - - $hsl['a'] = $amount->value / 100; - $hsl['a'] = self::clamp( $hsl['a'] ); - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - public function spin( $color = null, $amount = null ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to spin must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$amount instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The second argument to spin must be a number' . ( $amount instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $hsl = $color->toHSL(); - $hue = fmod( $hsl['h'] + $amount->value, 360 ); - - $hsl['h'] = $hue < 0 ? 360 + $hue : $hue; - - return $this->hsla( $hsl['h'], $hsl['s'], $hsl['l'], $hsl['a'] ); - } - - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - - /** - * @param Less_Tree_Color $color1 - */ - public function mix( $color1 = null, $color2 = null, $weight = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to mix must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to mix must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$weight ) { - $weight = new Less_Tree_Dimension( '50', '%' ); - } - if ( !$weight instanceof Less_Tree_Dimension ) { - throw new Less_Exception_Compiler( 'The third argument to contrast must be a percentage' . ( $weight instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - $p = $weight->value / 100.0; - $w = $p * 2 - 1; - $hsl1 = $color1->toHSL(); - $hsl2 = $color2->toHSL(); - $a = $hsl1['a'] - $hsl2['a']; - - $w1 = ( ( ( ( $w * $a ) == -1 ) ? $w : ( $w + $a ) / ( 1 + $w * $a ) ) + 1 ) / 2; - $w2 = 1 - $w1; - - $rgb = array( $color1->rgb[0] * $w1 + $color2->rgb[0] * $w2, - $color1->rgb[1] * $w1 + $color2->rgb[1] * $w2, - $color1->rgb[2] * $w1 + $color2->rgb[2] * $w2 ); - - $alpha = $color1->alpha * $p + $color2->alpha * ( 1 - $p ); - - return new Less_Tree_Color( $rgb, $alpha ); - } - - public function greyscale( $color ) { - return $this->desaturate( $color, new Less_Tree_Dimension( 100, '%' ) ); - } - - public function contrast( $color, $dark = null, $light = null, $threshold = null ) { - // filter: contrast(3.2); - // should be kept as is, so check for color - if ( !$color instanceof Less_Tree_Color ) { - return null; - } - if ( !$light ) { - $light = $this->rgba( 255, 255, 255, 1.0 ); - } - if ( !$dark ) { - $dark = $this->rgba( 0, 0, 0, 1.0 ); - } - - if ( !$dark instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to contrast must be a color' . ( $dark instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$light instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The third argument to contrast must be a color' . ( $light instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - // Figure out which is actually light and dark! - if ( $dark->luma() > $light->luma() ) { - $t = $light; - $light = $dark; - $dark = $t; - } - if ( !$threshold ) { - $threshold = 0.43; - } else { - $threshold = Less_Functions::number( $threshold ); - } - - if ( $color->luma() < $threshold ) { - return $light; - } else { - return $dark; - } - } - - public function e( $str ) { - if ( is_string( $str ) ) { - return new Less_Tree_Anonymous( $str ); - } - return new Less_Tree_Anonymous( $str instanceof Less_Tree_JavaScript ? $str->expression : $str->value ); - } - - public function escape( $str ) { - $revert = array( '%21' => '!', '%2A' => '*', '%27' => "'",'%3F' => '?','%26' => '&','%2C' => ',','%2F' => '/','%40' => '@','%2B' => '+','%24' => '$' ); - - return new Less_Tree_Anonymous( strtr( rawurlencode( $str->value ), $revert ) ); - } - - /** - * todo: This function will need some additional work to make it work the same as less.js - * - */ - public function replace( $string, $pattern, $replacement, $flags = null ) { - $result = $string->value; - - $expr = '/'.str_replace( '/', '\\/', $pattern->value ).'/'; - if ( $flags && $flags->value ) { - $expr .= self::replace_flags( $flags->value ); - } - - $result = preg_replace( $expr, $replacement->value, $result ); - - if ( property_exists( $string, 'quote' ) ) { - return new Less_Tree_Quoted( $string->quote, $result, $string->escaped ); - } - return new Less_Tree_Quoted( '', $result ); - } - - public static function replace_flags( $flags ) { - $flags = str_split( $flags, 1 ); - $new_flags = ''; - - foreach ( $flags as $flag ) { - switch ( $flag ) { - case 'e': - case 'g': - break; - - default: - $new_flags .= $flag; - break; - } - } - - return $new_flags; - } - - public function _percent() { - $string = func_get_arg( 0 ); - - $args = func_get_args(); - array_shift( $args ); - $result = $string->value; - - foreach ( $args as $arg ) { - if ( preg_match( '/%[sda]/i', $result, $token ) ) { - $token = $token[0]; - $value = stristr( $token, 's' ) ? $arg->value : $arg->toCSS(); - $value = preg_match( '/[A-Z]$/', $token ) ? urlencode( $value ) : $value; - $result = preg_replace( '/%[sda]/i', $value, $result, 1 ); - } - } - $result = str_replace( '%%', '%', $result ); - - return new Less_Tree_Quoted( $string->quote, $result, $string->escaped ); - } - - public function unit( $val, $unit = null ) { - if ( !( $val instanceof Less_Tree_Dimension ) ) { - throw new Less_Exception_Compiler( 'The first argument to unit must be a number' . ( $val instanceof Less_Tree_Operation ? '. Have you forgotten parenthesis?' : '.' ) ); - } - - if ( $unit ) { - if ( $unit instanceof Less_Tree_Keyword ) { - $unit = $unit->value; - } else { - $unit = $unit->toCSS(); - } - } else { - $unit = ""; - } - return new Less_Tree_Dimension( $val->value, $unit ); - } - - public function convert( $val, $unit ) { - return $val->convertTo( $unit->value ); - } - - public function round( $n, $f = false ) { - $fraction = 0; - if ( $f !== false ) { - $fraction = $f->value; - } - - return $this->_math( 'Less_Parser::round', null, $n, $fraction ); - } - - public function pi() { - return new Less_Tree_Dimension( M_PI ); - } - - public function mod( $a, $b ) { - return new Less_Tree_Dimension( $a->value % $b->value, $a->unit ); - } - - public function pow( $x, $y ) { - if ( is_numeric( $x ) && is_numeric( $y ) ) { - $x = new Less_Tree_Dimension( $x ); - $y = new Less_Tree_Dimension( $y ); - } elseif ( !( $x instanceof Less_Tree_Dimension ) || !( $y instanceof Less_Tree_Dimension ) ) { - throw new Less_Exception_Compiler( 'Arguments must be numbers' ); - } - - return new Less_Tree_Dimension( pow( $x->value, $y->value ), $x->unit ); - } - - // var mathFunctions = [{name:"ce ... - public function ceil( $n ) { - return $this->_math( 'ceil', null, $n ); - } - - public function floor( $n ) { - return $this->_math( 'floor', null, $n ); - } - - public function sqrt( $n ) { - return $this->_math( 'sqrt', null, $n ); - } - - public function abs( $n ) { - return $this->_math( 'abs', null, $n ); - } - - public function tan( $n ) { - return $this->_math( 'tan', '', $n ); - } - - public function sin( $n ) { - return $this->_math( 'sin', '', $n ); - } - - public function cos( $n ) { - return $this->_math( 'cos', '', $n ); - } - - public function atan( $n ) { - return $this->_math( 'atan', 'rad', $n ); - } - - public function asin( $n ) { - return $this->_math( 'asin', 'rad', $n ); - } - - public function acos( $n ) { - return $this->_math( 'acos', 'rad', $n ); - } - - private function _math() { - $args = func_get_args(); - $fn = array_shift( $args ); - $unit = array_shift( $args ); - - if ( $args[0] instanceof Less_Tree_Dimension ) { - - if ( $unit === null ) { - $unit = $args[0]->unit; - } else { - $args[0] = $args[0]->unify(); - } - $args[0] = (float)$args[0]->value; - return new Less_Tree_Dimension( call_user_func_array( $fn, $args ), $unit ); - } else if ( is_numeric( $args[0] ) ) { - return call_user_func_array( $fn, $args ); - } else { - throw new Less_Exception_Compiler( "math functions take numbers as parameters" ); - } - } - - /** - * @param boolean $isMin - */ - private function _minmax( $isMin, $args ) { - $arg_count = count( $args ); - - if ( $arg_count < 1 ) { - throw new Less_Exception_Compiler( 'one or more arguments required' ); - } - - $j = null; - $unitClone = null; - $unitStatic = null; - - $order = array(); // elems only contains original argument values. - $values = array(); // key is the unit.toString() for unified tree.Dimension values, - // value is the index into the order array. - - for ( $i = 0; $i < $arg_count; $i++ ) { - $current = $args[$i]; - if ( !( $current instanceof Less_Tree_Dimension ) ) { - if ( is_array( $args[$i]->value ) ) { - $args[] = $args[$i]->value; - } - continue; - } - - if ( $current->unit->toString() === '' && !$unitClone ) { - $temp = new Less_Tree_Dimension( $current->value, $unitClone ); - $currentUnified = $temp->unify(); - } else { - $currentUnified = $current->unify(); - } - - if ( $currentUnified->unit->toString() === "" && !$unitStatic ) { - $unit = $unitStatic; - } else { - $unit = $currentUnified->unit->toString(); - } - - if ( $unit !== '' && !$unitStatic || $unit !== '' && $order[0]->unify()->unit->toString() === "" ) { - $unitStatic = $unit; - } - - if ( $unit != '' && !$unitClone ) { - $unitClone = $current->unit->toString(); - } - - if ( isset( $values[''] ) && $unit !== '' && $unit === $unitStatic ) { - $j = $values['']; - } elseif ( isset( $values[$unit] ) ) { - $j = $values[$unit]; - } else { - - if ( $unitStatic && $unit !== $unitStatic ) { - throw new Less_Exception_Compiler( 'incompatible types' ); - } - $values[$unit] = count( $order ); - $order[] = $current; - continue; - } - - if ( $order[$j]->unit->toString() === "" && $unitClone ) { - $temp = new Less_Tree_Dimension( $order[$j]->value, $unitClone ); - $referenceUnified = $temp->unify(); - } else { - $referenceUnified = $order[$j]->unify(); - } - if ( ( $isMin && $currentUnified->value < $referenceUnified->value ) || ( !$isMin && $currentUnified->value > $referenceUnified->value ) ) { - $order[$j] = $current; - } - } - - if ( count( $order ) == 1 ) { - return $order[0]; - } - $args = array(); - foreach ( $order as $a ) { - $args[] = $a->toCSS( $this->env ); - } - return new Less_Tree_Anonymous( ( $isMin ? 'min(' : 'max(' ) . implode( Less_Environment::$_outputMap[','], $args ).')' ); - } - - public function min() { - $args = func_get_args(); - return $this->_minmax( true, $args ); - } - - public function max() { - $args = func_get_args(); - return $this->_minmax( false, $args ); - } - - public function getunit( $n ) { - return new Less_Tree_Anonymous( $n->unit ); - } - - public function argb( $color ) { - if ( !$color instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to argb must be a color' . ( $color instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return new Less_Tree_Anonymous( $color->toARGB() ); - } - - public function percentage( $n ) { - return new Less_Tree_Dimension( $n->value * 100, '%' ); - } - - public function color( $n ) { - if ( $n instanceof Less_Tree_Quoted ) { - $colorCandidate = $n->value; - $returnColor = Less_Tree_Color::fromKeyword( $colorCandidate ); - if ( $returnColor ) { - return $returnColor; - } - if ( preg_match( '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/', $colorCandidate ) ) { - return new Less_Tree_Color( substr( $colorCandidate, 1 ) ); - } - throw new Less_Exception_Compiler( "argument must be a color keyword or 3/6 digit hex e.g. #FFF" ); - } else { - throw new Less_Exception_Compiler( "argument must be a string" ); - } - } - - public function iscolor( $n ) { - return $this->_isa( $n, 'Less_Tree_Color' ); - } - - public function isnumber( $n ) { - return $this->_isa( $n, 'Less_Tree_Dimension' ); - } - - public function isstring( $n ) { - return $this->_isa( $n, 'Less_Tree_Quoted' ); - } - - public function iskeyword( $n ) { - return $this->_isa( $n, 'Less_Tree_Keyword' ); - } - - public function isurl( $n ) { - return $this->_isa( $n, 'Less_Tree_Url' ); - } - - public function ispixel( $n ) { - return $this->isunit( $n, 'px' ); - } - - public function ispercentage( $n ) { - return $this->isunit( $n, '%' ); - } - - public function isem( $n ) { - return $this->isunit( $n, 'em' ); - } - - /** - * @param string $unit - */ - public function isunit( $n, $unit ) { - if ( is_object( $unit ) && property_exists( $unit, 'value' ) ) { - $unit = $unit->value; - } - - return ( $n instanceof Less_Tree_Dimension ) && $n->unit->is( $unit ) ? new Less_Tree_Keyword( 'true' ) : new Less_Tree_Keyword( 'false' ); - } - - /** - * @param string $type - */ - private function _isa( $n, $type ) { - return is_a( $n, $type ) ? new Less_Tree_Keyword( 'true' ) : new Less_Tree_Keyword( 'false' ); - } - - public function tint( $color, $amount = null ) { - return $this->mix( $this->rgb( 255, 255, 255 ), $color, $amount ); - } - - public function shade( $color, $amount = null ) { - return $this->mix( $this->rgb( 0, 0, 0 ), $color, $amount ); - } - - public function extract( $values, $index ) { - $index = (int)$index->value - 1; // (1-based index) - // handle non-array values as an array of length 1 - // return 'undefined' if index is invalid - if ( property_exists( $values, 'value' ) && is_array( $values->value ) ) { - if ( isset( $values->value[$index] ) ) { - return $values->value[$index]; - } - return null; - - } elseif ( (int)$index === 0 ) { - return $values; - } - - return null; - } - - public function length( $values ) { - $n = ( property_exists( $values, 'value' ) && is_array( $values->value ) ) ? count( $values->value ) : 1; - return new Less_Tree_Dimension( $n ); - } - - public function datauri( $mimetypeNode, $filePathNode = null ) { - $filePath = ( $filePathNode ? $filePathNode->value : null ); - $mimetype = $mimetypeNode->value; - - $args = 2; - if ( !$filePath ) { - $filePath = $mimetype; - $args = 1; - } - - $filePath = str_replace( '\\', '/', $filePath ); - if ( Less_Environment::isPathRelative( $filePath ) ) { - - if ( Less_Parser::$options['relativeUrls'] ) { - $temp = $this->currentFileInfo['currentDirectory']; - } else { - $temp = $this->currentFileInfo['entryPath']; - } - - if ( !empty( $temp ) ) { - $filePath = Less_Environment::normalizePath( rtrim( $temp, '/' ).'/'.$filePath ); - } - - } - - // detect the mimetype if not given - if ( $args < 2 ) { - - /* incomplete - $mime = require('mime'); - mimetype = mime.lookup(path); - - // use base 64 unless it's an ASCII or UTF-8 format - var charset = mime.charsets.lookup(mimetype); - useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; - if (useBase64) mimetype += ';base64'; - */ - - $mimetype = Less_Mime::lookup( $filePath ); - - $charset = Less_Mime::charsets_lookup( $mimetype ); - $useBase64 = !in_array( $charset, array( 'US-ASCII', 'UTF-8' ) ); - if ( $useBase64 ) { $mimetype .= ';base64'; - } - - } else { - $useBase64 = preg_match( '/;base64$/', $mimetype ); - } - - if ( file_exists( $filePath ) ) { - $buf = @file_get_contents( $filePath ); - } else { - $buf = false; - } - - // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded - // and the --ieCompat flag is enabled, return a normal url() instead. - $DATA_URI_MAX_KB = 32; - $fileSizeInKB = round( strlen( $buf ) / 1024 ); - if ( $fileSizeInKB >= $DATA_URI_MAX_KB ) { - $url = new Less_Tree_Url( ( $filePathNode ? $filePathNode : $mimetypeNode ), $this->currentFileInfo ); - return $url->compile( $this ); - } - - if ( $buf ) { - $buf = $useBase64 ? base64_encode( $buf ) : rawurlencode( $buf ); - $filePath = '"data:' . $mimetype . ',' . $buf . '"'; - } - - return new Less_Tree_Url( new Less_Tree_Anonymous( $filePath ) ); - } - - // svg-gradient - public function svggradient( $direction ) { - $throw_message = 'svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]'; - $arguments = func_get_args(); - - if ( count( $arguments ) < 3 ) { - throw new Less_Exception_Compiler( $throw_message ); - } - - $stops = array_slice( $arguments, 1 ); - $gradientType = 'linear'; - $rectangleDimension = 'x="0" y="0" width="1" height="1"'; - $useBase64 = true; - $directionValue = $direction->toCSS(); - - switch ( $directionValue ) { - case "to bottom": - $gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; - break; - case "to right": - $gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; - break; - case "to bottom right": - $gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; - break; - case "to top right": - $gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; - break; - case "ellipse": - case "ellipse at center": - $gradientType = "radial"; - $gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; - $rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; - break; - default: - throw new Less_Exception_Compiler( "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" ); - } - - $returner = '' . - '' . - '<' . $gradientType . 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' . $gradientDirectionSvg . '>'; - - for ( $i = 0; $i < count( $stops ); $i++ ) { - if ( is_object( $stops[$i] ) && property_exists( $stops[$i], 'value' ) ) { - $color = $stops[$i]->value[0]; - $position = $stops[$i]->value[1]; - } else { - $color = $stops[$i]; - $position = null; - } - - if ( !( $color instanceof Less_Tree_Color ) || ( !( ( $i === 0 || $i + 1 === count( $stops ) ) && $position === null ) && !( $position instanceof Less_Tree_Dimension ) ) ) { - throw new Less_Exception_Compiler( $throw_message ); - } - if ( $position ) { - $positionValue = $position->toCSS(); - } elseif ( $i === 0 ) { - $positionValue = '0%'; - } else { - $positionValue = '100%'; - } - $alpha = $color->alpha; - $returner .= ''; - } - - $returner .= ''; - - if ( $useBase64 ) { - $returner = "'data:image/svg+xml;base64,".base64_encode( $returner )."'"; - } else { - $returner = "'data:image/svg+xml,".$returner."'"; - } - - return new Less_Tree_URL( new Less_Tree_Anonymous( $returner ) ); - } - - /** - * Php version of javascript's `encodeURIComponent` function - * - * @param string $string The string to encode - * @return string The encoded string - */ - public static function encodeURIComponent( $string ) { - $revert = array( '%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')' ); - return strtr( rawurlencode( $string ), $revert ); - } - - // Color Blending - // ref: http://www.w3.org/TR/compositing-1 - - public function colorBlend( $mode, $color1, $color2 ) { - $ab = $color1->alpha; // backdrop - $as = $color2->alpha; // source - $r = array(); // result - - $ar = $as + $ab * ( 1 - $as ); - for ( $i = 0; $i < 3; $i++ ) { - $cb = $color1->rgb[$i] / 255; - $cs = $color2->rgb[$i] / 255; - $cr = call_user_func( $mode, $cb, $cs ); - if ( $ar ) { - $cr = ( $as * $cs + $ab * ( $cb - $as * ( $cb + $cs - $cr ) ) ) / $ar; - } - $r[$i] = $cr * 255; - } - - return new Less_Tree_Color( $r, $ar ); - } - - public function multiply( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to multiply must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to multiply must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendMultiply' ), $color1, $color2 ); - } - - private function colorBlendMultiply( $cb, $cs ) { - return $cb * $cs; - } - - public function screen( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to screen must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to screen must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendScreen' ), $color1, $color2 ); - } - - private function colorBlendScreen( $cb, $cs ) { - return $cb + $cs - $cb * $cs; - } - - public function overlay( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to overlay must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to overlay must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendOverlay' ), $color1, $color2 ); - } - - private function colorBlendOverlay( $cb, $cs ) { - $cb *= 2; - return ( $cb <= 1 ) - ? $this->colorBlendMultiply( $cb, $cs ) - : $this->colorBlendScreen( $cb - 1, $cs ); - } - - public function softlight( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to softlight must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to softlight must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendSoftlight' ), $color1, $color2 ); - } - - private function colorBlendSoftlight( $cb, $cs ) { - $d = 1; - $e = $cb; - if ( $cs > 0.5 ) { - $e = 1; - $d = ( $cb > 0.25 ) ? sqrt( $cb ) - : ( ( 16 * $cb - 12 ) * $cb + 4 ) * $cb; - } - return $cb - ( 1 - 2 * $cs ) * $e * ( $d - $cb ); - } - - public function hardlight( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to hardlight must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to hardlight must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendHardlight' ), $color1, $color2 ); - } - - private function colorBlendHardlight( $cb, $cs ) { - return $this->colorBlendOverlay( $cs, $cb ); - } - - public function difference( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to difference must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to difference must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendDifference' ), $color1, $color2 ); - } - - private function colorBlendDifference( $cb, $cs ) { - return abs( $cb - $cs ); - } - - public function exclusion( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to exclusion must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to exclusion must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendExclusion' ), $color1, $color2 ); - } - - private function colorBlendExclusion( $cb, $cs ) { - return $cb + $cs - 2 * $cb * $cs; - } - - public function average( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to average must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to average must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendAverage' ), $color1, $color2 ); - } - - // non-w3c functions: - public function colorBlendAverage( $cb, $cs ) { - return ( $cb + $cs ) / 2; - } - - public function negation( $color1 = null, $color2 = null ) { - if ( !$color1 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The first argument to negation must be a color' . ( $color1 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - if ( !$color2 instanceof Less_Tree_Color ) { - throw new Less_Exception_Compiler( 'The second argument to negation must be a color' . ( $color2 instanceof Less_Tree_Expression ? ' (did you forgot commas?)' : '' ) ); - } - - return $this->colorBlend( array( $this,'colorBlendNegation' ), $color1, $color2 ); - } - - public function colorBlendNegation( $cb, $cs ) { - return 1 - abs( $cb + $cs - 1 ); - } - - // ~ End of Color Blending - -} diff --git a/less.php/lib/Less/Less.php.combine b/less.php/lib/Less/Less.php.combine deleted file mode 100755 index d63cc78..0000000 --- a/less.php/lib/Less/Less.php.combine +++ /dev/null @@ -1,17 +0,0 @@ - -./Parser.php -./Colors.php -./Environment.php -./Functions.php -./Mime.php -./Tree.php -./Output.php -./Visitor.php -./VisitorReplacing.php -./Configurable.php -./Tree -./Visitor -./Exception/Parser.php -./Exception/ -./Output -./SourceMap diff --git a/less.php/lib/Less/Mime.php b/less.php/lib/Less/Mime.php deleted file mode 100755 index b4723f9..0000000 --- a/less.php/lib/Less/Mime.php +++ /dev/null @@ -1,41 +0,0 @@ - 'text/html', - '.html' => 'text/html', - '.gif' => 'image/gif', - '.jpg' => 'image/jpeg', - '.jpeg' => 'image/jpeg', - '.png' => 'image/png', - '.ttf' => 'application/x-font-ttf', - '.otf' => 'application/x-font-otf', - '.eot' => 'application/vnd.ms-fontobject', - '.woff' => 'application/x-font-woff', - '.svg' => 'image/svg+xml', - ); - - public static function lookup( $filepath ) { - $parts = explode( '.', $filepath ); - $ext = '.'.strtolower( array_pop( $parts ) ); - - if ( !isset( self::$_types[$ext] ) ) { - return null; - } - return self::$_types[$ext]; - } - - public static function charsets_lookup( $type = null ) { - // assumes all text types are UTF-8 - return $type && preg_match( '/^text\//', $type ) ? 'UTF-8' : ''; - } -} diff --git a/less.php/lib/Less/Output.php b/less.php/lib/Less/Output.php deleted file mode 100755 index 8f7dd61..0000000 --- a/less.php/lib/Less/Output.php +++ /dev/null @@ -1,48 +0,0 @@ -strs[] = $chunk; - } - - /** - * Is the output empty? - * - * @return boolean - */ - public function isEmpty() { - return count( $this->strs ) === 0; - } - - /** - * Converts the output to string - * - * @return string - */ - public function toString() { - return implode( '', $this->strs ); - } - -} diff --git a/less.php/lib/Less/Output/Mapped.php b/less.php/lib/Less/Output/Mapped.php deleted file mode 100755 index e486c98..0000000 --- a/less.php/lib/Less/Output/Mapped.php +++ /dev/null @@ -1,119 +0,0 @@ -contentsMap = $contentsMap; - $this->generator = $generator; - } - - /** - * Adds a chunk to the stack - * The $index for less.php may be different from less.js since less.php does not chunkify inputs - * - * @param string $chunk - * @param string $fileInfo - * @param integer $index - * @param mixed $mapLines - */ - public function add( $chunk, $fileInfo = null, $index = 0, $mapLines = null ) { - // ignore adding empty strings - if ( $chunk === '' ) { - return; - } - - $sourceLines = array(); - $sourceColumns = ' '; - - if ( $fileInfo ) { - - $url = $fileInfo['currentUri']; - - if ( isset( $this->contentsMap[$url] ) ) { - $inputSource = substr( $this->contentsMap[$url], 0, $index ); - $sourceLines = explode( "\n", $inputSource ); - $sourceColumns = end( $sourceLines ); - } else { - throw new Exception( 'Filename '.$url.' not in contentsMap' ); - } - - } - - $lines = explode( "\n", $chunk ); - $columns = end( $lines ); - - if ( $fileInfo ) { - - if ( !$mapLines ) { - $this->generator->addMapping( - $this->lineNumber + 1, // generated_line - $this->column, // generated_column - count( $sourceLines ), // original_line - strlen( $sourceColumns ), // original_column - $fileInfo - ); - } else { - for ( $i = 0, $count = count( $lines ); $i < $count; $i++ ) { - $this->generator->addMapping( - $this->lineNumber + $i + 1, // generated_line - $i === 0 ? $this->column : 0, // generated_column - count( $sourceLines ) + $i, // original_line - $i === 0 ? strlen( $sourceColumns ) : 0, // original_column - $fileInfo - ); - } - } - } - - if ( count( $lines ) === 1 ) { - $this->column += strlen( $columns ); - } else { - $this->lineNumber += count( $lines ) - 1; - $this->column = strlen( $columns ); - } - - // add only chunk - parent::add( $chunk ); - } - -} diff --git a/less.php/lib/Less/Parser.php b/less.php/lib/Less/Parser.php deleted file mode 100755 index 36e0b3e..0000000 --- a/less.php/lib/Less/Parser.php +++ /dev/null @@ -1,2691 +0,0 @@ - false, // option - whether to compress - 'strictUnits' => false, // whether units need to evaluate correctly - 'strictMath' => false, // whether math has to be within parenthesis - 'relativeUrls' => true, // option - whether to adjust URL's to be relative - 'urlArgs' => '', // whether to add args into url tokens - 'numPrecision' => 8, - - 'import_dirs' => array(), - 'import_callback' => null, - 'cache_dir' => null, - 'cache_method' => 'php', // false, 'serialize', 'php', 'var_export', 'callback'; - 'cache_callback_get' => null, - 'cache_callback_set' => null, - - 'sourceMap' => false, // whether to output a source map - 'sourceMapBasepath' => null, - 'sourceMapWriteTo' => null, - 'sourceMapURL' => null, - - 'indentation' => ' ', - - 'plugins' => array(), - - ); - - public static $options = array(); - - private $input; // Less input string - private $input_len; // input string length - private $pos; // current index in `input` - private $saveStack = array(); // holds state for backtracking - private $furthest; - private $mb_internal_encoding = ''; // for remember exists value of mbstring.internal_encoding - - /** - * @var Less_Environment - */ - private $env; - - protected $rules = array(); - - private static $imports = array(); - - public static $has_extends = false; - - public static $next_id = 0; - - /** - * Filename to contents of all parsed the files - * - * @var array - */ - public static $contentsMap = array(); - - /** - * @param Less_Environment|array|null $env - */ - public function __construct( $env = null ) { - // Top parser on an import tree must be sure there is one "env" - // which will then be passed around by reference. - if ( $env instanceof Less_Environment ) { - $this->env = $env; - } else { - $this->SetOptions( Less_Parser::$default_options ); - $this->Reset( $env ); - } - - // mbstring.func_overload > 1 bugfix - // The encoding value must be set for each source file, - // therefore, to conserve resources and improve the speed of this design is taken here - if ( ini_get( 'mbstring.func_overload' ) ) { - $this->mb_internal_encoding = ini_get( 'mbstring.internal_encoding' ); - @ini_set( 'mbstring.internal_encoding', 'ascii' ); - } - - } - - /** - * Reset the parser state completely - * - */ - public function Reset( $options = null ) { - $this->rules = array(); - self::$imports = array(); - self::$has_extends = false; - self::$imports = array(); - self::$contentsMap = array(); - - $this->env = new Less_Environment( $options ); - - // set new options - if ( is_array( $options ) ) { - $this->SetOptions( Less_Parser::$default_options ); - $this->SetOptions( $options ); - } - - $this->env->Init(); - } - - /** - * Set one or more compiler options - * options: import_dirs, cache_dir, cache_method - * - */ - public function SetOptions( $options ) { - foreach ( $options as $option => $value ) { - $this->SetOption( $option, $value ); - } - } - - /** - * Set one compiler option - * - */ - public function SetOption( $option, $value ) { - switch ( $option ) { - - case 'import_dirs': - $this->SetImportDirs( $value ); - return; - - case 'cache_dir': - if ( is_string( $value ) ) { - Less_Cache::SetCacheDir( $value ); - Less_Cache::CheckCacheDir(); - } - return; - } - - Less_Parser::$options[$option] = $value; - } - - /** - * Registers a new custom function - * - * @param string $name function name - * @param callable $callback callback - */ - public function registerFunction( $name, $callback ) { - $this->env->functions[$name] = $callback; - } - - /** - * Removed an already registered function - * - * @param string $name function name - */ - public function unregisterFunction( $name ) { - if ( isset( $this->env->functions[$name] ) ) - unset( $this->env->functions[$name] ); - } - - /** - * Get the current css buffer - * - * @return string - */ - public function getCss() { - $precision = ini_get( 'precision' ); - @ini_set( 'precision', 16 ); - $locale = setlocale( LC_NUMERIC, 0 ); - setlocale( LC_NUMERIC, "C" ); - - try { - - $root = new Less_Tree_Ruleset( array(), $this->rules ); - $root->root = true; - $root->firstRoot = true; - - $this->PreVisitors( $root ); - - self::$has_extends = false; - $evaldRoot = $root->compile( $this->env ); - - $this->PostVisitors( $evaldRoot ); - - if ( Less_Parser::$options['sourceMap'] ) { - $generator = new Less_SourceMap_Generator( $evaldRoot, Less_Parser::$contentsMap, Less_Parser::$options ); - // will also save file - // FIXME: should happen somewhere else? - $css = $generator->generateCSS(); - } else { - $css = $evaldRoot->toCSS(); - } - - if ( Less_Parser::$options['compress'] ) { - $css = preg_replace( '/(^(\s)+)|((\s)+$)/', '', $css ); - } - - } catch ( Exception $exc ) { - // Intentional fall-through so we can reset environment - } - - // reset php settings - @ini_set( 'precision', $precision ); - setlocale( LC_NUMERIC, $locale ); - - // If you previously defined $this->mb_internal_encoding - // is required to return the encoding as it was before - if ( $this->mb_internal_encoding != '' ) { - @ini_set( "mbstring.internal_encoding", $this->mb_internal_encoding ); - $this->mb_internal_encoding = ''; - } - - // Rethrow exception after we handled resetting the environment - if ( !empty( $exc ) ) { - throw $exc; - } - - return $css; - } - - public function findValueOf( $varName ) { - foreach ( $this->rules as $rule ) { - if ( isset( $rule->variable ) && ( $rule->variable == true ) && ( str_replace( "@", "", $rule->name ) == $varName ) ) { - return $this->getVariableValue( $rule ); - } - } - return null; - } - - /** - * - * this function gets the private rules variable and returns an array of the found variables - * it uses a helper method getVariableValue() that contains the logic ot fetch the value from the rule object - * - * @return array - */ - public function getVariables() { - $variables = array(); - - $not_variable_type = array( - 'Comment', // this include less comments ( // ) and css comments (/* */) - 'Import', // do not search variables in included files @import - 'Ruleset', // selectors (.someclass, #someid, …) - 'Operation', // - ); - - // @TODO run compilation if not runned yet - foreach ( $this->rules as $key => $rule ) { - if ( in_array( $rule->type, $not_variable_type ) ) { - continue; - } - - // Note: it seems rule->type is always Rule when variable = true - if ( $rule->type == 'Rule' && $rule->variable ) { - $variables[$rule->name] = $this->getVariableValue( $rule ); - } else { - if ( $rule->type == 'Comment' ) { - $variables[] = $this->getVariableValue( $rule ); - } - } - } - return $variables; - } - - public function findVarByName( $var_name ) { - foreach ( $this->rules as $rule ) { - if ( isset( $rule->variable ) && ( $rule->variable == true ) ) { - if ( $rule->name == $var_name ) { - return $this->getVariableValue( $rule ); - } - } - } - return null; - } - - /** - * - * This method gets the value of the less variable from the rules object. - * Since the objects vary here we add the logic for extracting the css/less value. - * - * @param $var - * - * @return bool|string - */ - private function getVariableValue( $var ) { - if ( !is_a( $var, 'Less_Tree' ) ) { - throw new Exception( 'var is not a Less_Tree object' ); - } - - switch ( $var->type ) { - case 'Color': - return $this->rgb2html( $var->rgb ); - case 'Unit': - return $var->value. $var->unit->numerator[0]; - case 'Variable': - return $this->findVarByName( $var->name ); - case 'Keyword': - return $var->value; - case 'Rule': - return $this->getVariableValue( $var->value ); - case 'Value': - $value = ''; - foreach ( $var->value as $sub_value ) { - $value .= $this->getVariableValue( $sub_value ).' '; - } - return $value; - case 'Quoted': - return $var->quote.$var->value.$var->quote; - case 'Dimension': - $value = $var->value; - if ( $var->unit && $var->unit->numerator ) { - $value .= $var->unit->numerator[0]; - } - return $value; - case 'Expression': - $value = ""; - foreach ( $var->value as $item ) { - $value .= $this->getVariableValue( $item )." "; - } - return $value; - case 'Operation': - throw new Exception( 'getVariables() require Less to be compiled. please use $parser->getCss() before calling getVariables()' ); - case 'Comment': - case 'Import': - case 'Ruleset': - default: - throw new Exception( "type missing in switch/case getVariableValue for ".$var->type ); - } - return false; - } - - private function rgb2html( $r, $g = -1, $b = -1 ) { - if ( is_array( $r ) && sizeof( $r ) == 3 ) - list( $r, $g, $b ) = $r; - - $r = intval( $r ); $g = intval( $g ); - $b = intval( $b ); - - $r = dechex( $r < 0 ? 0 : ( $r > 255 ? 255 : $r ) ); - $g = dechex( $g < 0 ? 0 : ( $g > 255 ? 255 : $g ) ); - $b = dechex( $b < 0 ? 0 : ( $b > 255 ? 255 : $b ) ); - - $color = ( strlen( $r ) < 2 ? '0' : '' ).$r; - $color .= ( strlen( $g ) < 2 ? '0' : '' ).$g; - $color .= ( strlen( $b ) < 2 ? '0' : '' ).$b; - return '#'.$color; - } - - /** - * Run pre-compile visitors - * - */ - private function PreVisitors( $root ) { - if ( Less_Parser::$options['plugins'] ) { - foreach ( Less_Parser::$options['plugins'] as $plugin ) { - if ( !empty( $plugin->isPreEvalVisitor ) ) { - $plugin->run( $root ); - } - } - } - } - - /** - * Run post-compile visitors - * - */ - private function PostVisitors( $evaldRoot ) { - $visitors = array(); - $visitors[] = new Less_Visitor_joinSelector(); - if ( self::$has_extends ) { - $visitors[] = new Less_Visitor_processExtends(); - } - $visitors[] = new Less_Visitor_toCSS(); - - if ( Less_Parser::$options['plugins'] ) { - foreach ( Less_Parser::$options['plugins'] as $plugin ) { - if ( property_exists( $plugin, 'isPreEvalVisitor' ) && $plugin->isPreEvalVisitor ) { - continue; - } - - if ( property_exists( $plugin, 'isPreVisitor' ) && $plugin->isPreVisitor ) { - array_unshift( $visitors, $plugin ); - } else { - $visitors[] = $plugin; - } - } - } - - for ( $i = 0; $i < count( $visitors ); $i++ ) { - $visitors[$i]->run( $evaldRoot ); - } - - } - - /** - * Parse a Less string into css - * - * @param string $str The string to convert - * @param string $uri_root The url of the file - * @return Less_Tree_Ruleset|Less_Parser - */ - public function parse( $str, $file_uri = null ) { - if ( !$file_uri ) { - $uri_root = ''; - $filename = 'anonymous-file-'.Less_Parser::$next_id++.'.less'; - } else { - $file_uri = self::WinPath( $file_uri ); - $filename = $file_uri; - $uri_root = dirname( $file_uri ); - } - - $previousFileInfo = $this->env->currentFileInfo; - $uri_root = self::WinPath( $uri_root ); - $this->SetFileInfo( $filename, $uri_root ); - - $this->input = $str; - $this->_parse(); - - if ( $previousFileInfo ) { - $this->env->currentFileInfo = $previousFileInfo; - } - - return $this; - } - - /** - * Parse a Less string from a given file - * - * @throws Less_Exception_Parser - * @param string $filename The file to parse - * @param string $uri_root The url of the file - * @param bool $returnRoot Indicates whether the return value should be a css string a root node - * @return Less_Tree_Ruleset|Less_Parser - */ - public function parseFile( $filename, $uri_root = '', $returnRoot = false ) { - if ( !file_exists( $filename ) ) { - $this->Error( sprintf( 'File `%s` not found.', $filename ) ); - } - - // fix uri_root? - // Instead of The mixture of file path for the first argument and directory path for the second argument has bee - if ( !$returnRoot && !empty( $uri_root ) && basename( $uri_root ) == basename( $filename ) ) { - $uri_root = dirname( $uri_root ); - } - - $previousFileInfo = $this->env->currentFileInfo; - - if ( $filename ) { - $filename = self::AbsPath( $filename, true ); - } - $uri_root = self::WinPath( $uri_root ); - - $this->SetFileInfo( $filename, $uri_root ); - - self::AddParsedFile( $filename ); - - if ( $returnRoot ) { - $rules = $this->GetRules( $filename ); - $return = new Less_Tree_Ruleset( array(), $rules ); - } else { - $this->_parse( $filename ); - $return = $this; - } - - if ( $previousFileInfo ) { - $this->env->currentFileInfo = $previousFileInfo; - } - - return $return; - } - - /** - * Allows a user to set variables values - * @param array $vars - * @return Less_Parser - */ - public function ModifyVars( $vars ) { - $this->input = Less_Parser::serializeVars( $vars ); - $this->_parse(); - - return $this; - } - - /** - * @param string $filename - */ - public function SetFileInfo( $filename, $uri_root = '' ) { - $filename = Less_Environment::normalizePath( $filename ); - $dirname = preg_replace( '/[^\/\\\\]*$/', '', $filename ); - - if ( !empty( $uri_root ) ) { - $uri_root = rtrim( $uri_root, '/' ).'/'; - } - - $currentFileInfo = array(); - - // entry info - if ( isset( $this->env->currentFileInfo ) ) { - $currentFileInfo['entryPath'] = $this->env->currentFileInfo['entryPath']; - $currentFileInfo['entryUri'] = $this->env->currentFileInfo['entryUri']; - $currentFileInfo['rootpath'] = $this->env->currentFileInfo['rootpath']; - - } else { - $currentFileInfo['entryPath'] = $dirname; - $currentFileInfo['entryUri'] = $uri_root; - $currentFileInfo['rootpath'] = $dirname; - } - - $currentFileInfo['currentDirectory'] = $dirname; - $currentFileInfo['currentUri'] = $uri_root.basename( $filename ); - $currentFileInfo['filename'] = $filename; - $currentFileInfo['uri_root'] = $uri_root; - - // inherit reference - if ( isset( $this->env->currentFileInfo['reference'] ) && $this->env->currentFileInfo['reference'] ) { - $currentFileInfo['reference'] = true; - } - - $this->env->currentFileInfo = $currentFileInfo; - } - - /** - * @deprecated 1.5.1.2 - * - */ - public function SetCacheDir( $dir ) { - if ( !file_exists( $dir ) ) { - if ( mkdir( $dir ) ) { - return true; - } - throw new Less_Exception_Parser( 'Less.php cache directory couldn\'t be created: '.$dir ); - - } elseif ( !is_dir( $dir ) ) { - throw new Less_Exception_Parser( 'Less.php cache directory doesn\'t exist: '.$dir ); - - } elseif ( !is_writable( $dir ) ) { - throw new Less_Exception_Parser( 'Less.php cache directory isn\'t writable: '.$dir ); - - } else { - $dir = self::WinPath( $dir ); - Less_Cache::$cache_dir = rtrim( $dir, '/' ).'/'; - return true; - } - } - - /** - * Set a list of directories or callbacks the parser should use for determining import paths - * - * @param array $dirs - */ - public function SetImportDirs( $dirs ) { - Less_Parser::$options['import_dirs'] = array(); - - foreach ( $dirs as $path => $uri_root ) { - - $path = self::WinPath( $path ); - if ( !empty( $path ) ) { - $path = rtrim( $path, '/' ).'/'; - } - - if ( !is_callable( $uri_root ) ) { - $uri_root = self::WinPath( $uri_root ); - if ( !empty( $uri_root ) ) { - $uri_root = rtrim( $uri_root, '/' ).'/'; - } - } - - Less_Parser::$options['import_dirs'][$path] = $uri_root; - } - } - - /** - * @param string $file_path - */ - private function _parse( $file_path = null ) { - $this->rules = array_merge( $this->rules, $this->GetRules( $file_path ) ); - } - - /** - * Return the results of parsePrimary for $file_path - * Use cache and save cached results if possible - * - * @param string|null $file_path - */ - private function GetRules( $file_path ) { - $this->SetInput( $file_path ); - - $cache_file = $this->CacheFile( $file_path ); - if ( $cache_file ) { - if ( Less_Parser::$options['cache_method'] == 'callback' ) { - if ( is_callable( Less_Parser::$options['cache_callback_get'] ) ) { - $cache = call_user_func_array( - Less_Parser::$options['cache_callback_get'], - array( $this, $file_path, $cache_file ) - ); - - if ( $cache ) { - $this->UnsetInput(); - return $cache; - } - } - - } elseif ( file_exists( $cache_file ) ) { - switch ( Less_Parser::$options['cache_method'] ) { - - // Using serialize - // Faster but uses more memory - case 'serialize': - $cache = unserialize( file_get_contents( $cache_file ) ); - if ( $cache ) { - touch( $cache_file ); - $this->UnsetInput(); - return $cache; - } - break; - - // Using generated php code - case 'var_export': - case 'php': - $this->UnsetInput(); - return include $cache_file; - } - } - } - - $rules = $this->parsePrimary(); - - if ( $this->pos < $this->input_len ) { - throw new Less_Exception_Chunk( $this->input, null, $this->furthest, $this->env->currentFileInfo ); - } - - $this->UnsetInput(); - - // save the cache - if ( $cache_file ) { - if ( Less_Parser::$options['cache_method'] == 'callback' ) { - if ( is_callable( Less_Parser::$options['cache_callback_set'] ) ) { - call_user_func_array( - Less_Parser::$options['cache_callback_set'], - array( $this, $file_path, $cache_file, $rules ) - ); - } - - } else { - // msg('write cache file'); - switch ( Less_Parser::$options['cache_method'] ) { - case 'serialize': - file_put_contents( $cache_file, serialize( $rules ) ); - break; - case 'php': - file_put_contents( $cache_file, '' ); - break; - case 'var_export': - // Requires __set_state() - file_put_contents( $cache_file, '' ); - break; - } - - Less_Cache::CleanCache(); - } - } - - return $rules; - } - - /** - * Set up the input buffer - * - */ - public function SetInput( $file_path ) { - if ( $file_path ) { - $this->input = file_get_contents( $file_path ); - } - - $this->pos = $this->furthest = 0; - - // Remove potential UTF Byte Order Mark - $this->input = preg_replace( '/\\G\xEF\xBB\xBF/', '', $this->input ); - $this->input_len = strlen( $this->input ); - - if ( Less_Parser::$options['sourceMap'] && $this->env->currentFileInfo ) { - $uri = $this->env->currentFileInfo['currentUri']; - Less_Parser::$contentsMap[$uri] = $this->input; - } - - } - - /** - * Free up some memory - * - */ - public function UnsetInput() { - unset( $this->input, $this->pos, $this->input_len, $this->furthest ); - $this->saveStack = array(); - } - - public function CacheFile( $file_path ) { - if ( $file_path && $this->CacheEnabled() ) { - - $env = get_object_vars( $this->env ); - unset( $env['frames'] ); - - $parts = array(); - $parts[] = $file_path; - $parts[] = filesize( $file_path ); - $parts[] = filemtime( $file_path ); - $parts[] = $env; - $parts[] = Less_Version::cache_version; - $parts[] = Less_Parser::$options['cache_method']; - return Less_Cache::$cache_dir . Less_Cache::$prefix . base_convert( sha1( json_encode( $parts ) ), 16, 36 ) . '.lesscache'; - } - } - - static function AddParsedFile( $file ) { - self::$imports[] = $file; - } - - static function AllParsedFiles() { - return self::$imports; - } - - /** - * @param string $file - */ - static function FileParsed( $file ) { - return in_array( $file, self::$imports ); - } - - function save() { - $this->saveStack[] = $this->pos; - } - - private function restore() { - $this->pos = array_pop( $this->saveStack ); - } - - private function forget() { - array_pop( $this->saveStack ); - } - - /** - * Determine if the character at the specified offset from the current position is a white space. - * - * @param int $offset - * - * @return bool - */ - private function isWhitespace( $offset = 0 ) { - return strpos( " \t\n\r\v\f", $this->input[$this->pos + $offset] ) !== false; - } - - /** - * Parse from a token, regexp or string, and move forward if match - * - * @param array $toks - * @return array - */ - private function match( $toks ) { - // The match is confirmed, add the match length to `this::pos`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - - foreach ( $toks as $tok ) { - - $char = $tok[0]; - - if ( $char === '/' ) { - $match = $this->MatchReg( $tok ); - - if ( $match ) { - return count( $match ) === 1 ? $match[0] : $match; - } - - } elseif ( $char === '#' ) { - $match = $this->MatchChar( $tok[1] ); - - } else { - // Non-terminal, match using a function call - $match = $this->$tok(); - - } - - if ( $match ) { - return $match; - } - } - } - - /** - * @param string[] $toks - * - * @return string - */ - private function MatchFuncs( $toks ) { - if ( $this->pos < $this->input_len ) { - foreach ( $toks as $tok ) { - $match = $this->$tok(); - if ( $match ) { - return $match; - } - } - } - - } - - // Match a single character in the input, - private function MatchChar( $tok ) { - if ( ( $this->pos < $this->input_len ) && ( $this->input[$this->pos] === $tok ) ) { - $this->skipWhitespace( 1 ); - return $tok; - } - } - - // Match a regexp from the current start point - private function MatchReg( $tok ) { - if ( preg_match( $tok, $this->input, $match, 0, $this->pos ) ) { - $this->skipWhitespace( strlen( $match[0] ) ); - return $match; - } - } - - /** - * Same as match(), but don't change the state of the parser, - * just return the match. - * - * @param string $tok - * @return integer - */ - public function PeekReg( $tok ) { - return preg_match( $tok, $this->input, $match, 0, $this->pos ); - } - - /** - * @param string $tok - */ - public function PeekChar( $tok ) { - // return ($this->input[$this->pos] === $tok ); - return ( $this->pos < $this->input_len ) && ( $this->input[$this->pos] === $tok ); - } - - /** - * @param integer $length - */ - public function skipWhitespace( $length ) { - $this->pos += $length; - - for ( ; $this->pos < $this->input_len; $this->pos++ ) { - $c = $this->input[$this->pos]; - - if ( ( $c !== "\n" ) && ( $c !== "\r" ) && ( $c !== "\t" ) && ( $c !== ' ' ) ) { - break; - } - } - } - - /** - * @param string $tok - * @param string|null $msg - */ - public function expect( $tok, $msg = NULL ) { - $result = $this->match( array( $tok ) ); - if ( !$result ) { - $this->Error( $msg ? "Expected '" . $tok . "' got '" . $this->input[$this->pos] . "'" : $msg ); - } else { - return $result; - } - } - - /** - * @param string $tok - */ - public function expectChar( $tok, $msg = null ) { - $result = $this->MatchChar( $tok ); - if ( !$result ) { - $msg = $msg ? $msg : "Expected '" . $tok . "' got '" . $this->input[$this->pos] . "'"; - $this->Error( $msg ); - } else { - return $result; - } - } - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - private function parsePrimary() { - $root = array(); - - while ( true ) { - - if ( $this->pos >= $this->input_len ) { - break; - } - - $node = $this->parseExtend( true ); - if ( $node ) { - $root = array_merge( $root, $node ); - continue; - } - - // $node = $this->MatchFuncs( array( 'parseMixinDefinition', 'parseRule', 'parseRuleset', 'parseMixinCall', 'parseComment', 'parseDirective')); - $node = $this->MatchFuncs( array( 'parseMixinDefinition', 'parseNameValue', 'parseRule', 'parseRuleset', 'parseMixinCall', 'parseComment', 'parseRulesetCall', 'parseDirective' ) ); - - if ( $node ) { - $root[] = $node; - } elseif ( !$this->MatchReg( '/\\G[\s\n;]+/' ) ) { - break; - } - - if ( $this->PeekChar( '}' ) ) { - break; - } - } - - return $root; - } - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - private function parseComment() { - if ( $this->input[$this->pos] !== '/' ) { - return; - } - - if ( $this->input[$this->pos + 1] === '/' ) { - $match = $this->MatchReg( '/\\G\/\/.*/' ); - return $this->NewObj4( 'Less_Tree_Comment', array( $match[0], true, $this->pos, $this->env->currentFileInfo ) ); - } - - // $comment = $this->MatchReg('/\\G\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/'); - $comment = $this->MatchReg( '/\\G\/\*(?s).*?\*+\/\n?/' );// not the same as less.js to prevent fatal errors - if ( $comment ) { - return $this->NewObj4( 'Less_Tree_Comment', array( $comment[0], false, $this->pos, $this->env->currentFileInfo ) ); - } - } - - private function parseComments() { - $comments = array(); - - while ( $this->pos < $this->input_len ) { - $comment = $this->parseComment(); - if ( !$comment ) { - break; - } - - $comments[] = $comment; - } - - return $comments; - } - - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - private function parseEntitiesQuoted() { - $j = $this->pos; - $e = false; - $index = $this->pos; - - if ( $this->input[$this->pos] === '~' ) { - $j++; - $e = true; // Escaped strings - } - - $char = $this->input[$j]; - if ( $char !== '"' && $char !== "'" ) { - return; - } - - if ( $e ) { - $this->MatchChar( '~' ); - } - - $matched = $this->MatchQuoted( $char, $j + 1 ); - if ( $matched === false ) { - return; - } - - $quoted = $char.$matched.$char; - return $this->NewObj5( 'Less_Tree_Quoted', array( $quoted, $matched, $e, $index, $this->env->currentFileInfo ) ); - } - - /** - * When PCRE JIT is enabled in php, regular expressions don't work for matching quoted strings - * - * $regex = '/\\G\'((?:[^\'\\\\\r\n]|\\\\.|\\\\\r\n|\\\\[\n\r\f])*)\'/'; - * $regex = '/\\G"((?:[^"\\\\\r\n]|\\\\.|\\\\\r\n|\\\\[\n\r\f])*)"/'; - * - */ - private function MatchQuoted( $quote_char, $i ) { - $matched = ''; - while ( $i < $this->input_len ) { - $c = $this->input[$i]; - - // escaped character - if ( $c === '\\' ) { - $matched .= $c . $this->input[$i + 1]; - $i += 2; - continue; - } - - if ( $c === $quote_char ) { - $this->pos = $i + 1; - $this->skipWhitespace( 0 ); - return $matched; - } - - if ( $c === "\r" || $c === "\n" ) { - return false; - } - - $i++; - $matched .= $c; - } - - return false; - } - - // - // A catch-all word, such as: - // - // black border-collapse - // - private function parseEntitiesKeyword() { - // $k = $this->MatchReg('/\\G[_A-Za-z-][_A-Za-z0-9-]*/'); - $k = $this->MatchReg( '/\\G%|\\G[_A-Za-z-][_A-Za-z0-9-]*/' ); - if ( $k ) { - $k = $k[0]; - $color = $this->fromKeyword( $k ); - if ( $color ) { - return $color; - } - return $this->NewObj1( 'Less_Tree_Keyword', $k ); - } - } - - // duplicate of Less_Tree_Color::FromKeyword - private function FromKeyword( $keyword ) { - $keyword = strtolower( $keyword ); - - if ( Less_Colors::hasOwnProperty( $keyword ) ) { - // detect named color - return $this->NewObj1( 'Less_Tree_Color', substr( Less_Colors::color( $keyword ), 1 ) ); - } - - if ( $keyword === 'transparent' ) { - return $this->NewObj3( 'Less_Tree_Color', array( array( 0, 0, 0 ), 0, true ) ); - } - } - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - private function parseEntitiesCall() { - $index = $this->pos; - - if ( !preg_match( '/\\G([\w-]+|%|progid:[\w\.]+)\(/', $this->input, $name, 0, $this->pos ) ) { - return; - } - $name = $name[1]; - $nameLC = strtolower( $name ); - - if ( $nameLC === 'url' ) { - return null; - } - - $this->pos += strlen( $name ); - - if ( $nameLC === 'alpha' ) { - $alpha_ret = $this->parseAlpha(); - if ( $alpha_ret ) { - return $alpha_ret; - } - } - - $this->MatchChar( '(' ); // Parse the '(' and consume whitespace. - - $args = $this->parseEntitiesArguments(); - - if ( !$this->MatchChar( ')' ) ) { - return; - } - - if ( $name ) { - return $this->NewObj4( 'Less_Tree_Call', array( $name, $args, $index, $this->env->currentFileInfo ) ); - } - } - - /** - * Parse a list of arguments - * - * @return array - */ - private function parseEntitiesArguments() { - $args = array(); - while ( true ) { - $arg = $this->MatchFuncs( array( 'parseEntitiesAssignment','parseExpression' ) ); - if ( !$arg ) { - break; - } - - $args[] = $arg; - if ( !$this->MatchChar( ',' ) ) { - break; - } - } - return $args; - } - - private function parseEntitiesLiteral() { - return $this->MatchFuncs( array( 'parseEntitiesDimension','parseEntitiesColor','parseEntitiesQuoted','parseUnicodeDescriptor' ) ); - } - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - private function parseEntitiesAssignment() { - $key = $this->MatchReg( '/\\G\w+(?=\s?=)/' ); - if ( !$key ) { - return; - } - - if ( !$this->MatchChar( '=' ) ) { - return; - } - - $value = $this->parseEntity(); - if ( $value ) { - return $this->NewObj2( 'Less_Tree_Assignment', array( $key[0], $value ) ); - } - } - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - private function parseEntitiesUrl() { - if ( $this->input[$this->pos] !== 'u' || !$this->matchReg( '/\\Gurl\(/' ) ) { - return; - } - - $value = $this->match( array( 'parseEntitiesQuoted','parseEntitiesVariable','/\\Gdata\:.*?[^\)]+/','/\\G(?:(?:\\\\[\(\)\'"])|[^\(\)\'"])+/' ) ); - if ( !$value ) { - $value = ''; - } - - $this->expectChar( ')' ); - - if ( isset( $value->value ) || $value instanceof Less_Tree_Variable ) { - return $this->NewObj2( 'Less_Tree_Url', array( $value, $this->env->currentFileInfo ) ); - } - - return $this->NewObj2( 'Less_Tree_Url', array( $this->NewObj1( 'Less_Tree_Anonymous', $value ), $this->env->currentFileInfo ) ); - } - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - private function parseEntitiesVariable() { - $index = $this->pos; - if ( $this->PeekChar( '@' ) && ( $name = $this->MatchReg( '/\\G@@?[\w-]+/' ) ) ) { - return $this->NewObj3( 'Less_Tree_Variable', array( $name[0], $index, $this->env->currentFileInfo ) ); - } - } - - // A variable entity using the protective {} e.g. @{var} - private function parseEntitiesVariableCurly() { - $index = $this->pos; - - if ( $this->input_len > ( $this->pos + 1 ) && $this->input[$this->pos] === '@' && ( $curly = $this->MatchReg( '/\\G@\{([\w-]+)\}/' ) ) ) { - return $this->NewObj3( 'Less_Tree_Variable', array( '@'.$curly[1], $index, $this->env->currentFileInfo ) ); - } - } - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - private function parseEntitiesColor() { - if ( $this->PeekChar( '#' ) && ( $rgb = $this->MatchReg( '/\\G#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/' ) ) ) { - return $this->NewObj1( 'Less_Tree_Color', $rgb[1] ); - } - } - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - private function parseEntitiesDimension() { - $c = @ord( $this->input[$this->pos] ); - - // Is the first char of the dimension 0-9, '.', '+' or '-' - if ( ( $c > 57 || $c < 43 ) || $c === 47 || $c == 44 ) { - return; - } - - $value = $this->MatchReg( '/\\G([+-]?\d*\.?\d+)(%|[a-z]+)?/' ); - if ( $value ) { - - if ( isset( $value[2] ) ) { - return $this->NewObj2( 'Less_Tree_Dimension', array( $value[1],$value[2] ) ); - } - return $this->NewObj1( 'Less_Tree_Dimension', $value[1] ); - } - } - - // - // A unicode descriptor, as is used in unicode-range - // - // U+0?? or U+00A1-00A9 - // - function parseUnicodeDescriptor() { - $ud = $this->MatchReg( '/\\G(U\+[0-9a-fA-F?]+)(\-[0-9a-fA-F?]+)?/' ); - if ( $ud ) { - return $this->NewObj1( 'Less_Tree_UnicodeDescriptor', $ud[0] ); - } - } - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - private function parseEntitiesJavascript() { - $e = false; - $j = $this->pos; - if ( $this->input[$j] === '~' ) { - $j++; - $e = true; - } - if ( $this->input[$j] !== '`' ) { - return; - } - if ( $e ) { - $this->MatchChar( '~' ); - } - $str = $this->MatchReg( '/\\G`([^`]*)`/' ); - if ( $str ) { - return $this->NewObj3( 'Less_Tree_Javascript', array( $str[1], $this->pos, $e ) ); - } - } - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - private function parseVariable() { - if ( $this->PeekChar( '@' ) && ( $name = $this->MatchReg( '/\\G(@[\w-]+)\s*:/' ) ) ) { - return $name[1]; - } - } - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink(); - // - private function parseRulesetCall() { - if ( $this->input[$this->pos] === '@' && ( $name = $this->MatchReg( '/\\G(@[\w-]+)\s*\(\s*\)\s*;/' ) ) ) { - return $this->NewObj1( 'Less_Tree_RulesetCall', $name[1] ); - } - } - - // - // extend syntax - used to extend selectors - // - function parseExtend( $isRule = false ) { - $index = $this->pos; - $extendList = array(); - - if ( !$this->MatchReg( $isRule ? '/\\G&:extend\(/' : '/\\G:extend\(/' ) ) { return; - } - - do{ - $option = null; - $elements = array(); - while ( true ) { - $option = $this->MatchReg( '/\\G(all)(?=\s*(\)|,))/' ); - if ( $option ) { break; - } - $e = $this->parseElement(); - if ( !$e ) { break; - } - $elements[] = $e; - } - - if ( $option ) { - $option = $option[1]; - } - - $extendList[] = $this->NewObj3( 'Less_Tree_Extend', array( $this->NewObj1( 'Less_Tree_Selector', $elements ), $option, $index ) ); - - }while ( $this->MatchChar( "," ) ); - - $this->expect( '/\\G\)/' ); - - if ( $isRule ) { - $this->expect( '/\\G;/' ); - } - - return $extendList; - } - - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - private function parseMixinCall() { - $char = $this->input[$this->pos]; - if ( $char !== '.' && $char !== '#' ) { - return; - } - - $index = $this->pos; - $this->save(); // stop us absorbing part of an invalid selector - - $elements = $this->parseMixinCallElements(); - - if ( $elements ) { - - if ( $this->MatchChar( '(' ) ) { - $returned = $this->parseMixinArgs( true ); - $args = $returned['args']; - $this->expectChar( ')' ); - } else { - $args = array(); - } - - $important = $this->parseImportant(); - - if ( $this->parseEnd() ) { - $this->forget(); - return $this->NewObj5( 'Less_Tree_Mixin_Call', array( $elements, $args, $index, $this->env->currentFileInfo, $important ) ); - } - } - - $this->restore(); - } - - private function parseMixinCallElements() { - $elements = array(); - $c = null; - - while ( true ) { - $elemIndex = $this->pos; - $e = $this->MatchReg( '/\\G[#.](?:[\w-]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/' ); - if ( !$e ) { - break; - } - $elements[] = $this->NewObj4( 'Less_Tree_Element', array( $c, $e[0], $elemIndex, $this->env->currentFileInfo ) ); - $c = $this->MatchChar( '>' ); - } - - return $elements; - } - - /** - * @param boolean $isCall - */ - private function parseMixinArgs( $isCall ) { - $expressions = array(); - $argsSemiColon = array(); - $isSemiColonSeperated = null; - $argsComma = array(); - $expressionContainsNamed = null; - $name = null; - $returner = array( 'args' => array(), 'variadic' => false ); - - $this->save(); - - while ( true ) { - if ( $isCall ) { - $arg = $this->MatchFuncs( array( 'parseDetachedRuleset','parseExpression' ) ); - } else { - $this->parseComments(); - if ( $this->input[ $this->pos ] === '.' && $this->MatchReg( '/\\G\.{3}/' ) ) { - $returner['variadic'] = true; - if ( $this->MatchChar( ";" ) && !$isSemiColonSeperated ) { - $isSemiColonSeperated = true; - } - - if ( $isSemiColonSeperated ) { - $argsSemiColon[] = array( 'variadic' => true ); - } else { - $argsComma[] = array( 'variadic' => true ); - } - break; - } - $arg = $this->MatchFuncs( array( 'parseEntitiesVariable','parseEntitiesLiteral','parseEntitiesKeyword' ) ); - } - - if ( !$arg ) { - break; - } - - $nameLoop = null; - if ( $arg instanceof Less_Tree_Expression ) { - $arg->throwAwayComments(); - } - $value = $arg; - $val = null; - - if ( $isCall ) { - // Variable - if ( property_exists( $arg, 'value' ) && count( $arg->value ) == 1 ) { - $val = $arg->value[0]; - } - } else { - $val = $arg; - } - - if ( $val instanceof Less_Tree_Variable ) { - - if ( $this->MatchChar( ':' ) ) { - if ( $expressions ) { - if ( $isSemiColonSeperated ) { - $this->Error( 'Cannot mix ; and , as delimiter types' ); - } - $expressionContainsNamed = true; - } - - // we do not support setting a ruleset as a default variable - it doesn't make sense - // However if we do want to add it, there is nothing blocking it, just don't error - // and remove isCall dependency below - $value = null; - if ( $isCall ) { - $value = $this->parseDetachedRuleset(); - } - if ( !$value ) { - $value = $this->parseExpression(); - } - - if ( !$value ) { - if ( $isCall ) { - $this->Error( 'could not understand value for named argument' ); - } else { - $this->restore(); - $returner['args'] = array(); - return $returner; - } - } - - $nameLoop = ( $name = $val->name ); - } elseif ( !$isCall && $this->MatchReg( '/\\G\.{3}/' ) ) { - $returner['variadic'] = true; - if ( $this->MatchChar( ";" ) && !$isSemiColonSeperated ) { - $isSemiColonSeperated = true; - } - if ( $isSemiColonSeperated ) { - $argsSemiColon[] = array( 'name' => $arg->name, 'variadic' => true ); - } else { - $argsComma[] = array( 'name' => $arg->name, 'variadic' => true ); - } - break; - } elseif ( !$isCall ) { - $name = $nameLoop = $val->name; - $value = null; - } - } - - if ( $value ) { - $expressions[] = $value; - } - - $argsComma[] = array( 'name' => $nameLoop, 'value' => $value ); - - if ( $this->MatchChar( ',' ) ) { - continue; - } - - if ( $this->MatchChar( ';' ) || $isSemiColonSeperated ) { - - if ( $expressionContainsNamed ) { - $this->Error( 'Cannot mix ; and , as delimiter types' ); - } - - $isSemiColonSeperated = true; - - if ( count( $expressions ) > 1 ) { - $value = $this->NewObj1( 'Less_Tree_Value', $expressions ); - } - $argsSemiColon[] = array( 'name' => $name, 'value' => $value ); - - $name = null; - $expressions = array(); - $expressionContainsNamed = false; - } - } - - $this->forget(); - $returner['args'] = ( $isSemiColonSeperated ? $argsSemiColon : $argsComma ); - return $returner; - } - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - private function parseMixinDefinition() { - $cond = null; - - $char = $this->input[$this->pos]; - if ( ( $char !== '.' && $char !== '#' ) || ( $char === '{' && $this->PeekReg( '/\\G[^{]*\}/' ) ) ) { - return; - } - - $this->save(); - - $match = $this->MatchReg( '/\\G([#.](?:[\w-]|\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/' ); - if ( $match ) { - $name = $match[1]; - - $argInfo = $this->parseMixinArgs( false ); - $params = $argInfo['args']; - $variadic = $argInfo['variadic']; - - // .mixincall("@{a}"); - // looks a bit like a mixin definition.. - // also - // .mixincall(@a: {rule: set;}); - // so we have to be nice and restore - if ( !$this->MatchChar( ')' ) ) { - $this->furthest = $this->pos; - $this->restore(); - return; - } - - $this->parseComments(); - - if ( $this->MatchReg( '/\\Gwhen/' ) ) { // Guard - $cond = $this->expect( 'parseConditions', 'Expected conditions' ); - } - - $ruleset = $this->parseBlock(); - - if ( is_array( $ruleset ) ) { - $this->forget(); - return $this->NewObj5( 'Less_Tree_Mixin_Definition', array( $name, $params, $ruleset, $cond, $variadic ) ); - } - - $this->restore(); - } else { - $this->forget(); - } - } - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - private function parseEntity() { - return $this->MatchFuncs( array( 'parseEntitiesLiteral','parseEntitiesVariable','parseEntitiesUrl','parseEntitiesCall','parseEntitiesKeyword','parseEntitiesJavascript','parseComment' ) ); - } - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was omitted. - // - private function parseEnd() { - return $this->MatchChar( ';' ) || $this->PeekChar( '}' ); - } - - // - // IE's alpha function - // - // alpha(opacity=88) - // - private function parseAlpha() { - if ( !$this->MatchReg( '/\\G\(opacity=/i' ) ) { - return; - } - - $value = $this->MatchReg( '/\\G[0-9]+/' ); - if ( $value ) { - $value = $value[0]; - } else { - $value = $this->parseEntitiesVariable(); - if ( !$value ) { - return; - } - } - - $this->expectChar( ')' ); - return $this->NewObj1( 'Less_Tree_Alpha', $value ); - } - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - private function parseElement() { - $c = $this->parseCombinator(); - $index = $this->pos; - - $e = $this->match( array( '/\\G(?:\d+\.\d+|\d+)%/', '/\\G(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/', - '#*', '#&', 'parseAttribute', '/\\G\([^()@]+\)/', '/\\G[\.#](?=@)/', 'parseEntitiesVariableCurly' ) ); - - if ( is_null( $e ) ) { - $this->save(); - if ( $this->MatchChar( '(' ) ) { - if ( ( $v = $this->parseSelector() ) && $this->MatchChar( ')' ) ) { - $e = $this->NewObj1( 'Less_Tree_Paren', $v ); - $this->forget(); - } else { - $this->restore(); - } - } else { - $this->forget(); - } - } - - if ( !is_null( $e ) ) { - return $this->NewObj4( 'Less_Tree_Element', array( $c, $e, $index, $this->env->currentFileInfo ) ); - } - } - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. - // - private function parseCombinator() { - if ( $this->pos < $this->input_len ) { - $c = $this->input[$this->pos]; - if ( $c === '>' || $c === '+' || $c === '~' || $c === '|' || $c === '^' ) { - - $this->pos++; - if ( $this->input[$this->pos] === '^' ) { - $c = '^^'; - $this->pos++; - } - - $this->skipWhitespace( 0 ); - - return $c; - } - - if ( $this->pos > 0 && $this->isWhitespace( -1 ) ) { - return ' '; - } - } - } - - // - // A CSS selector (see selector below) - // with less extensions e.g. the ability to extend and guard - // - private function parseLessSelector() { - return $this->parseSelector( true ); - } - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - private function parseSelector( $isLess = false ) { - $elements = array(); - $extendList = array(); - $condition = null; - $when = false; - $extend = false; - $e = null; - $c = null; - $index = $this->pos; - - while ( ( $isLess && ( $extend = $this->parseExtend() ) ) || ( $isLess && ( $when = $this->MatchReg( '/\\Gwhen/' ) ) ) || ( $e = $this->parseElement() ) ) { - if ( $when ) { - $condition = $this->expect( 'parseConditions', 'expected condition' ); - } elseif ( $condition ) { - // error("CSS guard can only be used at the end of selector"); - } elseif ( $extend ) { - $extendList = array_merge( $extendList, $extend ); - } else { - // if( count($extendList) ){ - //error("Extend can only be used at the end of selector"); - //} - if ( $this->pos < $this->input_len ) { - $c = $this->input[ $this->pos ]; - } - $elements[] = $e; - $e = null; - } - - if ( $c === '{' || $c === '}' || $c === ';' || $c === ',' || $c === ')' ) { break; - } - } - - if ( $elements ) { - return $this->NewObj5( 'Less_Tree_Selector', array( $elements, $extendList, $condition, $index, $this->env->currentFileInfo ) ); - } - if ( $extendList ) { - $this->Error( 'Extend must be used to extend a selector, it cannot be used on its own' ); - } - } - - private function parseTag() { - return ( $tag = $this->MatchReg( '/\\G[A-Za-z][A-Za-z-]*[0-9]?/' ) ) ? $tag : $this->MatchChar( '*' ); - } - - private function parseAttribute() { - $val = null; - - if ( !$this->MatchChar( '[' ) ) { - return; - } - - $key = $this->parseEntitiesVariableCurly(); - if ( !$key ) { - $key = $this->expect( '/\\G(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\\\.)+/' ); - } - - $op = $this->MatchReg( '/\\G[|~*$^]?=/' ); - if ( $op ) { - $val = $this->match( array( 'parseEntitiesQuoted','/\\G[0-9]+%/','/\\G[\w-]+/','parseEntitiesVariableCurly' ) ); - } - - $this->expectChar( ']' ); - - return $this->NewObj3( 'Less_Tree_Attribute', array( $key, $op === null ? null : $op[0], $val ) ); - } - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - private function parseBlock() { - if ( $this->MatchChar( '{' ) ) { - $content = $this->parsePrimary(); - if ( $this->MatchChar( '}' ) ) { - return $content; - } - } - } - - private function parseBlockRuleset() { - $block = $this->parseBlock(); - - if ( $block ) { - $block = $this->NewObj2( 'Less_Tree_Ruleset', array( null, $block ) ); - } - - return $block; - } - - private function parseDetachedRuleset() { - $blockRuleset = $this->parseBlockRuleset(); - if ( $blockRuleset ) { - return $this->NewObj1( 'Less_Tree_DetachedRuleset', $blockRuleset ); - } - } - - // - // div, .class, body > p {...} - // - private function parseRuleset() { - $selectors = array(); - - $this->save(); - - while ( true ) { - $s = $this->parseLessSelector(); - if ( !$s ) { - break; - } - $selectors[] = $s; - $this->parseComments(); - - if ( $s->condition && count( $selectors ) > 1 ) { - $this->Error( 'Guards are only currently allowed on a single selector.' ); - } - - if ( !$this->MatchChar( ',' ) ) { - break; - } - if ( $s->condition ) { - $this->Error( 'Guards are only currently allowed on a single selector.' ); - } - $this->parseComments(); - } - - if ( $selectors ) { - $rules = $this->parseBlock(); - if ( is_array( $rules ) ) { - $this->forget(); - return $this->NewObj2( 'Less_Tree_Ruleset', array( $selectors, $rules ) ); // Less_Environment::$strictImports - } - } - - // Backtrack - $this->furthest = $this->pos; - $this->restore(); - } - - /** - * Custom less.php parse function for finding simple name-value css pairs - * ex: width:100px; - * - */ - private function parseNameValue() { - $index = $this->pos; - $this->save(); - - // $match = $this->MatchReg('/\\G([a-zA-Z\-]+)\s*:\s*((?:\'")?[a-zA-Z0-9\-% \.,!]+?(?:\'")?)\s*([;}])/'); - $match = $this->MatchReg( '/\\G([a-zA-Z\-]+)\s*:\s*([\'"]?[#a-zA-Z0-9\-%\.,]+?[\'"]?) *(! *important)?\s*([;}])/' ); - if ( $match ) { - - if ( $match[4] == '}' ) { - $this->pos = $index + strlen( $match[0] ) - 1; - } - - if ( $match[3] ) { - $match[2] .= ' !important'; - } - - return $this->NewObj4( 'Less_Tree_NameValue', array( $match[1], $match[2], $index, $this->env->currentFileInfo ) ); - } - - $this->restore(); - } - - private function parseRule( $tryAnonymous = null ) { - $merge = false; - $startOfRule = $this->pos; - - $c = $this->input[$this->pos]; - if ( $c === '.' || $c === '#' || $c === '&' ) { - return; - } - - $this->save(); - $name = $this->MatchFuncs( array( 'parseVariable','parseRuleProperty' ) ); - - if ( $name ) { - - $isVariable = is_string( $name ); - - $value = null; - if ( $isVariable ) { - $value = $this->parseDetachedRuleset(); - } - - $important = null; - if ( !$value ) { - - // prefer to try to parse first if its a variable or we are compressing - // but always fallback on the other one - //if( !$tryAnonymous && is_string($name) && $name[0] === '@' ){ - if ( !$tryAnonymous && ( Less_Parser::$options['compress'] || $isVariable ) ) { - $value = $this->MatchFuncs( array( 'parseValue','parseAnonymousValue' ) ); - } else { - $value = $this->MatchFuncs( array( 'parseAnonymousValue','parseValue' ) ); - } - - $important = $this->parseImportant(); - - // a name returned by this.ruleProperty() is always an array of the form: - // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"] - // where each item is a tree.Keyword or tree.Variable - if ( !$isVariable && is_array( $name ) ) { - $nm = array_pop( $name ); - if ( $nm->value ) { - $merge = $nm->value; - } - } - } - - if ( $value && $this->parseEnd() ) { - $this->forget(); - return $this->NewObj6( 'Less_Tree_Rule', array( $name, $value, $important, $merge, $startOfRule, $this->env->currentFileInfo ) ); - } else { - $this->furthest = $this->pos; - $this->restore(); - if ( $value && !$tryAnonymous ) { - return $this->parseRule( true ); - } - } - } else { - $this->forget(); - } - } - - function parseAnonymousValue() { - if ( preg_match( '/\\G([^@+\/\'"*`(;{}-]*);/', $this->input, $match, 0, $this->pos ) ) { - $this->pos += strlen( $match[1] ); - return $this->NewObj1( 'Less_Tree_Anonymous', $match[1] ); - } - } - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environment, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - private function parseImport() { - $this->save(); - - $dir = $this->MatchReg( '/\\G@import?\s+/' ); - - if ( $dir ) { - $options = $this->parseImportOptions(); - $path = $this->MatchFuncs( array( 'parseEntitiesQuoted','parseEntitiesUrl' ) ); - - if ( $path ) { - $features = $this->parseMediaFeatures(); - if ( $this->MatchChar( ';' ) ) { - if ( $features ) { - $features = $this->NewObj1( 'Less_Tree_Value', $features ); - } - - $this->forget(); - return $this->NewObj5( 'Less_Tree_Import', array( $path, $features, $options, $this->pos, $this->env->currentFileInfo ) ); - } - } - } - - $this->restore(); - } - - private function parseImportOptions() { - $options = array(); - - // list of options, surrounded by parens - if ( !$this->MatchChar( '(' ) ) { - return $options; - } - do{ - $optionName = $this->parseImportOption(); - if ( $optionName ) { - $value = true; - switch ( $optionName ) { - case "css": - $optionName = "less"; - $value = false; - break; - case "once": - $optionName = "multiple"; - $value = false; - break; - } - $options[$optionName] = $value; - if ( !$this->MatchChar( ',' ) ) { break; - } - } - }while ( $optionName ); - $this->expectChar( ')' ); - return $options; - } - - private function parseImportOption() { - $opt = $this->MatchReg( '/\\G(less|css|multiple|once|inline|reference|optional)/' ); - if ( $opt ) { - return $opt[1]; - } - } - - private function parseMediaFeature() { - $nodes = array(); - - do{ - $e = $this->MatchFuncs( array( 'parseEntitiesKeyword','parseEntitiesVariable' ) ); - if ( $e ) { - $nodes[] = $e; - } elseif ( $this->MatchChar( '(' ) ) { - $p = $this->parseProperty(); - $e = $this->parseValue(); - if ( $this->MatchChar( ')' ) ) { - if ( $p && $e ) { - $r = $this->NewObj7( 'Less_Tree_Rule', array( $p, $e, null, null, $this->pos, $this->env->currentFileInfo, true ) ); - $nodes[] = $this->NewObj1( 'Less_Tree_Paren', $r ); - } elseif ( $e ) { - $nodes[] = $this->NewObj1( 'Less_Tree_Paren', $e ); - } else { - return null; - } - } else return null; - } - } while ( $e ); - - if ( $nodes ) { - return $this->NewObj1( 'Less_Tree_Expression', $nodes ); - } - } - - private function parseMediaFeatures() { - $features = array(); - - do{ - $e = $this->parseMediaFeature(); - if ( $e ) { - $features[] = $e; - if ( !$this->MatchChar( ',' ) ) break; - } else { - $e = $this->parseEntitiesVariable(); - if ( $e ) { - $features[] = $e; - if ( !$this->MatchChar( ',' ) ) break; - } - } - } while ( $e ); - - return $features ? $features : null; - } - - private function parseMedia() { - if ( $this->MatchReg( '/\\G@media/' ) ) { - $features = $this->parseMediaFeatures(); - $rules = $this->parseBlock(); - - if ( is_array( $rules ) ) { - return $this->NewObj4( 'Less_Tree_Media', array( $rules, $features, $this->pos, $this->env->currentFileInfo ) ); - } - } - } - - // - // A CSS Directive - // - // @charset "utf-8"; - // - private function parseDirective() { - if ( !$this->PeekChar( '@' ) ) { - return; - } - - $rules = null; - $index = $this->pos; - $hasBlock = true; - $hasIdentifier = false; - $hasExpression = false; - $hasUnknown = false; - - $value = $this->MatchFuncs( array( 'parseImport','parseMedia' ) ); - if ( $value ) { - return $value; - } - - $this->save(); - - $name = $this->MatchReg( '/\\G@[a-z-]+/' ); - - if ( !$name ) return; - $name = $name[0]; - - $nonVendorSpecificName = $name; - $pos = strpos( $name, '-', 2 ); - if ( $name[1] == '-' && $pos > 0 ) { - $nonVendorSpecificName = "@" . substr( $name, $pos + 1 ); - } - - switch ( $nonVendorSpecificName ) { - /* - case "@font-face": - case "@viewport": - case "@top-left": - case "@top-left-corner": - case "@top-center": - case "@top-right": - case "@top-right-corner": - case "@bottom-left": - case "@bottom-left-corner": - case "@bottom-center": - case "@bottom-right": - case "@bottom-right-corner": - case "@left-top": - case "@left-middle": - case "@left-bottom": - case "@right-top": - case "@right-middle": - case "@right-bottom": - hasBlock = true; - break; - */ - case "@charset": - $hasIdentifier = true; - $hasBlock = false; - break; - case "@namespace": - $hasExpression = true; - $hasBlock = false; - break; - case "@keyframes": - $hasIdentifier = true; - break; - case "@host": - case "@page": - case "@document": - case "@supports": - $hasUnknown = true; - break; - } - - if ( $hasIdentifier ) { - $value = $this->parseEntity(); - if ( !$value ) { - $this->error( "expected " . $name . " identifier" ); - } - } else if ( $hasExpression ) { - $value = $this->parseExpression(); - if ( !$value ) { - $this->error( "expected " . $name. " expression" ); - } - } else if ( $hasUnknown ) { - - $value = $this->MatchReg( '/\\G[^{;]+/' ); - if ( $value ) { - $value = $this->NewObj1( 'Less_Tree_Anonymous', trim( $value[0] ) ); - } - } - - if ( $hasBlock ) { - $rules = $this->parseBlockRuleset(); - } - - if ( $rules || ( !$hasBlock && $value && $this->MatchChar( ';' ) ) ) { - $this->forget(); - return $this->NewObj5( 'Less_Tree_Directive', array( $name, $value, $rules, $index, $this->env->currentFileInfo ) ); - } - - $this->restore(); - } - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - private function parseValue() { - $expressions = array(); - - do{ - $e = $this->parseExpression(); - if ( $e ) { - $expressions[] = $e; - if ( !$this->MatchChar( ',' ) ) { - break; - } - } - }while ( $e ); - - if ( $expressions ) { - return $this->NewObj1( 'Less_Tree_Value', $expressions ); - } - } - - private function parseImportant() { - if ( $this->PeekChar( '!' ) && $this->MatchReg( '/\\G! *important/' ) ) { - return ' !important'; - } - } - - private function parseSub() { - if ( $this->MatchChar( '(' ) ) { - $a = $this->parseAddition(); - if ( $a ) { - $this->expectChar( ')' ); - return $this->NewObj2( 'Less_Tree_Expression', array( array( $a ), true ) ); // instead of $e->parens = true so the value is cached - } - } - } - - /** - * Parses multiplication operation - * - * @return Less_Tree_Operation|null - */ - function parseMultiplication() { - $return = $m = $this->parseOperand(); - if ( $return ) { - while ( true ) { - - $isSpaced = $this->isWhitespace( -1 ); - - if ( $this->PeekReg( '/\\G\/[*\/]/' ) ) { - break; - } - - $op = $this->MatchChar( '/' ); - if ( !$op ) { - $op = $this->MatchChar( '*' ); - if ( !$op ) { - break; - } - } - - $a = $this->parseOperand(); - - if ( !$a ) { break; - } - - $m->parensInOp = true; - $a->parensInOp = true; - $return = $this->NewObj3( 'Less_Tree_Operation', array( $op, array( $return, $a ), $isSpaced ) ); - } - } - return $return; - - } - - /** - * Parses an addition operation - * - * @return Less_Tree_Operation|null - */ - private function parseAddition() { - $return = $m = $this->parseMultiplication(); - if ( $return ) { - while ( true ) { - - $isSpaced = $this->isWhitespace( -1 ); - - $op = $this->MatchReg( '/\\G[-+]\s+/' ); - if ( $op ) { - $op = $op[0]; - } else { - if ( !$isSpaced ) { - $op = $this->match( array( '#+','#-' ) ); - } - if ( !$op ) { - break; - } - } - - $a = $this->parseMultiplication(); - if ( !$a ) { - break; - } - - $m->parensInOp = true; - $a->parensInOp = true; - $return = $this->NewObj3( 'Less_Tree_Operation', array( $op, array( $return, $a ), $isSpaced ) ); - } - } - - return $return; - } - - /** - * Parses the conditions - * - * @return Less_Tree_Condition|null - */ - private function parseConditions() { - $index = $this->pos; - $return = $a = $this->parseCondition(); - if ( $a ) { - while ( true ) { - if ( !$this->PeekReg( '/\\G,\s*(not\s*)?\(/' ) || !$this->MatchChar( ',' ) ) { - break; - } - $b = $this->parseCondition(); - if ( !$b ) { - break; - } - - $return = $this->NewObj4( 'Less_Tree_Condition', array( 'or', $return, $b, $index ) ); - } - return $return; - } - } - - private function parseCondition() { - $index = $this->pos; - $negate = false; - $c = null; - - if ( $this->MatchReg( '/\\Gnot/' ) ) $negate = true; - $this->expectChar( '(' ); - $a = $this->MatchFuncs( array( 'parseAddition','parseEntitiesKeyword','parseEntitiesQuoted' ) ); - - if ( $a ) { - $op = $this->MatchReg( '/\\G(?:>=|<=|=<|[<=>])/' ); - if ( $op ) { - $b = $this->MatchFuncs( array( 'parseAddition','parseEntitiesKeyword','parseEntitiesQuoted' ) ); - if ( $b ) { - $c = $this->NewObj5( 'Less_Tree_Condition', array( $op[0], $a, $b, $index, $negate ) ); - } else { - $this->Error( 'Unexpected expression' ); - } - } else { - $k = $this->NewObj1( 'Less_Tree_Keyword', 'true' ); - $c = $this->NewObj5( 'Less_Tree_Condition', array( '=', $a, $k, $index, $negate ) ); - } - $this->expectChar( ')' ); - return $this->MatchReg( '/\\Gand/' ) ? $this->NewObj3( 'Less_Tree_Condition', array( 'and', $c, $this->parseCondition() ) ) : $c; - } - } - - /** - * An operand is anything that can be part of an operation, - * such as a Color, or a Variable - * - */ - private function parseOperand() { - $negate = false; - $offset = $this->pos + 1; - if ( $offset >= $this->input_len ) { - return; - } - $char = $this->input[$offset]; - if ( $char === '@' || $char === '(' ) { - $negate = $this->MatchChar( '-' ); - } - - $o = $this->MatchFuncs( array( 'parseSub','parseEntitiesDimension','parseEntitiesColor','parseEntitiesVariable','parseEntitiesCall' ) ); - - if ( $negate ) { - $o->parensInOp = true; - $o = $this->NewObj1( 'Less_Tree_Negative', $o ); - } - - return $o; - } - - /** - * Expressions either represent mathematical operations, - * or white-space delimited Entities. - * - * 1px solid black - * @var * 2 - * - * @return Less_Tree_Expression|null - */ - private function parseExpression() { - $entities = array(); - - do{ - $e = $this->MatchFuncs( array( 'parseAddition','parseEntity' ) ); - if ( $e ) { - $entities[] = $e; - // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here - if ( !$this->PeekReg( '/\\G\/[\/*]/' ) ) { - $delim = $this->MatchChar( '/' ); - if ( $delim ) { - $entities[] = $this->NewObj1( 'Less_Tree_Anonymous', $delim ); - } - } - } - }while ( $e ); - - if ( $entities ) { - return $this->NewObj1( 'Less_Tree_Expression', $entities ); - } - } - - /** - * Parse a property - * eg: 'min-width', 'orientation', etc - * - * @return string - */ - private function parseProperty() { - $name = $this->MatchReg( '/\\G(\*?-?[_a-zA-Z0-9-]+)\s*:/' ); - if ( $name ) { - return $name[1]; - } - } - - /** - * Parse a rule property - * eg: 'color', 'width', 'height', etc - * - * @return string - */ - private function parseRuleProperty() { - $offset = $this->pos; - $name = array(); - $index = array(); - $length = 0; - - $this->rulePropertyMatch( '/\\G(\*?)/', $offset, $length, $index, $name ); - while ( $this->rulePropertyMatch( '/\\G((?:[\w-]+)|(?:@\{[\w-]+\}))/', $offset, $length, $index, $name ) ); // ! - - if ( ( count( $name ) > 1 ) && $this->rulePropertyMatch( '/\\G\s*((?:\+_|\+)?)\s*:/', $offset, $length, $index, $name ) ) { - // at last, we have the complete match now. move forward, - // convert name particles to tree objects and return: - $this->skipWhitespace( $length ); - - if ( $name[0] === '' ) { - array_shift( $name ); - array_shift( $index ); - } - foreach ( $name as $k => $s ) { - if ( !$s || $s[0] !== '@' ) { - $name[$k] = $this->NewObj1( 'Less_Tree_Keyword', $s ); - } else { - $name[$k] = $this->NewObj3( 'Less_Tree_Variable', array( '@' . substr( $s, 2, -1 ), $index[$k], $this->env->currentFileInfo ) ); - } - } - return $name; - } - - } - - private function rulePropertyMatch( $re, &$offset, &$length, &$index, &$name ) { - preg_match( $re, $this->input, $a, 0, $offset ); - if ( $a ) { - $index[] = $this->pos + $length; - $length += strlen( $a[0] ); - $offset += strlen( $a[0] ); - $name[] = $a[1]; - return true; - } - } - - public static function serializeVars( $vars ) { - $s = ''; - - foreach ( $vars as $name => $value ) { - $s .= ( ( $name[0] === '@' ) ? '' : '@' ) . $name .': '. $value . ( ( substr( $value, -1 ) === ';' ) ? '' : ';' ); - } - - return $s; - } - - /** - * Some versions of php have trouble with method_exists($a,$b) if $a is not an object - * - * @param string $b - */ - public static function is_method( $a, $b ) { - return is_object( $a ) && method_exists( $a, $b ); - } - - /** - * Round numbers similarly to javascript - * eg: 1.499999 to 1 instead of 2 - * - */ - public static function round( $i, $precision = 0 ) { - $precision = pow( 10, $precision ); - $i = $i * $precision; - - $ceil = ceil( $i ); - $floor = floor( $i ); - if ( ( $ceil - $i ) <= ( $i - $floor ) ) { - return $ceil / $precision; - } else { - return $floor / $precision; - } - } - - /** - * Create Less_Tree_* objects and optionally generate a cache string - * - * @return mixed - */ - public function NewObj0( $class ) { - $obj = new $class(); - if ( $this->CacheEnabled() ) { - $obj->cache_string = ' new '.$class.'()'; - } - return $obj; - } - - public function NewObj1( $class, $arg ) { - $obj = new $class( $arg ); - if ( $this->CacheEnabled() ) { - $obj->cache_string = ' new '.$class.'('.Less_Parser::ArgString( $arg ).')'; - } - return $obj; - } - - public function NewObj2( $class, $args ) { - $obj = new $class( $args[0], $args[1] ); - if ( $this->CacheEnabled() ) { - $this->ObjCache( $obj, $class, $args ); - } - return $obj; - } - - public function NewObj3( $class, $args ) { - $obj = new $class( $args[0], $args[1], $args[2] ); - if ( $this->CacheEnabled() ) { - $this->ObjCache( $obj, $class, $args ); - } - return $obj; - } - - public function NewObj4( $class, $args ) { - $obj = new $class( $args[0], $args[1], $args[2], $args[3] ); - if ( $this->CacheEnabled() ) { - $this->ObjCache( $obj, $class, $args ); - } - return $obj; - } - - public function NewObj5( $class, $args ) { - $obj = new $class( $args[0], $args[1], $args[2], $args[3], $args[4] ); - if ( $this->CacheEnabled() ) { - $this->ObjCache( $obj, $class, $args ); - } - return $obj; - } - - public function NewObj6( $class, $args ) { - $obj = new $class( $args[0], $args[1], $args[2], $args[3], $args[4], $args[5] ); - if ( $this->CacheEnabled() ) { - $this->ObjCache( $obj, $class, $args ); - } - return $obj; - } - - public function NewObj7( $class, $args ) { - $obj = new $class( $args[0], $args[1], $args[2], $args[3], $args[4], $args[5], $args[6] ); - if ( $this->CacheEnabled() ) { - $this->ObjCache( $obj, $class, $args ); - } - return $obj; - } - - // caching - public function ObjCache( $obj, $class, $args = array() ) { - $obj->cache_string = ' new '.$class.'('. self::ArgCache( $args ).')'; - } - - public function ArgCache( $args ) { - return implode( ',', array_map( array( 'Less_Parser','ArgString' ), $args ) ); - } - - /** - * Convert an argument to a string for use in the parser cache - * - * @return string - */ - public static function ArgString( $arg ) { - $type = gettype( $arg ); - - if ( $type === 'object' ) { - $string = $arg->cache_string; - unset( $arg->cache_string ); - return $string; - - } elseif ( $type === 'array' ) { - $string = ' Array('; - foreach ( $arg as $k => $a ) { - $string .= var_export( $k, true ).' => '.self::ArgString( $a ).','; - } - return $string . ')'; - } - - return var_export( $arg, true ); - } - - public function Error( $msg ) { - throw new Less_Exception_Parser( $msg, null, $this->furthest, $this->env->currentFileInfo ); - } - - public static function WinPath( $path ) { - return str_replace( '\\', '/', $path ); - } - - public static function AbsPath( $path, $winPath = false ) { - if ( strpos( $path, '//' ) !== false && preg_match( '_^(https?:)?//\\w+(\\.\\w+)+/\\w+_i', $path ) ) { - return $winPath ? '' : false; - } else { - $path = realpath( $path ); - if ( $winPath ) { - $path = self::WinPath( $path ); - } - return $path; - } - } - - public function CacheEnabled() { - return ( Less_Parser::$options['cache_method'] && ( Less_Cache::$cache_dir || ( Less_Parser::$options['cache_method'] == 'callback' ) ) ); - } - -} diff --git a/less.php/lib/Less/SourceMap/Base64VLQ.php b/less.php/lib/Less/SourceMap/Base64VLQ.php deleted file mode 100755 index 989a4ce..0000000 --- a/less.php/lib/Less/SourceMap/Base64VLQ.php +++ /dev/null @@ -1,187 +0,0 @@ - 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, - 'H' => 7,'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13, - 'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, - 'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27, - 'c' => 28, 'd' => 29, 'e' => 30, 'f' => 31, 'g' => 32, 'h' => 33, 'i' => 34, - 'j' => 35, 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39, 'o' => 40, 'p' => 41, - 'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47, 'w' => 48, - 'x' => 49, 'y' => 50, 'z' => 51, 0 => 52, 1 => 53, 2 => 54, 3 => 55, 4 => 56, - 5 => 57, 6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63, - ); - - /** - * Integer to char map - * - * @var array - */ - private $intToCharMap = array( - 0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 5 => 'F', 6 => 'G', - 7 => 'H', 8 => 'I', 9 => 'J', 10 => 'K', 11 => 'L', 12 => 'M', 13 => 'N', - 14 => 'O', 15 => 'P', 16 => 'Q', 17 => 'R', 18 => 'S', 19 => 'T', 20 => 'U', - 21 => 'V', 22 => 'W', 23 => 'X', 24 => 'Y', 25 => 'Z', 26 => 'a', 27 => 'b', - 28 => 'c', 29 => 'd', 30 => 'e', 31 => 'f', 32 => 'g', 33 => 'h', 34 => 'i', - 35 => 'j', 36 => 'k', 37 => 'l', 38 => 'm', 39 => 'n', 40 => 'o', 41 => 'p', - 42 => 'q', 43 => 'r', 44 => 's', 45 => 't', 46 => 'u', 47 => 'v', 48 => 'w', - 49 => 'x', 50 => 'y', 51 => 'z', 52 => '0', 53 => '1', 54 => '2', 55 => '3', - 56 => '4', 57 => '5', 58 => '6', 59 => '7', 60 => '8', 61 => '9', 62 => '+', - 63 => '/', - ); - - /** - * Constructor - */ - public function __construct() { - // I leave it here for future reference - // foreach(str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') as $i => $char) - // { - // $this->charToIntMap[$char] = $i; - // $this->intToCharMap[$i] = $char; - // } - } - - /** - * Convert from a two-complement value to a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - * We generate the value for 32 bit machines, hence -2147483648 becomes 1, not 4294967297, - * even on a 64 bit machine. - * @param string $aValue - */ - public function toVLQSigned( $aValue ) { - return 0xffffffff & ( $aValue < 0 ? ( ( -$aValue ) << 1 ) + 1 : ( $aValue << 1 ) + 0 ); - } - - /** - * Convert to a two-complement value from a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - * We assume that the value was generated with a 32 bit machine in mind. - * Hence - * 1 becomes -2147483648 - * even on a 64 bit machine. - * @param integer $aValue - */ - public function fromVLQSigned( $aValue ) { - return $aValue & 1 ? $this->zeroFill( ~$aValue + 2, 1 ) | ( -1 - 0x7fffffff ) : $this->zeroFill( $aValue, 1 ); - } - - /** - * Return the base 64 VLQ encoded value. - * - * @param string $aValue The value to encode - * @return string The encoded value - */ - public function encode( $aValue ) { - $encoded = ''; - $vlq = $this->toVLQSigned( $aValue ); - do - { - $digit = $vlq & $this->mask; - $vlq = $this->zeroFill( $vlq, $this->shift ); - if ( $vlq > 0 ) { - $digit |= $this->continuationBit; - } - $encoded .= $this->base64Encode( $digit ); - } while ( $vlq > 0 ); - - return $encoded; - } - - /** - * Return the value decoded from base 64 VLQ. - * - * @param string $encoded The encoded value to decode - * @return integer The decoded value - */ - public function decode( $encoded ) { - $vlq = 0; - $i = 0; - do - { - $digit = $this->base64Decode( $encoded[$i] ); - $vlq |= ( $digit & $this->mask ) << ( $i * $this->shift ); - $i++; - } while ( $digit & $this->continuationBit ); - - return $this->fromVLQSigned( $vlq ); - } - - /** - * Right shift with zero fill. - * - * @param integer $a number to shift - * @param integer $b number of bits to shift - * @return integer - */ - public function zeroFill( $a, $b ) { - return ( $a >= 0 ) ? ( $a >> $b ) : ( $a >> $b ) & ( PHP_INT_MAX >> ( $b - 1 ) ); - } - - /** - * Encode single 6-bit digit as base64. - * - * @param integer $number - * @return string - * @throws Exception If the number is invalid - */ - public function base64Encode( $number ) { - if ( $number < 0 || $number > 63 ) { - throw new Exception( sprintf( 'Invalid number "%s" given. Must be between 0 and 63.', $number ) ); - } - return $this->intToCharMap[$number]; - } - - /** - * Decode single 6-bit digit from base64 - * - * @param string $char - * @return number - * @throws Exception If the number is invalid - */ - public function base64Decode( $char ) { - if ( !array_key_exists( $char, $this->charToIntMap ) ) { - throw new Exception( sprintf( 'Invalid base 64 digit "%s" given.', $char ) ); - } - return $this->charToIntMap[$char]; - } - -} diff --git a/less.php/lib/Less/SourceMap/Generator.php b/less.php/lib/Less/SourceMap/Generator.php deleted file mode 100755 index eded501..0000000 --- a/less.php/lib/Less/SourceMap/Generator.php +++ /dev/null @@ -1,354 +0,0 @@ - '', - - // an optional name of the generated code that this source map is associated with. - 'sourceMapFilename' => null, - - // url of the map - 'sourceMapURL' => null, - - // absolute path to a file to write the map to - 'sourceMapWriteTo' => null, - - // output source contents? - 'outputSourceFiles' => false, - - // base path for filename normalization - 'sourceMapRootpath' => '', - - // base path for filename normalization - 'sourceMapBasepath' => '' - ); - - /** - * The base64 VLQ encoder - * - * @var Less_SourceMap_Base64VLQ - */ - protected $encoder; - - /** - * Array of mappings - * - * @var array - */ - protected $mappings = array(); - - /** - * The root node - * - * @var Less_Tree_Ruleset - */ - protected $root; - - /** - * Array of contents map - * - * @var array - */ - protected $contentsMap = array(); - - /** - * File to content map - * - * @var array - */ - protected $sources = array(); - protected $source_keys = array(); - - /** - * Constructor - * - * @param Less_Tree_Ruleset $root The root node - * @param array $options Array of options - */ - public function __construct( Less_Tree_Ruleset $root, $contentsMap, $options = array() ) { - $this->root = $root; - $this->contentsMap = $contentsMap; - $this->encoder = new Less_SourceMap_Base64VLQ(); - - $this->SetOptions( $options ); - - $this->options['sourceMapRootpath'] = $this->fixWindowsPath( $this->options['sourceMapRootpath'], true ); - $this->options['sourceMapBasepath'] = $this->fixWindowsPath( $this->options['sourceMapBasepath'], true ); - } - - /** - * Generates the CSS - * - * @return string - */ - public function generateCSS() { - $output = new Less_Output_Mapped( $this->contentsMap, $this ); - - // catch the output - $this->root->genCSS( $output ); - - $sourceMapUrl = $this->getOption( 'sourceMapURL' ); - $sourceMapFilename = $this->getOption( 'sourceMapFilename' ); - $sourceMapContent = $this->generateJson(); - $sourceMapWriteTo = $this->getOption( 'sourceMapWriteTo' ); - - if ( !$sourceMapUrl && $sourceMapFilename ) { - $sourceMapUrl = $this->normalizeFilename( $sourceMapFilename ); - } - - // write map to a file - if ( $sourceMapWriteTo ) { - $this->saveMap( $sourceMapWriteTo, $sourceMapContent ); - } - - // inline the map - if ( !$sourceMapUrl ) { - $sourceMapUrl = sprintf( 'data:application/json,%s', Less_Functions::encodeURIComponent( $sourceMapContent ) ); - } - - if ( $sourceMapUrl ) { - $output->add( sprintf( '/*# sourceMappingURL=%s */', $sourceMapUrl ) ); - } - - return $output->toString(); - } - - /** - * Saves the source map to a file - * - * @param string $file The absolute path to a file - * @param string $content The content to write - * @throws Exception If the file could not be saved - */ - protected function saveMap( $file, $content ) { - $dir = dirname( $file ); - // directory does not exist - if ( !is_dir( $dir ) ) { - // FIXME: create the dir automatically? - throw new Exception( sprintf( 'The directory "%s" does not exist. Cannot save the source map.', $dir ) ); - } - // FIXME: proper saving, with dir write check! - if ( file_put_contents( $file, $content ) === false ) { - throw new Exception( sprintf( 'Cannot save the source map to "%s"', $file ) ); - } - return true; - } - - /** - * Normalizes the filename - * - * @param string $filename - * @return string - */ - protected function normalizeFilename( $filename ) { - $filename = $this->fixWindowsPath( $filename ); - - $rootpath = $this->getOption( 'sourceMapRootpath' ); - $basePath = $this->getOption( 'sourceMapBasepath' ); - - // "Trim" the 'sourceMapBasepath' from the output filename. - if ( is_string( $basePath ) && strpos( $filename, $basePath ) === 0 ) { - $filename = substr( $filename, strlen( $basePath ) ); - } - - // Remove extra leading path separators. - if ( strpos( $filename, '\\' ) === 0 || strpos( $filename, '/' ) === 0 ) { - $filename = substr( $filename, 1 ); - } - - return $rootpath . $filename; - } - - /** - * Adds a mapping - * - * @param integer $generatedLine The line number in generated file - * @param integer $generatedColumn The column number in generated file - * @param integer $originalLine The line number in original file - * @param integer $originalColumn The column number in original file - * @param string $sourceFile The original source file - */ - public function addMapping( $generatedLine, $generatedColumn, $originalLine, $originalColumn, $fileInfo ) { - $this->mappings[] = array( - 'generated_line' => $generatedLine, - 'generated_column' => $generatedColumn, - 'original_line' => $originalLine, - 'original_column' => $originalColumn, - 'source_file' => $fileInfo['currentUri'] - ); - - $this->sources[$fileInfo['currentUri']] = $fileInfo['filename']; - } - - /** - * Generates the JSON source map - * - * @return string - * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit# - */ - protected function generateJson() { - $sourceMap = array(); - $mappings = $this->generateMappings(); - - // File version (always the first entry in the object) and must be a positive integer. - $sourceMap['version'] = self::VERSION; - - // An optional name of the generated code that this source map is associated with. - $file = $this->getOption( 'sourceMapFilename' ); - if ( $file ) { - $sourceMap['file'] = $file; - } - - // An optional source root, useful for relocating source files on a server or removing repeated values in the 'sources' entry. This value is prepended to the individual entries in the 'source' field. - $root = $this->getOption( 'sourceRoot' ); - if ( $root ) { - $sourceMap['sourceRoot'] = $root; - } - - // A list of original sources used by the 'mappings' entry. - $sourceMap['sources'] = array(); - foreach ( $this->sources as $source_uri => $source_filename ) { - $sourceMap['sources'][] = $this->normalizeFilename( $source_filename ); - } - - // A list of symbol names used by the 'mappings' entry. - $sourceMap['names'] = array(); - - // A string with the encoded mapping data. - $sourceMap['mappings'] = $mappings; - - if ( $this->getOption( 'outputSourceFiles' ) ) { - // An optional list of source content, useful when the 'source' can't be hosted. - // The contents are listed in the same order as the sources above. - // 'null' may be used if some original sources should be retrieved by name. - $sourceMap['sourcesContent'] = $this->getSourcesContent(); - } - - // less.js compat fixes - if ( count( $sourceMap['sources'] ) && empty( $sourceMap['sourceRoot'] ) ) { - unset( $sourceMap['sourceRoot'] ); - } - - return json_encode( $sourceMap ); - } - - /** - * Returns the sources contents - * - * @return array|null - */ - protected function getSourcesContent() { - if ( empty( $this->sources ) ) { - return; - } - $content = array(); - foreach ( $this->sources as $sourceFile ) { - $content[] = file_get_contents( $sourceFile ); - } - return $content; - } - - /** - * Generates the mappings string - * - * @return string - */ - public function generateMappings() { - if ( !count( $this->mappings ) ) { - return ''; - } - - $this->source_keys = array_flip( array_keys( $this->sources ) ); - - // group mappings by generated line number. - $groupedMap = $groupedMapEncoded = array(); - foreach ( $this->mappings as $m ) { - $groupedMap[$m['generated_line']][] = $m; - } - ksort( $groupedMap ); - - $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0; - - foreach ( $groupedMap as $lineNumber => $line_map ) { - while ( ++$lastGeneratedLine < $lineNumber ) { - $groupedMapEncoded[] = ';'; - } - - $lineMapEncoded = array(); - $lastGeneratedColumn = 0; - - foreach ( $line_map as $m ) { - $mapEncoded = $this->encoder->encode( $m['generated_column'] - $lastGeneratedColumn ); - $lastGeneratedColumn = $m['generated_column']; - - // find the index - if ( $m['source_file'] ) { - $index = $this->findFileIndex( $m['source_file'] ); - if ( $index !== false ) { - $mapEncoded .= $this->encoder->encode( $index - $lastOriginalIndex ); - $lastOriginalIndex = $index; - - // lines are stored 0-based in SourceMap spec version 3 - $mapEncoded .= $this->encoder->encode( $m['original_line'] - 1 - $lastOriginalLine ); - $lastOriginalLine = $m['original_line'] - 1; - - $mapEncoded .= $this->encoder->encode( $m['original_column'] - $lastOriginalColumn ); - $lastOriginalColumn = $m['original_column']; - } - } - - $lineMapEncoded[] = $mapEncoded; - } - - $groupedMapEncoded[] = implode( ',', $lineMapEncoded ) . ';'; - } - - return rtrim( implode( $groupedMapEncoded ), ';' ); - } - - /** - * Finds the index for the filename - * - * @param string $filename - * @return integer|false - */ - protected function findFileIndex( $filename ) { - return $this->source_keys[$filename]; - } - - /** - * fix windows paths - * @param string $path - * @return string - */ - public function fixWindowsPath( $path, $addEndSlash = false ) { - $slash = ( $addEndSlash ) ? '/' : ''; - if ( !empty( $path ) ) { - $path = str_replace( '\\', '/', $path ); - $path = rtrim( $path, '/' ) . $slash; - } - - return $path; - } - -} diff --git a/less.php/lib/Less/Tree.php b/less.php/lib/Less/Tree.php deleted file mode 100755 index 7b48e9a..0000000 --- a/less.php/lib/Less/Tree.php +++ /dev/null @@ -1,84 +0,0 @@ -genCSS( $output ); - return $output->toString(); - } - - /** - * Generate CSS by adding it to the output object - * - * @param Less_Output $output The output - * @return void - */ - public function genCSS( $output ) { - } - - /** - * @param Less_Tree_Ruleset[] $rules - */ - public static function outputRuleset( $output, $rules ) { - $ruleCnt = count( $rules ); - Less_Environment::$tabLevel++; - - // Compressed - if ( Less_Parser::$options['compress'] ) { - $output->add( '{' ); - for ( $i = 0; $i < $ruleCnt; $i++ ) { - $rules[$i]->genCSS( $output ); - } - - $output->add( '}' ); - Less_Environment::$tabLevel--; - return; - } - - // Non-compressed - $tabSetStr = "\n".str_repeat( Less_Parser::$options['indentation'], Less_Environment::$tabLevel - 1 ); - $tabRuleStr = $tabSetStr.Less_Parser::$options['indentation']; - - $output->add( " {" ); - for ( $i = 0; $i < $ruleCnt; $i++ ) { - $output->add( $tabRuleStr ); - $rules[$i]->genCSS( $output ); - } - Less_Environment::$tabLevel--; - $output->add( $tabSetStr.'}' ); - - } - - public function accept( $visitor ) { - } - - public static function ReferencedArray( $rules ) { - foreach ( $rules as $rule ) { - if ( method_exists( $rule, 'markReferenced' ) ) { - $rule->markReferenced(); - } - } - } - - /** - * Requires php 5.3+ - */ - public static function __set_state( $args ) { - $class = get_called_class(); - $obj = new $class( null, null, null, null ); - foreach ( $args as $key => $val ) { - $obj->$key = $val; - } - return $obj; - } - -} diff --git a/less.php/lib/Less/Tree/Alpha.php b/less.php/lib/Less/Tree/Alpha.php deleted file mode 100755 index cd38c91..0000000 --- a/less.php/lib/Less/Tree/Alpha.php +++ /dev/null @@ -1,48 +0,0 @@ -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/less.php/lib/Less/Tree/Anonymous.php b/less.php/lib/Less/Tree/Anonymous.php deleted file mode 100755 index 1dc9bab..0000000 --- a/less.php/lib/Less/Tree/Anonymous.php +++ /dev/null @@ -1,58 +0,0 @@ -value = $value; - $this->index = $index; - $this->mapLines = $mapLines; - $this->currentFileInfo = $currentFileInfo; - } - - public function compile() { - 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/less.php/lib/Less/Tree/Assignment.php b/less.php/lib/Less/Tree/Assignment.php deleted file mode 100755 index 69c7a4e..0000000 --- a/less.php/lib/Less/Tree/Assignment.php +++ /dev/null @@ -1,39 +0,0 @@ -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/less.php/lib/Less/Tree/Attribute.php b/less.php/lib/Less/Tree/Attribute.php deleted file mode 100755 index c47abb9..0000000 --- a/less.php/lib/Less/Tree/Attribute.php +++ /dev/null @@ -1,53 +0,0 @@ -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/less.php/lib/Less/Tree/Call.php b/less.php/lib/Less/Tree/Call.php deleted file mode 100755 index 5341b74..0000000 --- a/less.php/lib/Less/Tree/Call.php +++ /dev/null @@ -1,117 +0,0 @@ -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 = array(); - 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 { - - if ( method_exists( 'Less_Functions', $nameLC ) ) { // 1. - try { - - $func = new Less_Functions( $env, $this->currentFileInfo ); - $result = call_user_func_array( array( $func,$nameLC ), $args ); - - } catch ( Exception $e ) { - throw new Less_Exception_Compiler( 'error evaluating function `' . $this->name . '` '.$e->getMessage().' index: '. $this->index ); - } - } elseif ( isset( $env->functions[$nameLC] ) && is_callable( $env->functions[$nameLC] ) ) { - try { - $result = call_user_func_array( $env->functions[$nameLC], $args ); - } catch ( Exception $e ) { - throw new Less_Exception_Compiler( 'error evaluating function `' . $this->name . '` '.$e->getMessage().' index: '. $this->index ); - } - } - } - - 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/less.php/lib/Less/Tree/Color.php b/less.php/lib/Less/Tree/Color.php deleted file mode 100755 index b0f79db..0000000 --- a/less.php/lib/Less/Tree/Color.php +++ /dev/null @@ -1,230 +0,0 @@ -rgb = $rgb; - $this->alpha = $a; - $this->isTransparentKeyword = true; - return; - } - - $this->rgb = array(); - if ( is_array( $rgb ) ) { - $this->rgb = $rgb; - } else if ( 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 compile() { - return $this; - } - - 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 = array(); - 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 = array(); - $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 array( '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 array( '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( array( 0, 0, 0 ), 0, true ); - } - } - -} diff --git a/less.php/lib/Less/Tree/Comment.php b/less.php/lib/Less/Tree/Comment.php deleted file mode 100755 index c7e6c0f..0000000 --- a/less.php/lib/Less/Tree/Comment.php +++ /dev/null @@ -1,51 +0,0 @@ -value = $value; - $this->silent = !!$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 compile() { - return $this; - } - - public function markReferenced() { - $this->isReferenced = true; - } - -} diff --git a/less.php/lib/Less/Tree/Condition.php b/less.php/lib/Less/Tree/Condition.php deleted file mode 100755 index 355de8c..0000000 --- a/less.php/lib/Less/Tree/Condition.php +++ /dev/null @@ -1,72 +0,0 @@ -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/less.php/lib/Less/Tree/DefaultFunc.php b/less.php/lib/Less/Tree/DefaultFunc.php deleted file mode 100755 index 41b78b6..0000000 --- a/less.php/lib/Less/Tree/DefaultFunc.php +++ /dev/null @@ -1,34 +0,0 @@ -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/less.php/lib/Less/Tree/Dimension.php b/less.php/lib/Less/Tree/Dimension.php deleted file mode 100755 index 70c71b4..0000000 --- a/less.php/lib/Less/Tree/Dimension.php +++ /dev/null @@ -1,198 +0,0 @@ -value = floatval( $value ); - - if ( $unit && ( $unit instanceof Less_Tree_Unit ) ) { - $this->unit = $unit; - } elseif ( $unit ) { - $this->unit = new Less_Tree_Unit( array( $unit ) ); - } else { - $this->unit = new Less_Tree_Unit(); - } - } - - public function accept( $visitor ) { - $this->unit = $visitor->visitObj( $this->unit ); - } - - public function compile() { - return $this; - } - - public function toColor() { - return new Less_Tree_Color( array( $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( $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 $strValue; - } - - // 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( array( 'length' => 'px', 'duration' => 's', 'angle' => 'rad' ) ); - } - - public function convertTo( $conversions ) { - $value = $this->value; - $unit = clone $this->unit; - - if ( is_string( $conversions ) ) { - $derivedConversions = array(); - foreach ( Less_Tree_UnitConversions::$groups as $i ) { - if ( isset( Less_Tree_UnitConversions::${$i}[$conversions] ) ) { - $derivedConversions = array( $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/less.php/lib/Less/Tree/Directive.php b/less.php/lib/Less/Tree/Directive.php deleted file mode 100755 index 6c6a94f..0000000 --- a/less.php/lib/Less/Tree/Directive.php +++ /dev/null @@ -1,96 +0,0 @@ -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, array( $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/less.php/lib/Less/Tree/Element.php b/less.php/lib/Less/Tree/Element.php deleted file mode 100755 index 5e25bc0..0000000 --- a/less.php/lib/Less/Tree/Element.php +++ /dev/null @@ -1,70 +0,0 @@ -value = $value; - $this->value_is_object = is_object( $value ); - - if ( $combinator ) { - $this->combinator = $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 ) { - if ( Less_Environment::$mixin_stack ) { - return new Less_Tree_Element( $this->combinator, ( $this->value_is_object ? $this->value->compile( $env ) : $this->value ), $this->index, $this->currentFileInfo ); - } - - if ( $this->value_is_object ) { - $this->value = $this->value->compile( $env ); - } - - return $this; - } - - /** - * @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/less.php/lib/Less/Tree/Expression.php b/less.php/lib/Less/Tree/Expression.php deleted file mode 100755 index cf06315..0000000 --- a/less.php/lib/Less/Tree/Expression.php +++ /dev/null @@ -1,95 +0,0 @@ -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 = array(); - 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 = array(); - foreach ( $this->value as $v ) { - if ( $v instanceof Less_Tree_Comment ) { - continue; - } - $new_value[] = $v; - } - $this->value = $new_value; - } - } -} diff --git a/less.php/lib/Less/Tree/Extend.php b/less.php/lib/Less/Tree/Extend.php deleted file mode 100755 index 4dd3665..0000000 --- a/less.php/lib/Less/Tree/Extend.php +++ /dev/null @@ -1,80 +0,0 @@ -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 = array( - $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 = array(); - - 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 = array( new Less_Tree_Selector( $selfElements ) ); - } - -} diff --git a/less.php/lib/Less/Tree/Import.php b/less.php/lib/Less/Tree/Import.php deleted file mode 100755 index ffdac64..0000000 --- a/less.php/lib/Less/Tree/Import.php +++ /dev/null @@ -1,291 +0,0 @@ -options = $options; - $this->index = $index; - $this->path = $path; - $this->features = $features; - $this->currentFileInfo = $currentFileInfo; - - if ( is_array( $options ) ) { - $this->options += array( '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(); - if ( $pathValue && preg_match( '/css([\?;].*)?$/', $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 - */ - 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'; - } else if ( $this->path instanceof Less_Tree_URL ) { - $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 array(); - } - - 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, array(), true ); - - if ( $this->features ) { - return new Less_Tree_Media( array( $contents ), $this->features->value ); - } - - return array( $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 array(); - } - - // 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 - * - * @param Less_Tree_Import $evald - */ - public function PathAndUri() { - $evald_path = $this->getPath(); - - if ( $evald_path ) { - - $import_dirs = array(); - - 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 array( $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 array( $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 array( $full_path, $uri ); - } - } - } - } - } - - /** - * Parse the import url and return the rules - * - * @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( array(), $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? - * - * @return boolean|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/less.php/lib/Less/Tree/Javascript.php b/less.php/lib/Less/Tree/Javascript.php deleted file mode 100755 index 179781a..0000000 --- a/less.php/lib/Less/Tree/Javascript.php +++ /dev/null @@ -1,30 +0,0 @@ -escaped = $escaped; - $this->expression = $string; - $this->index = $index; - } - - public function compile() { - return new Less_Tree_Anonymous( '/* Sorry, can not do JavaScript evaluation in PHP... :( */' ); - } - -} diff --git a/less.php/lib/Less/Tree/Keyword.php b/less.php/lib/Less/Tree/Keyword.php deleted file mode 100755 index ed217cf..0000000 --- a/less.php/lib/Less/Tree/Keyword.php +++ /dev/null @@ -1,43 +0,0 @@ -value = $value; - } - - public function compile() { - return $this; - } - - /** - * @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/less.php/lib/Less/Tree/Media.php b/less.php/lib/Less/Tree/Media.php deleted file mode 100755 index ba25a67..0000000 --- a/less.php/lib/Less/Tree/Media.php +++ /dev/null @@ -1,173 +0,0 @@ -index = $index; - $this->currentFileInfo = $currentFileInfo; - - $selectors = $this->emptySelectors(); - - $this->features = new Less_Tree_Value( $features ); - - $this->rules = array( 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 ); - - } - - public function compile( $env ) { - $media = new Less_Tree_Media( array(), array(), $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 = array( $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 = array( new Less_Tree_Selector( array( $el ), array(), 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 = array(); - $env->mediaPath = array(); - - return $result; - } - - public function compileNested( $env ) { - $path = array_merge( $env->mediaPath, array( $this ) ); - - // 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 : array( $value ); - } - - // 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 = array(); - 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, array( 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( array(), array() ); - } - - public function permute( $arr ) { - if ( !$arr ) - return array(); - - if ( count( $arr ) == 1 ) - return $arr[0]; - - $result = array(); - $rest = $this->permute( array_slice( $arr, 1 ) ); - foreach ( $rest as $r ) { - foreach ( $arr[0] as $a ) { - $result[] = array_merge( - is_array( $a ) ? $a : array( $a ), - is_array( $r ) ? $r : array( $r ) - ); - } - } - - return $result; - } - - public function bubbleSelectors( $selectors ) { - if ( !$selectors ) return; - - $this->rules = array( new Less_Tree_Ruleset( $selectors, array( $this->rules[0] ) ) ); - } - -} diff --git a/less.php/lib/Less/Tree/Mixin/Call.php b/less.php/lib/Less/Tree/Mixin/Call.php deleted file mode 100755 index 8e1eece..0000000 --- a/less.php/lib/Less/Tree/Mixin/Call.php +++ /dev/null @@ -1,193 +0,0 @@ -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 = array(); - $match = false; - $isOneFound = false; - $candidates = array(); - $defaultUsed = false; - $conditionResult = array(); - - $args = array(); - foreach ( $this->arguments as $a ) { - $args[] = array( '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 = array( '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 ); - } - 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 = array( 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( '', array(), $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 = array(); - 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/less.php/lib/Less/Tree/Mixin/Definition.php b/less.php/lib/Less/Tree/Mixin/Definition.php deleted file mode 100755 index f9f2eb4..0000000 --- a/less.php/lib/Less/Tree/Mixin/Definition.php +++ /dev/null @@ -1,233 +0,0 @@ -name = $name; - $this->selectors = array( new Less_Tree_Selector( array( 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 = array(), &$evaldArguments = array() ) { - $frame = new Less_Tree_Ruleset( null, array() ); - $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 = array(); - 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 ); - } else if ( isset( $param['value'] ) ) { - - if ( !$mixinEnv ) { - $mixinEnv = new Less_Environment(); - $mixinEnv->frames = array_merge( array( $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 = array(); - - 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( array( $this, $frame ), $mixinFrames ); - $ruleset = $ruleset->compile( $ruleSetEnv ); - - if ( $important ) { - $ruleset = $ruleset->makeImportant(); - } - - Less_Environment::$mixin_stack--; - - return $ruleset; - } - - 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 = array(); - } - - $frame = $this->compileParams( $env, array_merge( $this->frames, $env->frames ), $args ); - - $compile_env = new Less_Environment(); - $compile_env->frames = array_merge( - array( $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/less.php/lib/Less/Tree/NameValue.php b/less.php/lib/Less/Tree/NameValue.php deleted file mode 100755 index 4f9aa97..0000000 --- a/less.php/lib/Less/Tree/NameValue.php +++ /dev/null @@ -1,49 +0,0 @@ - color:#FF0000; - * - * @package Less - * @subpackage tree - */ -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/less.php/lib/Less/Tree/Negative.php b/less.php/lib/Less/Tree/Negative.php deleted file mode 100755 index f0f36c8..0000000 --- a/less.php/lib/Less/Tree/Negative.php +++ /dev/null @@ -1,37 +0,0 @@ -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( '*', array( new Less_Tree_Dimension( -1 ), $this->value ) ); - return $ret->compile( $env ); - } - return new Less_Tree_Negative( $this->value->compile( $env ) ); - } -} diff --git a/less.php/lib/Less/Tree/Operation.php b/less.php/lib/Less/Tree/Operation.php deleted file mode 100755 index d4eb9ac..0000000 --- a/less.php/lib/Less/Tree/Operation.php +++ /dev/null @@ -1,68 +0,0 @@ -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, array( $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/less.php/lib/Less/Tree/Paren.php b/less.php/lib/Less/Tree/Paren.php deleted file mode 100755 index 77ee48c..0000000 --- a/less.php/lib/Less/Tree/Paren.php +++ /dev/null @@ -1,35 +0,0 @@ -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/less.php/lib/Less/Tree/Quoted.php b/less.php/lib/Less/Tree/Quoted.php deleted file mode 100755 index d01598b..0000000 --- a/less.php/lib/Less/Tree/Quoted.php +++ /dev/null @@ -1,79 +0,0 @@ -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()->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/less.php/lib/Less/Tree/Rule.php b/less.php/lib/Less/Tree/Rule.php deleted file mode 100755 index 5f393eb..0000000 --- a/less.php/lib/Less/Tree/Rule.php +++ /dev/null @@ -1,112 +0,0 @@ -name = $name; - $this->value = ( $value instanceof Less_Tree_Value || $value instanceof Less_Tree_Ruleset ) ? $value : new Less_Tree_Value( array( $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 ); - } - - 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/less.php/lib/Less/Tree/Ruleset.php b/less.php/lib/Less/Tree/Ruleset.php deleted file mode 100755 index 9bc8243..0000000 --- a/less.php/lib/Less/Tree/Ruleset.php +++ /dev/null @@ -1,621 +0,0 @@ -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; - } - } - } - } - - public function __construct( $selectors, $rules, $strictImports = null ) { - $this->selectors = $selectors; - $this->rules = $rules; - $this->lookups = array(); - $this->strictImports = $strictImports; - $this->SetRulesetIndex(); - } - - public function accept( $visitor ) { - if ( $this->paths ) { - $paths_len = count( $this->paths ); - for ( $i = 0,$paths_len; $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 ); - } - } - - 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++ ) { - 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 = 0; - if ( $env instanceof Less_Environment ) { - $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, array( $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 integer $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 = array(); - 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 = array(); - 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 - * - */ - private function PrepareRuleset( $env ) { - $hasOnePassingSelector = false; - $selectors = array(); - if ( $this->selectors ) { - Less_Tree_DefaultFunc::error( "it is currently only allowed in parametric mixin guards," ); - - foreach ( $this->selectors as $s ) { - $selector = $s->compile( $env ); - $selectors[] = $selector; - if ( $selector->evaldCondition ) { - $hasOnePassingSelector = true; - } - } - - Less_Tree_DefaultFunc::reset(); - } else { - $hasOnePassingSelector = true; - } - - if ( $this->rules && $hasOnePassingSelector ) { - $rules = $this->rules; - } else { - $rules = array(); - } - - $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, array( $rules ) ); - } - - $this->resetCache(); - } - } - } - - function makeImportant() { - $important_rules = array(); - 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 ) { - 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 = array(); - } - - public function variables() { - $this->_variables = array(); - foreach ( $this->rules as $r ) { - if ( $r instanceof Less_Tree_Rule && $r->variable === true ) { - $this->_variables[$r->name] = $r; - } - } - } - - public function variable( $name ) { - if ( is_null( $this->_variables ) ) { - $this->variables(); - } - return isset( $this->_variables[$name] ) ? $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] = array(); - - $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 = array(); - $rulesetNodes = array(); - foreach ( $this->rules as $rule ) { - - $class = get_class( $rule ); - if ( ( $class === 'Less_Tree_Media' ) || ( $class === 'Less_Tree_Directive' ) || ( $this->root && $class === 'Less_Tree_Comment' ) || ( $class === '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 ) { - - /* - debugInfo = tree.debugInfo(env, this, tabSetStr); - - if (debugInfo) { - output.add(debugInfo); - output.add(tabSetStr); - } - */ - - $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(); - } - } - - public function joinSelectors( $context, $selectors ) { - $paths = array(); - if ( is_array( $selectors ) ) { - foreach ( $selectors as $selector ) { - $this->joinSelector( $paths, $context, $selector ); - } - } - return $paths; - } - - public function joinSelector( &$paths, $context, $selector ) { - $hasParentSelector = false; - - foreach ( $selector->elements as $el ) { - if ( $el->value === '&' ) { - $hasParentSelector = true; - } - } - - if ( !$hasParentSelector ) { - if ( $context ) { - foreach ( $context as $context_el ) { - $paths[] = array_merge( $context_el, array( $selector ) ); - } - } else { - $paths[] = array( $selector ); - } - return; - } - - // 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 = array(); - // 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 = array( array() ); - - foreach ( $selector->elements as $el ) { - - // non parent reference elements just get added - if ( $el->value !== '&' ) { - $currentElements[] = $el; - } else { - // the new list of selectors to add - $selectorsMultiplied = array(); - - // merge the current list of non parent selector elements - // on to the current list of selectors to add - if ( $currentElements ) { - $this->mergeElementsOnToSelectors( $currentElements, $newSelectors ); - } - - // loop through our current selectors - 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 = array_slice( $sel[0]->elements, 0 ); - $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 - - // our new selector path - $newSelectorPath = array(); - // selectors from the parent after the join - $afterParentJoin = array(); - $newJoinedSelectorEmpty = true; - - // 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 ( $sel ) { - $newSelectorPath = $sel; - $lastSelector = array_pop( $newSelectorPath ); - $newJoinedSelector = $selector->createDerived( array_slice( $lastSelector->elements, 0 ) ); - $newJoinedSelectorEmpty = false; - } else { - $newJoinedSelector = $selector->createDerived( array() ); - } - - // put together the parent selectors after the join - if ( count( $parentSel ) > 1 ) { - $afterParentJoin = array_merge( $afterParentJoin, array_slice( $parentSel, 1 ) ); - } - - if ( $parentSel ) { - $newJoinedSelectorEmpty = false; - - // join the elements so far with the first part of the parent - $newJoinedSelector->elements[] = new Less_Tree_Element( $el->combinator, $parentSel[0]->elements[0]->value, $el->index, $el->currentFileInfo ); - - $newJoinedSelector->elements = array_merge( $newJoinedSelector->elements, array_slice( $parentSel[0]->elements, 1 ) ); - } - - if ( !$newJoinedSelectorEmpty ) { - // now add the joined selector - $newSelectorPath[] = $newJoinedSelector; - } - - // and the rest of the parent - $newSelectorPath = array_merge( $newSelectorPath, $afterParentJoin ); - - // add that to our new set of selectors - $selectorsMultiplied[] = $newSelectorPath; - } - } - } - - // our new selectors has been multiplied, so reset the state - $newSelectors = $selectorsMultiplied; - $currentElements = array(); - } - } - - // if we have any elements left over (e.g. .a& .b == .b) - // add them on to all the current selectors - if ( $currentElements ) { - $this->mergeElementsOnToSelectors( $currentElements, $newSelectors ); - } - foreach ( $newSelectors as $new_sel ) { - if ( $new_sel ) { - $paths[] = $new_sel; - } - } - } - - function mergeElementsOnToSelectors( $elements, &$selectors ) { - if ( !$selectors ) { - $selectors[] = array( 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/less.php/lib/Less/Tree/RulesetCall.php b/less.php/lib/Less/Tree/RulesetCall.php deleted file mode 100755 index 079ff4f..0000000 --- a/less.php/lib/Less/Tree/RulesetCall.php +++ /dev/null @@ -1,26 +0,0 @@ -variable = $variable; - } - - public function accept( $visitor ) { - } - - public function compile( $env ) { - $variable = new Less_Tree_Variable( $this->variable ); - $detachedRuleset = $variable->compile( $env ); - return $detachedRuleset->callEval( $env ); - } -} diff --git a/less.php/lib/Less/Tree/Selector.php b/less.php/lib/Less/Tree/Selector.php deleted file mode 100755 index 7ecfc6a..0000000 --- a/less.php/lib/Less/Tree/Selector.php +++ /dev/null @@ -1,165 +0,0 @@ -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 ? $extendList : $this->extendList ), null, $this->index, $this->currentFileInfo, $this->isReferenced ); - $newSelector->evaldCondition = $evaldCondition ? $evaldCondition : $this->evaldCondition; - 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 = array(); - $this->_oelements_assoc = array(); - - $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 = array(); - foreach ( $this->elements as $el ) { - $elements[] = $el->compile( $env ); - } - - $extendList = array(); - 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/less.php/lib/Less/Tree/UnicodeDescriptor.php b/less.php/lib/Less/Tree/UnicodeDescriptor.php deleted file mode 100755 index 38e0526..0000000 --- a/less.php/lib/Less/Tree/UnicodeDescriptor.php +++ /dev/null @@ -1,28 +0,0 @@ -value = $value; - } - - /** - * @see Less_Tree::genCSS - */ - public function genCSS( $output ) { - $output->add( $this->value ); - } - - public function compile() { - return $this; - } -} diff --git a/less.php/lib/Less/Tree/Unit.php b/less.php/lib/Less/Tree/Unit.php deleted file mode 100755 index 29230df..0000000 --- a/less.php/lib/Less/Tree/Unit.php +++ /dev/null @@ -1,142 +0,0 @@ -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 !!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 = array(); - - 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 = array(); - $backup = null; - - foreach ( $this->numerator as $atomicUnit ) { - if ( !$backup ) { - $backup = $atomicUnit; - } - $counter[$atomicUnit] = ( isset( $counter[$atomicUnit] ) ? $counter[$atomicUnit] : 0 ) + 1; - } - - foreach ( $this->denominator as $atomicUnit ) { - if ( !$backup ) { - $backup = $atomicUnit; - } - $counter[$atomicUnit] = ( isset( $counter[$atomicUnit] ) ? $counter[$atomicUnit] : 0 ) - 1; - } - - $this->numerator = array(); - $this->denominator = array(); - - 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/less.php/lib/Less/Tree/UnitConversions.php b/less.php/lib/Less/Tree/UnitConversions.php deleted file mode 100755 index 7f857fb..0000000 --- a/less.php/lib/Less/Tree/UnitConversions.php +++ /dev/null @@ -1,35 +0,0 @@ - 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 = array( - 's' => 1, - 'ms' => 0.001 - ); - - public static $angle = array( - 'rad' => 0.1591549430919, // 1/(2*M_PI), - 'deg' => 0.002777778, // 1/360, - 'grad' => 0.0025, // 1/400, - 'turn' => 1 - ); - -} diff --git a/less.php/lib/Less/Tree/Url.php b/less.php/lib/Less/Tree/Url.php deleted file mode 100755 index 4e7f114..0000000 --- a/less.php/lib/Less/Tree/Url.php +++ /dev/null @@ -1,76 +0,0 @@ -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_Functions $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/less.php/lib/Less/Tree/Value.php b/less.php/lib/Less/Tree/Value.php deleted file mode 100755 index a4c0d85..0000000 --- a/less.php/lib/Less/Tree/Value.php +++ /dev/null @@ -1,47 +0,0 @@ -value = $value; - } - - public function accept( $visitor ) { - $this->value = $visitor->visitArray( $this->value ); - } - - public function compile( $env ) { - $ret = array(); - $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/less.php/lib/Less/Tree/Variable.php b/less.php/lib/Less/Tree/Variable.php deleted file mode 100755 index e36d3d4..0000000 --- a/less.php/lib/Less/Tree/Variable.php +++ /dev/null @@ -1,51 +0,0 @@ -name = $name; - $this->index = $index; - $this->currentFileInfo = $currentFileInfo; - } - - public function compile( $env ) { - if ( $this->name[1] === '@' ) { - $v = new Less_Tree_Variable( substr( $this->name, 1 ), $this->index + 1, $this->currentFileInfo ); - $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 ); - } - -} diff --git a/less.php/lib/Less/Version.php b/less.php/lib/Less/Version.php deleted file mode 100755 index 2d05c38..0000000 --- a/less.php/lib/Less/Version.php +++ /dev/null @@ -1,15 +0,0 @@ -_visitFnCache = get_class_methods( get_class( $this ) ); - $this->_visitFnCache = array_flip( $this->_visitFnCache ); - } - - public function visitObj( $node ) { - $funcName = 'visit'.$node->type; - if ( isset( $this->_visitFnCache[$funcName] ) ) { - - $visitDeeper = true; - $this->$funcName( $node, $visitDeeper ); - - if ( $visitDeeper ) { - $node->accept( $this ); - } - - $funcName = $funcName . "Out"; - if ( isset( $this->_visitFnCache[$funcName] ) ) { - $this->$funcName( $node ); - } - - } else { - $node->accept( $this ); - } - - return $node; - } - - public function visitArray( $nodes ) { - array_map( array( $this,'visitObj' ), $nodes ); - return $nodes; - } -} diff --git a/less.php/lib/Less/Visitor/extendFinder.php b/less.php/lib/Less/Visitor/extendFinder.php deleted file mode 100755 index 7d5d3fd..0000000 --- a/less.php/lib/Less/Visitor/extendFinder.php +++ /dev/null @@ -1,109 +0,0 @@ -contexts = array(); - $this->allExtendsStack = array( array() ); - parent::__construct(); - } - - /** - * @param Less_Tree_Ruleset $root - */ - public function run( $root ) { - $root = $this->visitObj( $root ); - $root->allExtends =& $this->allExtendsStack[0]; - return $root; - } - - public function visitRule( $ruleNode, &$visitDeeper ) { - $visitDeeper = false; - } - - public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ) { - $visitDeeper = false; - } - - public function visitRuleset( $rulesetNode ) { - if ( $rulesetNode->root ) { - return; - } - - $allSelectorsExtendList = array(); - - // get &:extend(.a); rules which apply to all selectors in this ruleset - if ( $rulesetNode->rules ) { - foreach ( $rulesetNode->rules as $rule ) { - if ( $rule instanceof Less_Tree_Extend ) { - $allSelectorsExtendList[] = $rule; - $rulesetNode->extendOnEveryPath = true; - } - } - } - - // now find every selector and apply the extends that apply to all extends - // and the ones which apply to an individual extend - foreach ( $rulesetNode->paths as $selectorPath ) { - $selector = end( $selectorPath ); // $selectorPath[ count($selectorPath)-1]; - - $j = 0; - foreach ( $selector->extendList as $extend ) { - $this->allExtendsStackPush( $rulesetNode, $selectorPath, $extend, $j ); - } - foreach ( $allSelectorsExtendList as $extend ) { - $this->allExtendsStackPush( $rulesetNode, $selectorPath, $extend, $j ); - } - } - - $this->contexts[] = $rulesetNode->selectors; - } - - public function allExtendsStackPush( $rulesetNode, $selectorPath, $extend, &$j ) { - $this->foundExtends = true; - $extend = clone $extend; - $extend->findSelfSelectors( $selectorPath ); - $extend->ruleset = $rulesetNode; - if ( $j === 0 ) { - $extend->firstExtendOnThisSelectorPath = true; - } - - $end_key = count( $this->allExtendsStack ) - 1; - $this->allExtendsStack[$end_key][] = $extend; - $j++; - } - - public function visitRulesetOut( $rulesetNode ) { - if ( !is_object( $rulesetNode ) || !$rulesetNode->root ) { - array_pop( $this->contexts ); - } - } - - public function visitMedia( $mediaNode ) { - $mediaNode->allExtends = array(); - $this->allExtendsStack[] =& $mediaNode->allExtends; - } - - public function visitMediaOut() { - array_pop( $this->allExtendsStack ); - } - - public function visitDirective( $directiveNode ) { - $directiveNode->allExtends = array(); - $this->allExtendsStack[] =& $directiveNode->allExtends; - } - - public function visitDirectiveOut() { - array_pop( $this->allExtendsStack ); - } -} diff --git a/less.php/lib/Less/Visitor/import.php b/less.php/lib/Less/Visitor/import.php deleted file mode 100755 index 7af96eb..0000000 --- a/less.php/lib/Less/Visitor/import.php +++ /dev/null @@ -1,137 +0,0 @@ -env = $evalEnv; - $this->importCount = 0; - parent::__construct(); - } - - - function run( $root ){ - $root = $this->visitObj($root); - $this->isFinished = true; - - //if( $this->importCount === 0) { - // $this->_finish(); - //} - } - - function visitImport($importNode, &$visitDeeper ){ - $importVisitor = $this; - $inlineCSS = $importNode->options['inline']; - - if( !$importNode->css || $inlineCSS ){ - $evaldImportNode = $importNode->compileForImport($this->env); - - if( $evaldImportNode && (!$evaldImportNode->css || $inlineCSS) ){ - $importNode = $evaldImportNode; - $this->importCount++; - $env = clone $this->env; - - if( (isset($importNode->options['multiple']) && $importNode->options['multiple']) ){ - $env->importMultiple = true; - } - - //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'],$importNode); - } - - if( !$path_and_uri ){ - $path_and_uri = $importNode->PathAndUri(); - } - - if( $path_and_uri ){ - list($full_path, $uri) = $path_and_uri; - }else{ - $full_path = $uri = $importNode->getPath(); - } - - - //import once - if( $importNode->skip( $full_path, $env) ){ - return array(); - } - - if( $importNode->options['inline'] ){ - //todo needs to reference css file not import - //$contents = new Less_Tree_Anonymous($importNode->root, 0, array('filename'=>$importNode->importedFilename), true ); - - Less_Parser::AddParsedFile($full_path); - $contents = new Less_Tree_Anonymous( file_get_contents($full_path), 0, array(), true ); - - if( $importNode->features ){ - return new Less_Tree_Media( array($contents), $importNode->features->value ); - } - - return array( $contents ); - } - - - // css ? - if( $importNode->css ){ - $features = ( $importNode->features ? $importNode->features->compile($env) : null ); - return new Less_Tree_Import( $importNode->compilePath( $env), $features, $importNode->options, $this->index); - } - - return $importNode->ParseImport( $full_path, $uri, $env ); - } - - } - - $visitDeeper = false; - return $importNode; - } - - - function visitRule( $ruleNode, &$visitDeeper ){ - $visitDeeper = false; - return $ruleNode; - } - - function visitDirective($directiveNode, $visitArgs){ - array_unshift($this->env->frames,$directiveNode); - return $directiveNode; - } - - function visitDirectiveOut($directiveNode) { - array_shift($this->env->frames); - } - - function visitMixinDefinition($mixinDefinitionNode, $visitArgs) { - array_unshift($this->env->frames,$mixinDefinitionNode); - return $mixinDefinitionNode; - } - - function visitMixinDefinitionOut($mixinDefinitionNode) { - array_shift($this->env->frames); - } - - function visitRuleset($rulesetNode, $visitArgs) { - array_unshift($this->env->frames,$rulesetNode); - return $rulesetNode; - } - - function visitRulesetOut($rulesetNode) { - array_shift($this->env->frames); - } - - function visitMedia($mediaNode, $visitArgs) { - array_unshift($this->env->frames, $mediaNode->ruleset); - return $mediaNode; - } - - function visitMediaOut($mediaNode) { - array_shift($this->env->frames); - } - -} -*/ diff --git a/less.php/lib/Less/Visitor/joinSelector.php b/less.php/lib/Less/Visitor/joinSelector.php deleted file mode 100755 index bb08ece..0000000 --- a/less.php/lib/Less/Visitor/joinSelector.php +++ /dev/null @@ -1,68 +0,0 @@ -visitObj( $root ); - } - - public function visitRule( $ruleNode, &$visitDeeper ) { - $visitDeeper = false; - } - - public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ) { - $visitDeeper = false; - } - - public function visitRuleset( $rulesetNode ) { - $paths = array(); - - if ( !$rulesetNode->root ) { - $selectors = array(); - - if ( $rulesetNode->selectors && $rulesetNode->selectors ) { - foreach ( $rulesetNode->selectors as $selector ) { - if ( $selector->getIsOutput() ) { - $selectors[] = $selector; - } - } - } - - if ( !$selectors ) { - $rulesetNode->selectors = null; - $rulesetNode->rules = null; - } else { - $context = end( $this->contexts ); // $context = $this->contexts[ count($this->contexts) - 1]; - $paths = $rulesetNode->joinSelectors( $context, $selectors ); - } - - $rulesetNode->paths = $paths; - } - - $this->contexts[] = $paths; // different from less.js. Placed after joinSelectors() so that $this->contexts will get correct $paths - } - - public function visitRulesetOut() { - array_pop( $this->contexts ); - } - - public function visitMedia( $mediaNode ) { - $context = end( $this->contexts ); // $context = $this->contexts[ count($this->contexts) - 1]; - - if ( !count( $context ) || ( is_object( $context[0] ) && $context[0]->multiMedia ) ) { - $mediaNode->rules[0]->root = true; - } - } - -} diff --git a/less.php/lib/Less/Visitor/processExtends.php b/less.php/lib/Less/Visitor/processExtends.php deleted file mode 100755 index 65082a4..0000000 --- a/less.php/lib/Less/Visitor/processExtends.php +++ /dev/null @@ -1,441 +0,0 @@ -run( $root ); - if ( !$extendFinder->foundExtends ) { - return $root; - } - - $root->allExtends = $this->doExtendChaining( $root->allExtends, $root->allExtends ); - - $this->allExtendsStack = array(); - $this->allExtendsStack[] = &$root->allExtends; - - return $this->visitObj( $root ); - } - - private function doExtendChaining( $extendsList, $extendsListTarget, $iterationCount = 0 ) { - // - // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting - // the selector we would do normally, but we are also adding an extend with the same target selector - // this means this new extend can then go and alter other extends - // - // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors - // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if - // we look at each selector at a time, as is done in visitRuleset - - $extendsToAdd = array(); - - // loop through comparing every extend with every target extend. - // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place - // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one - // and the second is the target. - // the separation into two lists allows us to process a subset of chains with a bigger set, as is the - // case when processing media queries - for ( $extendIndex = 0, $extendsList_len = count( $extendsList ); $extendIndex < $extendsList_len; $extendIndex++ ) { - for ( $targetExtendIndex = 0; $targetExtendIndex < count( $extendsListTarget ); $targetExtendIndex++ ) { - - $extend = $extendsList[$extendIndex]; - $targetExtend = $extendsListTarget[$targetExtendIndex]; - - // Optimisation: Explicit reference,  - if ( \array_key_exists( $targetExtend->object_id, $extend->parent_ids ) ) { - // ignore circular references - continue; - } - - // find a match in the target extends self selector (the bit before :extend) - $selectorPath = array( $targetExtend->selfSelectors[0] ); - $matches = $this->findMatch( $extend, $selectorPath ); - - if ( $matches ) { - - // we found a match, so for each self selector.. - foreach ( $extend->selfSelectors as $selfSelector ) { - - // process the extend as usual - $newSelector = $this->extendSelector( $matches, $selectorPath, $selfSelector ); - - // but now we create a new extend from it - $newExtend = new Less_Tree_Extend( $targetExtend->selector, $targetExtend->option, 0 ); - $newExtend->selfSelectors = $newSelector; - - // add the extend onto the list of extends for that selector - end( $newSelector )->extendList = array( $newExtend ); - // $newSelector[ count($newSelector)-1]->extendList = array($newExtend); - - // record that we need to add it. - $extendsToAdd[] = $newExtend; - $newExtend->ruleset = $targetExtend->ruleset; - - // remember its parents for circular references - $newExtend->parent_ids = array_merge( $newExtend->parent_ids, $targetExtend->parent_ids, $extend->parent_ids ); - - // only process the selector once.. if we have :extend(.a,.b) then multiple - // extends will look at the same selector path, so when extending - // we know that any others will be duplicates in terms of what is added to the css - if ( $targetExtend->firstExtendOnThisSelectorPath ) { - $newExtend->firstExtendOnThisSelectorPath = true; - $targetExtend->ruleset->paths[] = $newSelector; - } - } - } - } - } - - if ( $extendsToAdd ) { - // try to detect circular references to stop a stack overflow. - // may no longer be needed. $this->extendChainCount++; - if ( $iterationCount > 100 ) { - - try{ - $selectorOne = $extendsToAdd[0]->selfSelectors[0]->toCSS(); - $selectorTwo = $extendsToAdd[0]->selector->toCSS(); - }catch ( Exception $e ) { - $selectorOne = "{unable to calculate}"; - $selectorTwo = "{unable to calculate}"; - } - - throw new Less_Exception_Parser( "extend circular reference detected. One of the circular extends is currently:" . $selectorOne . ":extend(" . $selectorTwo . ")" ); - } - - // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... - $extendsToAdd = $this->doExtendChaining( $extendsToAdd, $extendsListTarget, $iterationCount + 1 ); - } - - return array_merge( $extendsList, $extendsToAdd ); - } - - protected function visitRule( $ruleNode, &$visitDeeper ) { - $visitDeeper = false; - } - - protected function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ) { - $visitDeeper = false; - } - - protected function visitSelector( $selectorNode, &$visitDeeper ) { - $visitDeeper = false; - } - - protected function visitRuleset( $rulesetNode ) { - if ( $rulesetNode->root ) { - return; - } - - $allExtends = end( $this->allExtendsStack ); - $paths_len = count( $rulesetNode->paths ); - - // look at each selector path in the ruleset, find any extend matches and then copy, find and replace - foreach ( $allExtends as $allExtend ) { - for ( $pathIndex = 0; $pathIndex < $paths_len; $pathIndex++ ) { - - // extending extends happens initially, before the main pass - if ( isset( $rulesetNode->extendOnEveryPath ) && $rulesetNode->extendOnEveryPath ) { - continue; - } - - $selectorPath = $rulesetNode->paths[$pathIndex]; - - if ( end( $selectorPath )->extendList ) { - continue; - } - - $this->ExtendMatch( $rulesetNode, $allExtend, $selectorPath ); - - } - } - } - - private function ExtendMatch( $rulesetNode, $extend, $selectorPath ) { - $matches = $this->findMatch( $extend, $selectorPath ); - - if ( $matches ) { - foreach ( $extend->selfSelectors as $selfSelector ) { - $rulesetNode->paths[] = $this->extendSelector( $matches, $selectorPath, $selfSelector ); - } - } - } - - private function findMatch( $extend, $haystackSelectorPath ) { - if ( !$this->HasMatches( $extend, $haystackSelectorPath ) ) { - return false; - } - - // - // look through the haystack selector path to try and find the needle - extend.selector - // returns an array of selector matches that can then be replaced - // - $needleElements = $extend->selector->elements; - $potentialMatches = array(); - $potentialMatches_len = 0; - $potentialMatch = null; - $matches = array(); - - // loop through the haystack elements - $haystack_path_len = count( $haystackSelectorPath ); - for ( $haystackSelectorIndex = 0; $haystackSelectorIndex < $haystack_path_len; $haystackSelectorIndex++ ) { - $hackstackSelector = $haystackSelectorPath[$haystackSelectorIndex]; - - $haystack_elements_len = count( $hackstackSelector->elements ); - for ( $hackstackElementIndex = 0; $hackstackElementIndex < $haystack_elements_len; $hackstackElementIndex++ ) { - - $haystackElement = $hackstackSelector->elements[$hackstackElementIndex]; - - // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. - if ( $extend->allowBefore || ( $haystackSelectorIndex === 0 && $hackstackElementIndex === 0 ) ) { - $potentialMatches[] = array( 'pathIndex' => $haystackSelectorIndex, 'index' => $hackstackElementIndex, 'matched' => 0, 'initialCombinator' => $haystackElement->combinator ); - $potentialMatches_len++; - } - - for ( $i = 0; $i < $potentialMatches_len; $i++ ) { - - $potentialMatch = &$potentialMatches[$i]; - $potentialMatch = $this->PotentialMatch( $potentialMatch, $needleElements, $haystackElement, $hackstackElementIndex ); - - // if we are still valid and have finished, test whether we have elements after and whether these are allowed - if ( $potentialMatch && $potentialMatch['matched'] === $extend->selector->elements_len ) { - $potentialMatch['finished'] = true; - - if ( !$extend->allowAfter && ( $hackstackElementIndex + 1 < $haystack_elements_len || $haystackSelectorIndex + 1 < $haystack_path_len ) ) { - $potentialMatch = null; - } - } - - // if null we remove, if not, we are still valid, so either push as a valid match or continue - if ( $potentialMatch ) { - if ( $potentialMatch['finished'] ) { - $potentialMatch['length'] = $extend->selector->elements_len; - $potentialMatch['endPathIndex'] = $haystackSelectorIndex; - $potentialMatch['endPathElementIndex'] = $hackstackElementIndex + 1; // index after end of match - $potentialMatches = array(); // we don't allow matches to overlap, so start matching again - $potentialMatches_len = 0; - $matches[] = $potentialMatch; - } - continue; - } - - array_splice( $potentialMatches, $i, 1 ); - $potentialMatches_len--; - $i--; - } - } - } - - return $matches; - } - - // Before going through all the nested loops, lets check to see if a match is possible - // Reduces Bootstrap 3.1 compile time from ~6.5s to ~5.6s - private function HasMatches( $extend, $haystackSelectorPath ) { - if ( !$extend->selector->cacheable ) { - return true; - } - - $first_el = $extend->selector->_oelements[0]; - - foreach ( $haystackSelectorPath as $hackstackSelector ) { - if ( !$hackstackSelector->cacheable ) { - return true; - } - - // Optimisation: Explicit reference,  - if ( \array_key_exists( $first_el, $hackstackSelector->_oelements_assoc ) ) { - return true; - } - } - - return false; - } - - /** - * @param integer $hackstackElementIndex - */ - private function PotentialMatch( $potentialMatch, $needleElements, $haystackElement, $hackstackElementIndex ) { - if ( $potentialMatch['matched'] > 0 ) { - - // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't - // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out - // what the resulting combinator will be - $targetCombinator = $haystackElement->combinator; - if ( $targetCombinator === '' && $hackstackElementIndex === 0 ) { - $targetCombinator = ' '; - } - - if ( $needleElements[ $potentialMatch['matched'] ]->combinator !== $targetCombinator ) { - return null; - } - } - - // if we don't match, null our match to indicate failure - if ( !$this->isElementValuesEqual( $needleElements[$potentialMatch['matched'] ]->value, $haystackElement->value ) ) { - return null; - } - - $potentialMatch['finished'] = false; - $potentialMatch['matched']++; - - return $potentialMatch; - } - - private function isElementValuesEqual( $elementValue1, $elementValue2 ) { - if ( $elementValue1 === $elementValue2 ) { - return true; - } - - if ( is_string( $elementValue1 ) || is_string( $elementValue2 ) ) { - return false; - } - - if ( $elementValue1 instanceof Less_Tree_Attribute ) { - return $this->isAttributeValuesEqual( $elementValue1, $elementValue2 ); - } - - $elementValue1 = $elementValue1->value; - if ( $elementValue1 instanceof Less_Tree_Selector ) { - return $this->isSelectorValuesEqual( $elementValue1, $elementValue2 ); - } - - return false; - } - - /** - * @param Less_Tree_Selector $elementValue1 - */ - private function isSelectorValuesEqual( $elementValue1, $elementValue2 ) { - $elementValue2 = $elementValue2->value; - if ( !( $elementValue2 instanceof Less_Tree_Selector ) || $elementValue1->elements_len !== $elementValue2->elements_len ) { - return false; - } - - for ( $i = 0; $i < $elementValue1->elements_len; $i++ ) { - - if ( $elementValue1->elements[$i]->combinator !== $elementValue2->elements[$i]->combinator ) { - if ( $i !== 0 || ( $elementValue1->elements[$i]->combinator || ' ' ) !== ( $elementValue2->elements[$i]->combinator || ' ' ) ) { - return false; - } - } - - if ( !$this->isElementValuesEqual( $elementValue1->elements[$i]->value, $elementValue2->elements[$i]->value ) ) { - return false; - } - } - - return true; - } - - /** - * @param Less_Tree_Attribute $elementValue1 - */ - private function isAttributeValuesEqual( $elementValue1, $elementValue2 ) { - if ( $elementValue1->op !== $elementValue2->op || $elementValue1->key !== $elementValue2->key ) { - return false; - } - - if ( !$elementValue1->value || !$elementValue2->value ) { - if ( $elementValue1->value || $elementValue2->value ) { - return false; - } - return true; - } - - $elementValue1 = ( $elementValue1->value->value ? $elementValue1->value->value : $elementValue1->value ); - $elementValue2 = ( $elementValue2->value->value ? $elementValue2->value->value : $elementValue2->value ); - - return $elementValue1 === $elementValue2; - } - - private function extendSelector( $matches, $selectorPath, $replacementSelector ) { - // for a set of matches, replace each match with the replacement selector - - $currentSelectorPathIndex = 0; - $currentSelectorPathElementIndex = 0; - $path = array(); - $selectorPath_len = count( $selectorPath ); - - for ( $matchIndex = 0, $matches_len = count( $matches ); $matchIndex < $matches_len; $matchIndex++ ) { - - $match = $matches[$matchIndex]; - $selector = $selectorPath[ $match['pathIndex'] ]; - - $firstElement = new Less_Tree_Element( - $match['initialCombinator'], - $replacementSelector->elements[0]->value, - $replacementSelector->elements[0]->index, - $replacementSelector->elements[0]->currentFileInfo - ); - - if ( $match['pathIndex'] > $currentSelectorPathIndex && $currentSelectorPathElementIndex > 0 ) { - $last_path = end( $path ); - $last_path->elements = array_merge( $last_path->elements, array_slice( $selectorPath[$currentSelectorPathIndex]->elements, $currentSelectorPathElementIndex ) ); - $currentSelectorPathElementIndex = 0; - $currentSelectorPathIndex++; - } - - $newElements = array_merge( - array_slice( $selector->elements, $currentSelectorPathElementIndex, ( $match['index'] - $currentSelectorPathElementIndex ) ), // last parameter of array_slice is different than the last parameter of javascript's slice - array( $firstElement ), - array_slice( $replacementSelector->elements, 1 ) - ); - - if ( $currentSelectorPathIndex === $match['pathIndex'] && $matchIndex > 0 ) { - $last_key = count( $path ) - 1; - $path[$last_key]->elements = array_merge( $path[$last_key]->elements, $newElements ); - } else { - $path = array_merge( $path, array_slice( $selectorPath, $currentSelectorPathIndex, $match['pathIndex'] ) ); - $path[] = new Less_Tree_Selector( $newElements ); - } - - $currentSelectorPathIndex = $match['endPathIndex']; - $currentSelectorPathElementIndex = $match['endPathElementIndex']; - if ( $currentSelectorPathElementIndex >= count( $selectorPath[$currentSelectorPathIndex]->elements ) ) { - $currentSelectorPathElementIndex = 0; - $currentSelectorPathIndex++; - } - } - - if ( $currentSelectorPathIndex < $selectorPath_len && $currentSelectorPathElementIndex > 0 ) { - $last_path = end( $path ); - $last_path->elements = array_merge( $last_path->elements, array_slice( $selectorPath[$currentSelectorPathIndex]->elements, $currentSelectorPathElementIndex ) ); - $currentSelectorPathIndex++; - } - - $slice_len = $selectorPath_len - $currentSelectorPathIndex; - $path = array_merge( $path, array_slice( $selectorPath, $currentSelectorPathIndex, $slice_len ) ); - - return $path; - } - - protected function visitMedia( $mediaNode ) { - $newAllExtends = array_merge( $mediaNode->allExtends, end( $this->allExtendsStack ) ); - $this->allExtendsStack[] = $this->doExtendChaining( $newAllExtends, $mediaNode->allExtends ); - } - - protected function visitMediaOut() { - array_pop( $this->allExtendsStack ); - } - - protected function visitDirective( $directiveNode ) { - $newAllExtends = array_merge( $directiveNode->allExtends, end( $this->allExtendsStack ) ); - $this->allExtendsStack[] = $this->doExtendChaining( $newAllExtends, $directiveNode->allExtends ); - } - - protected function visitDirectiveOut() { - array_pop( $this->allExtendsStack ); - } - -} diff --git a/less.php/lib/Less/Visitor/toCSS.php b/less.php/lib/Less/Visitor/toCSS.php deleted file mode 100755 index e90f211..0000000 --- a/less.php/lib/Less/Visitor/toCSS.php +++ /dev/null @@ -1,280 +0,0 @@ -visitObj( $root ); - } - - public function visitRule( $ruleNode ) { - if ( $ruleNode->variable ) { - return array(); - } - return $ruleNode; - } - - public function visitMixinDefinition( $mixinNode ) { - // mixin definitions do not get eval'd - this means they keep state - // so we have to clear that state here so it isn't used if toCSS is called twice - $mixinNode->frames = array(); - return array(); - } - - public function visitExtend() { - return array(); - } - - public function visitComment( $commentNode ) { - if ( $commentNode->isSilent() ) { - return array(); - } - return $commentNode; - } - - public function visitMedia( $mediaNode, &$visitDeeper ) { - $mediaNode->accept( $this ); - $visitDeeper = false; - - if ( !$mediaNode->rules ) { - return array(); - } - return $mediaNode; - } - - public function visitDirective( $directiveNode ) { - if ( isset( $directiveNode->currentFileInfo['reference'] ) && ( !property_exists( $directiveNode, 'isReferenced' ) || !$directiveNode->isReferenced ) ) { - return array(); - } - if ( $directiveNode->name === '@charset' ) { - // Only output the debug info together with subsequent @charset definitions - // a comment (or @media statement) before the actual @charset directive would - // be considered illegal css as it has to be on the first line - if ( isset( $this->charset ) && $this->charset ) { - - // if( $directiveNode->debugInfo ){ - // $comment = new Less_Tree_Comment('/* ' . str_replace("\n",'',$directiveNode->toCSS())." */\n"); - // $comment->debugInfo = $directiveNode->debugInfo; - // return $this->visit($comment); - //} - - return array(); - } - $this->charset = true; - } - return $directiveNode; - } - - public function checkPropertiesInRoot( $rulesetNode ) { - if ( !$rulesetNode->firstRoot ) { - return; - } - - foreach ( $rulesetNode->rules as $ruleNode ) { - if ( $ruleNode instanceof Less_Tree_Rule && !$ruleNode->variable ) { - $msg = "properties must be inside selector blocks, they cannot be in the root. Index ".$ruleNode->index.( $ruleNode->currentFileInfo ? ( ' Filename: '.$ruleNode->currentFileInfo['filename'] ) : null ); - throw new Less_Exception_Compiler( $msg ); - } - } - } - - public function visitRuleset( $rulesetNode, &$visitDeeper ) { - $visitDeeper = false; - - $this->checkPropertiesInRoot( $rulesetNode ); - - if ( $rulesetNode->root ) { - return $this->visitRulesetRoot( $rulesetNode ); - } - - $rulesets = array(); - $rulesetNode->paths = $this->visitRulesetPaths( $rulesetNode ); - - // Compile rules and rulesets - $nodeRuleCnt = $rulesetNode->rules ? count( $rulesetNode->rules ) : 0; - for ( $i = 0; $i < $nodeRuleCnt; ) { - $rule = $rulesetNode->rules[$i]; - - if ( property_exists( $rule, 'rules' ) ) { - // visit because we are moving them out from being a child - $rulesets[] = $this->visitObj( $rule ); - array_splice( $rulesetNode->rules, $i, 1 ); - $nodeRuleCnt--; - continue; - } - $i++; - } - - // accept the visitor to remove rules and refactor itself - // then we can decide now whether we want it or not - if ( $nodeRuleCnt > 0 ) { - $rulesetNode->accept( $this ); - - if ( $rulesetNode->rules ) { - - if ( count( $rulesetNode->rules ) > 1 ) { - $this->_mergeRules( $rulesetNode->rules ); - $this->_removeDuplicateRules( $rulesetNode->rules ); - } - - // now decide whether we keep the ruleset - if ( $rulesetNode->paths ) { - // array_unshift($rulesets, $rulesetNode); - array_splice( $rulesets, 0, 0, array( $rulesetNode ) ); - } - } - - } - - if ( count( $rulesets ) === 1 ) { - return $rulesets[0]; - } - return $rulesets; - } - - /** - * Helper function for visitiRuleset - * - * return array|Less_Tree_Ruleset - */ - private function visitRulesetRoot( $rulesetNode ) { - $rulesetNode->accept( $this ); - if ( $rulesetNode->firstRoot || $rulesetNode->rules ) { - return $rulesetNode; - } - return array(); - } - - /** - * Helper function for visitRuleset() - * - * @return array - */ - private function visitRulesetPaths( $rulesetNode ) { - $paths = array(); - foreach ( $rulesetNode->paths as $p ) { - if ( $p[0]->elements[0]->combinator === ' ' ) { - $p[0]->elements[0]->combinator = ''; - } - - foreach ( $p as $pi ) { - if ( $pi->getIsReferenced() && $pi->getIsOutput() ) { - $paths[] = $p; - break; - } - } - } - - return $paths; - } - - protected function _removeDuplicateRules( &$rules ) { - // remove duplicates - $ruleCache = array(); - for ( $i = count( $rules ) - 1; $i >= 0; $i-- ) { - $rule = $rules[$i]; - if ( $rule instanceof Less_Tree_Rule || $rule instanceof Less_Tree_NameValue ) { - - if ( !isset( $ruleCache[$rule->name] ) ) { - $ruleCache[$rule->name] = $rule; - } else { - $ruleList =& $ruleCache[$rule->name]; - - if ( $ruleList instanceof Less_Tree_Rule || $ruleList instanceof Less_Tree_NameValue ) { - $ruleList = $ruleCache[$rule->name] = array( $ruleCache[$rule->name]->toCSS() ); - } - - $ruleCSS = $rule->toCSS(); - if ( array_search( $ruleCSS, $ruleList ) !== false ) { - array_splice( $rules, $i, 1 ); - } else { - $ruleList[] = $ruleCSS; - } - } - } - } - } - - protected function _mergeRules( &$rules ) { - $groups = array(); - - // obj($rules); - - $rules_len = count( $rules ); - for ( $i = 0; $i < $rules_len; $i++ ) { - $rule = $rules[$i]; - - if ( ( $rule instanceof Less_Tree_Rule ) && $rule->merge ) { - - $key = $rule->name; - if ( $rule->important ) { - $key .= ',!'; - } - - if ( !isset( $groups[$key] ) ) { - $groups[$key] = array(); - } else { - array_splice( $rules, $i--, 1 ); - $rules_len--; - } - - $groups[$key][] = $rule; - } - } - - foreach ( $groups as $parts ) { - - if ( count( $parts ) > 1 ) { - $rule = $parts[0]; - $spacedGroups = array(); - $lastSpacedGroup = array(); - $parts_mapped = array(); - foreach ( $parts as $p ) { - if ( $p->merge === '+' ) { - if ( $lastSpacedGroup ) { - $spacedGroups[] = self::toExpression( $lastSpacedGroup ); - } - $lastSpacedGroup = array(); - } - $lastSpacedGroup[] = $p; - } - - $spacedGroups[] = self::toExpression( $lastSpacedGroup ); - $rule->value = self::toValue( $spacedGroups ); - } - } - - } - - public static function toExpression( $values ) { - $mapped = array(); - foreach ( $values as $p ) { - $mapped[] = $p->value; - } - return new Less_Tree_Expression( $mapped ); - } - - public static function toValue( $values ) { - // return new Less_Tree_Value($values); ?? - - $mapped = array(); - foreach ( $values as $p ) { - $mapped[] = $p; - } - return new Less_Tree_Value( $mapped ); - } -} diff --git a/less.php/lib/Less/VisitorReplacing.php b/less.php/lib/Less/VisitorReplacing.php deleted file mode 100755 index cd401ad..0000000 --- a/less.php/lib/Less/VisitorReplacing.php +++ /dev/null @@ -1,70 +0,0 @@ -type; - if ( isset( $this->_visitFnCache[$funcName] ) ) { - - $visitDeeper = true; - $node = $this->$funcName( $node, $visitDeeper ); - - if ( $node ) { - if ( $visitDeeper && is_object( $node ) ) { - $node->accept( $this ); - } - - $funcName = $funcName . "Out"; - if ( isset( $this->_visitFnCache[$funcName] ) ) { - $this->$funcName( $node ); - } - } - - } else { - $node->accept( $this ); - } - - return $node; - } - - public function visitArray( $nodes ) { - $newNodes = array(); - foreach ( $nodes as $node ) { - $evald = $this->visitObj( $node ); - if ( $evald ) { - if ( is_array( $evald ) ) { - self::flatten( $evald, $newNodes ); - } else { - $newNodes[] = $evald; - } - } - } - return $newNodes; - } - - public function flatten( $arr, &$out ) { - foreach ( $arr as $item ) { - if ( !is_array( $item ) ) { - $out[] = $item; - continue; - } - - foreach ( $item as $nestedItem ) { - if ( is_array( $nestedItem ) ) { - self::flatten( $nestedItem, $out ); - } else { - $out[] = $nestedItem; - } - } - } - - return $out; - } - -} diff --git a/mkht.php b/mkht.php index 7b94737..d0179b3 100755 --- a/mkht.php +++ b/mkht.php @@ -32,45 +32,21 @@ if (file_exists(SITE . '/config.ini')) $config = parse_ini_file(SITE . '/config.ini'); $config['title'] ??= ''; -$config['css'] ??= 1; $config['header'] ??= false; $config['author'] ??= NULL; $config['base-url'] ??= []; $config['center-index'] ??= false; $config['default-lang'] ??= NULL; +$config['announce-css'] ??= false; +$config['announce-feed'] ??= false; if (!isset($config['id'])) { $config['id'] = bin2hex(random_bytes(32)); file_put_contents(SITE . '/config.ini', 'id = "' . $config['id'] . '"' . LF, FILE_APPEND); } -// Less > CSS -if ($config['css'] == true) { - // Create CSS output directory if needed - if (!file_exists(SITE . '/css')) - mkdir(SITE . '/css', 0755); - - require ROOT . '/less.php/lib/Less/Autoloader.php'; - Less_Autoloader::register(); - - $colorScheme = [ - 'darkColor' => 'black', - 'lightColor' => 'white', - 'mainColor' => 'red', - ]; - - $options = [ - 'cache_dir' => SITE . '/css', - 'compress' => true, - ]; - - if (file_exists(SITE . '/style.less')) - $lessFiles = [ROOT . '/style.less' => '', SITE . '/style.less' => '']; - else - $lessFiles = [ROOT . '/style.less' => '']; - - define('CSS_FILENAME', Less_Cache::Get($lessFiles, $options, $colorScheme)); -} +if ($config['announce-css']) + copy(ROOT . '/style.css', SITE . '/mkht-php.css'); // Determine whether links need to use Onion or DNS function clearnetOrOnion($clearnet_url, $onion_url) { @@ -148,10 +124,7 @@ foreach ($files_dates as $src_page => $last_mod) { $gmilines[$key] = '[' . ($lnTitle[1] ?? $lnUrl[1]) . '](' . $lnUrl[1] . ')'; } } - $code = ''; - foreach ($gmilines as $line) - $code .= LF . $line; - file_put_contents($base_filepath . '.md', $code); + file_put_contents($base_filepath . '.md', implode(LF, $gmilines)); } // Compile Markdown to HTML @@ -211,8 +184,12 @@ foreach ($files_dates as $src_page => $last_mod) { if ($config['announce-feed']) echo '' . LF; - if ($config['announce-css']) - echo '' . LF; + if ($config['announce-css']) { + if (file_exists(SITE . '/style.css')) + echo '' . LF; + echo '' . LF; + } + if (file_exists(SITE . '/head.inc.html')) echo file_get_contents(SITE . '/head.inc.html'); @@ -296,6 +273,3 @@ foreach ($files_dates as $src_page => $last_mod) { } } file_put_contents(SITE . '/feed.atom', $feed . '' . LF); - -if ($config['css'] == true) - exec('gzip --keep --fast --force ' . SITE . '/css/' . CSS_FILENAME); diff --git a/style.less b/style.css old mode 100755 new mode 100644 similarity index 60% rename from style.less rename to style.css index a899a91..096857a --- a/style.less +++ b/style.css @@ -1,29 +1,37 @@ @light: ~"(prefers-color-scheme: light)"; @dark: ~"(prefers-color-scheme: dark)"; -@smallWidthScreen: ~"(max-width: 420px)"; + +:root { + --dark-color: #141312; + --light-color: #FFFFFF; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-color: var(--light-color); + --background-color: var(--dark-color); + --main-color: #FF1E00; + } +} + +@media (prefers-color-scheme: light) { + :root { + --foreground-color: var(--dark-color); + --background-color: var(--light-color); + --main-color: #FF0000; + } +} ::selection { - @media @light { - color: @lightColor; - background-color: @darkColor; - } - @media @dark { - color: @darkColor; - background-color: @lightColor; - } + color: var(--background-color); + background-color: var(--foreground-color); } * { padding: 0px; margin: 0px; - @media @light { - scrollbar-color: @darkColor @lightColor; - } - - @media @dark { - scrollbar-color: @lightColor @darkColor; - } + scrollbar-color: var(--foreground-color) var(--background-color); } body { @@ -32,17 +40,11 @@ body { line-height: 42px; margin: 20px; - @media @light { - background-color: @lightColor; - color: @darkColor; - } - - @media @dark { - background-color: @darkColor; - color: @lightColor; - } - - @media @smallWidthScreen { + background-color: var(--background-color); + color: var(--foreground-color); +} +@media (max-width: 420px) { + body { font-size: 26px; line-height: 38px; } @@ -51,13 +53,15 @@ body { main { margin-left: 20%; margin-right: 20%; - - @media (max-width: 1400px) { +} +@media (max-width: 1400px) { + main { margin-left: 10%; margin-right: 10%; } - - @media (max-width: 800px) { +} +@media (max-width: 800px) { + main { margin-left: 0px; margin-right: 0px; padding-left: 0px; @@ -70,24 +74,16 @@ a, a:visited { transition-property: color, border-color; transition-duration: 0.05s; transition-timing-function: linear; - - @media @light { - background-color: @lightColor; - color: @darkColor; - } - - @media @dark { - background-color: @darkColor; - color: @lightColor; - } - - &:hover, &:focus { - text-decoration: none; - color: @mainColor; - } + background-color: var(--background-color); + color: var(--foreground-color); } -.button { +a:hover, a:visited:hover, a:focus, a:focus:visited { + text-decoration: none; + color: var(--main-color); +} + +.small-button, .button { border-width: 2px; border-style: solid; padding: 8px 16px 8px 16px; @@ -95,23 +91,15 @@ a, a:visited { display: inline-block; border-radius: 14px; text-decoration: none; - - @media @light { - border-color: @darkColor; - } - @media @dark { - border-color: @lightColor; - } - - &:hover, &:focus { - color: @mainColor; - border: 2px solid @mainColor; - } - + border-color: var(--foreground-color); } -.smallButton { - .button(); +.small-button:hover, .button:hover, .small-button:focus, .button:focus { + color: var(--main-color); + border: 2px solid var(--main-color); +} + +.small-button { font-size: 80%; padding: 0px 16px 0px 16px; } @@ -132,14 +120,7 @@ img { border-width: 1px; border-style: solid; border-radius: 5px; - - @media @light { - border-color: @darkColor; - } - - @media @dark { - border-color: @lightColor; - } + border-color: var(--foreground-color); } strong { @@ -190,7 +171,7 @@ footer { flex-direction: column; } -// ----- TITLES ----- +/* ----- TITLES ----- */ h1, h2, h3, h4, h5, h6 { font-weight: normal; @@ -202,8 +183,9 @@ h1 { text-align: center; padding-top: 15px; margin-bottom: 20px; - - @media @smallWidthScreen { +} +@media (max-width: 420px) { + h1 { font-size: 45px; } } @@ -212,8 +194,9 @@ h2 { font-size: 60px; margin-top: 30px; margin-bottom: 15px; - - @media @smallWidthScreen { +} +@media (max-width: 420px) { + h2 { font-size: 40px; } } @@ -222,8 +205,9 @@ h3 { font-size: 42px; margin-top: 30px; margin-bottom: 15px; - - @media @smallWidthScreen { +} +@media (max-width: 420px) { + h3 { font-size: 35px; } }