From 8b239cb567becc7d67c1cfb5cfd3badb3ca508c2 Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Thu, 1 Jul 2010 23:24:06 +0300 Subject: [PATCH 1/8] fixed package to reference to README instead of README.markdown (symfony plugins strict standart). You can make symlink to README.markdown --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index ca7d2a1..3fcd4f4 100644 --- a/package.xml +++ b/package.xml @@ -23,7 +23,7 @@ - - + From 4ebef6c2c5aa78f02ba99f574f3d4b64bfd701b4 Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 13:47:32 +0300 Subject: [PATCH 2/8] renamed LessCss herlper to LESS --- lib/helper/LESSHelper.php | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/helper/LESSHelper.php diff --git a/lib/helper/LESSHelper.php b/lib/helper/LESSHelper.php new file mode 100644 index 0000000..47f12c0 --- /dev/null +++ b/lib/helper/LESSHelper.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * LessCssHelper handles the less css stylesheets + * + * @package sfLESSPlugin + * @subpackage helper + * @author Victor Berchet + * @version 1.0.0 + */ +use_helper('Asset'); + +/** + * Returns tags for all stylesheets configured in view.yml or added to the response object. + * + * You can use this helper to decide the location of stylesheets in pages. + * By default, if you don't call this helper, symfony will automatically include stylesheets before . + * Calling this helper disables this behavior. + * + * @return string tags + */ +function get_less_stylesheets() +{ + $response = sfContext::getInstance()->getResponse(); + sfConfig::set('symfony.asset.stylesheets_included', true); + + sfLESS::findAndFixContentLinks($response, sfConfig::get('app_sf_less_plugin_use_js', false)); + + $html = ''; + foreach ($response->getStylesheets() as $file => $options) + { + $html .= stylesheet_tag($file, $options); + } + + return $html; +} + +/** + * Prints tags for all stylesheets configured in view.yml or added to the response object. + * + * @see get_stylesheets() + */ +function include_less_stylesheets() +{ + echo get_less_stylesheets(); +} \ No newline at end of file From db68c4d9bda3dda7058e132ce79846b815a24116 Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 13:48:41 +0300 Subject: [PATCH 3/8] rename --- lib/helper/LessCssHelper.php | 54 ------------------------------------ 1 file changed, 54 deletions(-) delete mode 100644 lib/helper/LessCssHelper.php diff --git a/lib/helper/LessCssHelper.php b/lib/helper/LessCssHelper.php deleted file mode 100644 index 47f12c0..0000000 --- a/lib/helper/LessCssHelper.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * LessCssHelper handles the less css stylesheets - * - * @package sfLESSPlugin - * @subpackage helper - * @author Victor Berchet - * @version 1.0.0 - */ -use_helper('Asset'); - -/** - * Returns tags for all stylesheets configured in view.yml or added to the response object. - * - * You can use this helper to decide the location of stylesheets in pages. - * By default, if you don't call this helper, symfony will automatically include stylesheets before . - * Calling this helper disables this behavior. - * - * @return string tags - */ -function get_less_stylesheets() -{ - $response = sfContext::getInstance()->getResponse(); - sfConfig::set('symfony.asset.stylesheets_included', true); - - sfLESS::findAndFixContentLinks($response, sfConfig::get('app_sf_less_plugin_use_js', false)); - - $html = ''; - foreach ($response->getStylesheets() as $file => $options) - { - $html .= stylesheet_tag($file, $options); - } - - return $html; -} - -/** - * Prints tags for all stylesheets configured in view.yml or added to the response object. - * - * @see get_stylesheets() - */ -function include_less_stylesheets() -{ - echo get_less_stylesheets(); -} \ No newline at end of file From f11f6a8fd6eca1bd5f0f36884def9c7f4f92b62f Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 13:49:38 +0300 Subject: [PATCH 4/8] refactored sfLESS class & moved getSepFixedPath && getProjectRelativePath to sfLESSUtils --- lib/sfLESS.class.php | 41 ++++++++------------------------------- lib/sfLESSUtils.class.php | 30 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/lib/sfLESS.class.php b/lib/sfLESS.class.php index 62cd44d..3955df6 100644 --- a/lib/sfLESS.class.php +++ b/lib/sfLESS.class.php @@ -100,34 +100,6 @@ public function getDebugInfo() ); } - /** - * Returns path with changed directory separators to unix-style (\ => /) - * - * @param string $path basic path - * - * @return string unix-style path - */ - public static function getSepFixedPath($path) - { - return str_replace(DIRECTORY_SEPARATOR, '/', $path); - } - - /** - * Returns relative path from the project root dir - * - * @param string $fullPath full path to file - * - * @return string relative path from the project root - */ - public static function getProjectRelativePath($fullPath) - { - return str_replace( - self::getSepFixedPath(sfConfig::get('sf_root_dir')) . '/', - '', - self::getSepFixedPath($fullPath) - ); - } - /** * Do we need to check dates before compile * @@ -175,7 +147,7 @@ public function setIsUseCompression($useCompression) */ static public function getCssPaths() { - return self::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/css/'; + return sfLESSUtils::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/css/'; } /** @@ -226,7 +198,7 @@ static public function isCssLessCompiled($dir, $entry) */ static public function getLessPaths() { - return self::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/less/'; + return sfLESSUtils::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/less/'; } /** @@ -271,13 +243,16 @@ static public function findAndFixContentLinks(sfWebResponse $response, $useJs) foreach ($response->getStylesheets() as $file => $options) { - if ('.less' === substr($file, -5) && (!isset($options['rel']) || 'stylesheet/less' !== $options['rel'])) + if ( + '.less' === substr($file, -5) && + (!isset($options['rel']) || 'stylesheet/less' !== $options['rel']) + ) { $response->removeStylesheet($file); if ($useJs) { $response->addStylesheet('/less/' . $file, '', array_merge($options, array('rel' => 'stylesheet/less'))); - $hasLess = true; + $hasLess = true; } else { @@ -290,7 +265,7 @@ static public function findAndFixContentLinks(sfWebResponse $response, $useJs) { if (sfConfig::get('symfony.asset.javascripts_included', false)) { - throw new LogicException("The stylesheets must be included before the javascript in your layout"); + throw new LogicException("The stylesheets must be included before the javascript in your layout (less.js requirement)"); } else { diff --git a/lib/sfLESSUtils.class.php b/lib/sfLESSUtils.class.php index b70d910..fd89af5 100644 --- a/lib/sfLESSUtils.class.php +++ b/lib/sfLESSUtils.class.php @@ -1,4 +1,5 @@ @@ -13,6 +14,7 @@ * @package sfLESSPlugin * @subpackage lib * @author Victor Berchet + * @author Victor Berchet * @version 1.0.0 */ @@ -53,4 +55,32 @@ public static function stripLessComments($less) $less = preg_replace('#//.*$#m', '', $less); return $less; } + + /** + * Returns path with changed directory separators to unix-style (\ => /) + * + * @param string $path basic path + * + * @return string unix-style path + */ + public static function getSepFixedPath($path) + { + return str_replace(DIRECTORY_SEPARATOR, '/', $path); + } + + /** + * Returns relative path from the project root dir + * + * @param string $fullPath full path to file + * + * @return string relative path from the project root + */ + public static function getProjectRelativePath($fullPath) + { + return str_replace( + self::getSepFixedPath(sfConfig::get('sf_root_dir')) . '/', + '', + self::getSepFixedPath($fullPath) + ); + } } \ No newline at end of file From c84aef38a53766ea825e1fef73886a6ff0b803ae Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 13:50:27 +0300 Subject: [PATCH 5/8] coding style guides --- lib/sfLESSDependency.class.php | 19 +++++++++++-------- lib/task/lessCompileTask.class.php | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/sfLESSDependency.class.php b/lib/sfLESSDependency.class.php index 8774f0c..2059cc4 100644 --- a/lib/sfLESSDependency.class.php +++ b/lib/sfLESSDependency.class.php @@ -1,4 +1,5 @@ @@ -28,8 +29,8 @@ class sfLESSDependency protected $check = false; /** - * @param string $path Base path (web root folder) - * @param boolean $check Whether to check for dependency + * @param string $path Base path (web root folder) + * @param boolean $check Whether to check for dependency */ public function __construct($path, $check) { @@ -47,8 +48,9 @@ public function __construct($path, $check) /** * Return the modification time of the file (optionally including its dependency) * - * @param string $file Filename - * @return integer|false The time the files was last modified (unix timestamp) + * @param string $file Filename + * + * @return integer|boolean The time the files was last modified (unix timestamp) */ public function getMtime($lessFile) { @@ -72,9 +74,10 @@ public function getMtime($lessFile) /** * Compute the dependencies of the file * - * @param file $lessFile A less file - * @param array $deps An array of pre-existing dependencies - * @return array The updated array of dependencies + * @param file $lessFile A less file + * @param array $deps An array of pre-existing dependencies + * + * @return array The updated array of dependencies */ protected function computeDependencies($lessFile, array $deps) { @@ -119,4 +122,4 @@ protected function computeDependencies($lessFile, array $deps) return array(); } } -} \ No newline at end of file +} diff --git a/lib/task/lessCompileTask.class.php b/lib/task/lessCompileTask.class.php index af58546..50cdae4 100644 --- a/lib/task/lessCompileTask.class.php +++ b/lib/task/lessCompileTask.class.php @@ -101,8 +101,8 @@ protected function execute($arguments = array(), $options = array()) if (isset($options['debug']) && $options['debug']) { $this->logSection('compiled', sprintf("%s => %s", - sfLESS::getProjectRelativePath($lessFile), - sfLESS::getProjectRelativePath(sfLESS::getCssPathOfLess($lessFile)) + sfLESSUtils::getProjectRelativePath($lessFile), + sfLESSUtils::getProjectRelativePath(sfLESS::getCssPathOfLess($lessFile)) ), null, 'COMMAND'); } else From 8530a132a8f9c9f4489d6bcfd4cd3b006f9e5138 Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 13:50:41 +0300 Subject: [PATCH 6/8] readme update to reflect latest changes --- README.markdown | 67 ++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/README.markdown b/README.markdown index 1542fc5..938b1a1 100755 --- a/README.markdown +++ b/README.markdown @@ -41,11 +41,15 @@ and enable plugin in your ProjectConfigurations class. ## Usage ## +### Prepare ### + After installation, you need to create directory `web/less`. Any LESS file placed in this directory, including subdirectories, will automatically be parsed through LESS and saved as a corresponding CSS file in `web/css`. Example: web/less/clients/screen.less => web/css/clients/screen.css +### Style partials ### + If you prefix a file with an underscore, it is considered to be a partial, and will not be parsed unless included in another file. Example: @@ -65,41 +69,41 @@ sfLESSPlugin can use 2 workflows to manage your *.less files: 1. Compile on browser side by `less.js`; 2. Compile on server side by `lessc`. -### Update your layout files ### +### prepare: Update layout ### -Update your layout php files (at least the ones using less stylesheets): +For both flows, you need to update your layout files (at least the ones using less stylesheets): * include the less css helper: - + * update the way stylesheets are included by changing `` for `` -### Compile on browser side ### +### 1st way: Compile on browser side ### -This is default plugin behaviour. In this behaviour, all stylesheets ending with `.less`, added: +This is default plugin behaviour. In this behaviour, all stylesheets ending with `.less`, added in: -* in your `view.yml` configs: +* your `view.yml` configs: - stylesheets: [header/main.less] - -* in a template view file: + stylesheets: [header/main.less] - +* a template view file: -In this case, it will be automatically changed from something like + + +In this case, it will be automatically changed from something like: -to +to link like: and will add link to `less.js` into javascripts list. -This will cause browser to parse your linked less files on the fly. +This will cause browser to parse your linked less files on the fly through `less.js`. -### Compile on server side ### +### 2nd way: Compile on server side ### In details, sfLESSPlugin server side compiler does the following: @@ -109,18 +113,24 @@ In details, sfLESSPlugin server side compiler does the following: You have to install 2 packages: -1. `node.js`; -2. `less.js`. +1. `node.js` - server side interp., based on Google V8 JS engine; +2. `less.js` - `LESS2`. You can install this with Node Package Manager (`npm install less`). After that, enable server behavior & disable browser behavior in `app.yml`: sf_less_plugin: - compile: true - use_js: false + compile: true + use_js: false In this case, sfLESSPlugin will try to find all your less files inside `web/less/*.less` & compile them into `web/css/*.css`, so you can link your less styles as default css stylesheets: - stylesheets: [main.css] + stylesheets: [main.css] + +or (best way) with: + + stylesheets: [main.less] + +so `include_less_stylesheets` helper will automatically change `.less` extension to `.css`, but you still will have ability to change compiler type (server side <-> browser side) on the fly with single change in `app.yml` ## Configuration ## @@ -128,16 +138,16 @@ sfLESSPlugin server side compiler rechecks `web/less/*.less` at every routes ini prod: sf_less_plugin: - compile: false + compile: false sfLESSPlugin server side compiler checks the dates of LESS & CSS files, and will by default compile again only if LESS file have been changed since last parsing . -When you use `@import` statements in your LESS files, you should also turn on dependencies checking in one of you app.yml: +When you use `@import` statements in your LESS files to include partials (styles with `_` prefix), you should also turn on dependencies checking (because, less compiler will not rerun on partials change) in one of you app.yml: - dev: - sf_less_plugin: - check_dates: true - check_dependencies: true + dev: + sf_less_plugin: + check_dates: true + check_dependencies: true **warning:** Checking for the dependencies will affect performances and should not be turned on in production @@ -145,15 +155,15 @@ The safest (but probably slowest) option is to enforce everytime compiling: dev: sf_less_plugin: - check_dates: false + check_dates: false -Also, sfLESSPlugin server side compiler has Web Debug Panel, from which you can view all styles to compile & can open them for edit in prefered editor. For that you need to configure sf_file_link_format in settings.yml. +Also, sfLESSPlugin server side compiler has Web Debug Panel, from which you can view all styles to compile & can open them for edit in prefered editor. For that you need to configure `sf_file_link_format` in `settings.yml`. Last but not least, you can enable CSS compression (remove of whitespaces, tabs & newlines) in server side compiler with: all: sf_less_plugin: - use_compression: true + use_compression: true ## Tasks ## @@ -191,6 +201,7 @@ less.js is maintained by Alexis Sellier [http://github.com/cloudhead](http://git ### github latest ### +* updated readme & some refactorings * dependency check improvements ### v1.1.0 released on 2010-07-01 ### From 6b0cc039c54f60416771e4c8237f762f10d3fcdf Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 13:53:40 +0300 Subject: [PATCH 7/8] code base movements --- lib/{ => debug}/sfWebDebugPanelLESS.class.php | 0 lib/{ => less}/sfLESS.class.php | 0 lib/{ => less}/sfLESSDependency.class.php | 0 lib/{ => less}/sfLESSUtils.class.php | 0 {lib/test => test}/fixtures/a/a.less | 0 {lib/test => test}/fixtures/b/b.less | 0 {lib/test => test}/fixtures/c/c.c.less | 0 {lib/test => test}/fixtures/d/d.less | 0 {lib/test => test}/fixtures/e/e.css | 0 {lib/test => test}/fixtures/not/not.less | 0 {lib/test => test}/fixtures/root.less | 0 {lib/test => test}/unit/dependencyTest.php | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename lib/{ => debug}/sfWebDebugPanelLESS.class.php (100%) rename lib/{ => less}/sfLESS.class.php (100%) rename lib/{ => less}/sfLESSDependency.class.php (100%) rename lib/{ => less}/sfLESSUtils.class.php (100%) rename {lib/test => test}/fixtures/a/a.less (100%) rename {lib/test => test}/fixtures/b/b.less (100%) rename {lib/test => test}/fixtures/c/c.c.less (100%) rename {lib/test => test}/fixtures/d/d.less (100%) rename {lib/test => test}/fixtures/e/e.css (100%) rename {lib/test => test}/fixtures/not/not.less (100%) rename {lib/test => test}/fixtures/root.less (100%) rename {lib/test => test}/unit/dependencyTest.php (100%) diff --git a/lib/sfWebDebugPanelLESS.class.php b/lib/debug/sfWebDebugPanelLESS.class.php similarity index 100% rename from lib/sfWebDebugPanelLESS.class.php rename to lib/debug/sfWebDebugPanelLESS.class.php diff --git a/lib/sfLESS.class.php b/lib/less/sfLESS.class.php similarity index 100% rename from lib/sfLESS.class.php rename to lib/less/sfLESS.class.php diff --git a/lib/sfLESSDependency.class.php b/lib/less/sfLESSDependency.class.php similarity index 100% rename from lib/sfLESSDependency.class.php rename to lib/less/sfLESSDependency.class.php diff --git a/lib/sfLESSUtils.class.php b/lib/less/sfLESSUtils.class.php similarity index 100% rename from lib/sfLESSUtils.class.php rename to lib/less/sfLESSUtils.class.php diff --git a/lib/test/fixtures/a/a.less b/test/fixtures/a/a.less similarity index 100% rename from lib/test/fixtures/a/a.less rename to test/fixtures/a/a.less diff --git a/lib/test/fixtures/b/b.less b/test/fixtures/b/b.less similarity index 100% rename from lib/test/fixtures/b/b.less rename to test/fixtures/b/b.less diff --git a/lib/test/fixtures/c/c.c.less b/test/fixtures/c/c.c.less similarity index 100% rename from lib/test/fixtures/c/c.c.less rename to test/fixtures/c/c.c.less diff --git a/lib/test/fixtures/d/d.less b/test/fixtures/d/d.less similarity index 100% rename from lib/test/fixtures/d/d.less rename to test/fixtures/d/d.less diff --git a/lib/test/fixtures/e/e.css b/test/fixtures/e/e.css similarity index 100% rename from lib/test/fixtures/e/e.css rename to test/fixtures/e/e.css diff --git a/lib/test/fixtures/not/not.less b/test/fixtures/not/not.less similarity index 100% rename from lib/test/fixtures/not/not.less rename to test/fixtures/not/not.less diff --git a/lib/test/fixtures/root.less b/test/fixtures/root.less similarity index 100% rename from lib/test/fixtures/root.less rename to test/fixtures/root.less diff --git a/lib/test/unit/dependencyTest.php b/test/unit/dependencyTest.php similarity index 100% rename from lib/test/unit/dependencyTest.php rename to test/unit/dependencyTest.php From ebf202c0d14fe25be4439175661c790e69a328c5 Mon Sep 17 00:00:00 2001 From: "ever.zet" Date: Mon, 5 Jul 2010 14:34:40 +0300 Subject: [PATCH 8/8] huuuge refactoring. Decoupled sfLESS to many small pieces --- config/sfLESSPluginConfiguration.class.php | 2 +- lib/config/LESSConfig.class.php | 121 +++++++++++ lib/config/sfLESSConfig.class.php | 52 +++++ lib/helper/LESSHelper.php | 5 +- lib/less/sfLESS.class.php | 240 +++------------------ lib/less/sfLESSListeners.php | 93 ++++++++ lib/less/sfLESSUtils.class.php | 49 ++++- lib/task/lessCompileTask.class.php | 28 ++- 8 files changed, 364 insertions(+), 226 deletions(-) create mode 100644 lib/config/LESSConfig.class.php create mode 100644 lib/config/sfLESSConfig.class.php create mode 100644 lib/less/sfLESSListeners.php diff --git a/config/sfLESSPluginConfiguration.class.php b/config/sfLESSPluginConfiguration.class.php index bc308ca..130607f 100644 --- a/config/sfLESSPluginConfiguration.class.php +++ b/config/sfLESSPluginConfiguration.class.php @@ -29,7 +29,7 @@ public function initialize() // Register listener to routing.load_configuration event $this->dispatcher->connect( 'context.load_factories', - array('sfLESS', 'findAndCompile') + array('sfLESSListeners', 'findAndCompile') ); // If app_sf_less_plugin_toolbar in app.yml is set to true (by default) diff --git a/lib/config/LESSConfig.class.php b/lib/config/LESSConfig.class.php new file mode 100644 index 0000000..3bfa101 --- /dev/null +++ b/lib/config/LESSConfig.class.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * sfLESSConfig is configuration manager. + * + * @package sfLESSPlugin + * @subpackage lib + * @author Konstantin Kudryashov + * @version 1.0.0 + */ +class sfLESSConfig +{ + /** + * Do we need to check dates before compile + * + * @var boolean + */ + protected $checkDates; + + /** + * Do we need compression for CSS files + * + * @var boolean + */ + protected $useCompression; + + /** + * Creates config instance + * + * @param boolean $checkDates whether we check dates before compile + * @param boolean $useCompression whether we compress result styles + */ + public function __construct($checkDates = true, $useCompression = false) + { + $this->checkDates = $checkDates; + $this->useCompression = $useCompression; + } + + /** + * Do we need to check dates before compile + * + * @return boolean + */ + public function isCheckDates() + { + return $this->checkDates; + } + + /** + * Set need of check dates before compile + * + * @param boolean $checkDates Do we need to check dates before compile + */ + public function setIsCheckDates($checkDates) + { + $this->checkDates = $checkDates; + } + + /** + * Do we need compression for CSS files + * + * @return boolean + */ + public function isUseCompression() + { + return $this->useCompression; + } + + /** + * Set need of compression for CSS files + * + * @param boolean $useCompression Do we need compression for CSS files + */ + public function setIsUseCompression($useCompression) + { + $this->useCompression = $useCompression; + } + + /** + * Returns paths to CSS files + * + * @return string a path to CSS files directory + */ + public function getCssPaths() + { + return 'web/css/'; + } + + /** + * Returns paths to LESS files + * + * @return string a path to LESS files directories + */ + public function getLessPaths() + { + return 'web/less/'; + } + + /** + * Returns debug info of the current state + * + * @return array state + */ + public function getDebugInfo() + { + return array( + 'dates' => var_export($this->isCheckDates(), true), + 'compress' => var_export($this->isUseCompression(), true), + 'less' => $this->getLessPaths(), + 'css' => $this->getCssPaths() + ); + } +} diff --git a/lib/config/sfLESSConfig.class.php b/lib/config/sfLESSConfig.class.php new file mode 100644 index 0000000..ac44884 --- /dev/null +++ b/lib/config/sfLESSConfig.class.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * sfLESS is helper class to provide LESS compiling in symfony projects. + * + * @package sfLESSPlugin + * @subpackage lib + * @author Konstantin Kudryashov + * @version 1.0.0 + */ +class sfLESSConfig extends LESSConfig +{ + /** + * @see LESSConfig + */ + public function isCheckDates() + { + return sfConfig::get('app_sf_less_plugin_check_dates', parent::isCheckDates()); + } + + /** + * @see LESSConfig + */ + public function isUseCompression() + { + return sfConfig::get('app_sf_less_plugin_use_compression', parent::isUseCompression()); + } + + /** + * @see LESSConfig + */ + public function getCssPaths() + { + return sfLESSUtils::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/css/'; + } + + /** + * @see LESSConfig + */ + public function getLessPaths() + { + return sfLESSUtils::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/less/'; + } +} diff --git a/lib/helper/LESSHelper.php b/lib/helper/LESSHelper.php index 47f12c0..7e9961e 100644 --- a/lib/helper/LESSHelper.php +++ b/lib/helper/LESSHelper.php @@ -14,6 +14,7 @@ * @package sfLESSPlugin * @subpackage helper * @author Victor Berchet + * @author Konstantin Kudryashov * @version 1.0.0 */ use_helper('Asset'); @@ -32,7 +33,9 @@ function get_less_stylesheets() $response = sfContext::getInstance()->getResponse(); sfConfig::set('symfony.asset.stylesheets_included', true); - sfLESS::findAndFixContentLinks($response, sfConfig::get('app_sf_less_plugin_use_js', false)); + sfLESSListeners::findAndFixContentLinks( + $response, sfConfig::get('app_sf_less_plugin_use_js', false) + ); $html = ''; foreach ($response->getStylesheets() as $file => $options) diff --git a/lib/less/sfLESS.class.php b/lib/less/sfLESS.class.php index 3955df6..426a1b8 100644 --- a/lib/less/sfLESS.class.php +++ b/lib/less/sfLESS.class.php @@ -22,47 +22,48 @@ class sfLESS * Array of LESS styles * * @var array - **/ + */ protected static $results = array(); /** * Errors of compiler * * @var array - **/ + */ protected static $errors = array(); /** - * Do we need to check dates before compile + * Current LESS file to be parsed. This var used to help output errors in callCompiler() * - * @var boolean + * @var string */ - protected $checkDates = true; + protected $currentFile; /** - * Do we need compression for CSS files + * LESS configuration manager * - * @var boolean + * @var LESSConfig */ - protected $useCompression = false; + protected $config; /** - * Current LESS file to be parsed. This var used to help output errors in callCompiler() + * Constructor * - * @var string + * @param LESSConfig $config configuration manager */ - protected $currentFile; + public function __construct(LESSConfig $config) + { + $this->config = $config; + } /** - * Constructor + * Returns configuration manager * - * @param boolean $checkDates Do we need to check dates before compile - * @param boolean $useCompression Do we need compression for CSS files + * @return LESSConfig configurator instance */ - public function __construct($checkDates = true, $useCompression = false) + public function getConfig() { - $this->setIsCheckDates($checkDates); - $this->setIsUseCompression($useCompression); + return $this->config; } /** @@ -85,120 +86,17 @@ public static function getCompileErrors() return self::$errors; } - /** - * Returns debug info of the current state - * - * @return array state - */ - public function getDebugInfo() - { - return array( - 'dates' => var_export($this->isCheckDates(), true), - 'compress' => var_export($this->isUseCompression(), true), - 'less' => $this->getLessPaths(), - 'css' => $this->getCssPaths() - ); - } - - /** - * Do we need to check dates before compile - * - * @return boolean - */ - public function isCheckDates() - { - return sfConfig::get('app_sf_less_plugin_check_dates', $this->checkDates); - } - - /** - * Set need of check dates before compile - * - * @param boolean $checkDates Do we need to check dates before compile - */ - public function setIsCheckDates($checkDates) - { - $this->checkDates = $checkDates; - } - - /** - * Do we need compression for CSS files - * - * @return boolean - */ - public function isUseCompression() - { - return sfConfig::get('app_sf_less_plugin_use_compression', $this->useCompression); - } - - /** - * Set need of compression for CSS files - * - * @param boolean $useCompression Do we need compression for CSS files - */ - public function setIsUseCompression($useCompression) - { - $this->useCompression = $useCompression; - } - - /** - * Returns paths to CSS files - * - * @return string a path to CSS files directory - */ - static public function getCssPaths() - { - return sfLESSUtils::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/css/'; - } - /** * Returns all CSS files under the CSS directory * * @return array an array of CSS files */ - static public function findCssFiles() + public function findCssFiles() { return sfFinder::type('file') - ->exec(array('sfLESS', 'isCssLessCompiled')) + ->exec(array('sfLESSUtils', 'isCssLessCompiled')) ->name('*.css') - ->in(self::getCssPaths()); - } - - /** - * Returns header text for CSS files - * - * @return string a header text for CSS files - */ - static protected function getCssHeader() - { - return '/* This CSS is autocompiled by LESS parser. Don\'t edit it manually. */'; - } - - /** - * Checks if CSS file was compiled from LESS - * - * @param string $dir a path to file - * @param string $entry a filename - * - * @return boolean - */ - static public function isCssLessCompiled($dir, $entry) - { - $file = $dir . '/' . $entry; - $fp = fopen( $file, 'r' ); - $line = stream_get_line($fp, 1024, "\n"); - fclose($fp); - - return (0 === strcmp($line, self::getCssHeader())); - } - - /** - * Returns paths to LESS files - * - * @return string a path to LESS files directories - */ - static public function getLessPaths() - { - return sfLESSUtils::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/less/'; + ->in($this->config->getCssPaths()); } /** @@ -206,13 +104,13 @@ static public function getLessPaths() * * @return array an array of LESS files */ - static public function findLessFiles() + public function findLessFiles() { return sfFinder::type('file') ->name('*.less') ->discard('_*') ->follow_link() - ->in(self::getLessPaths()); + ->in($this->config->getLessPaths()); } /** @@ -225,78 +123,12 @@ static public function findLessFiles() static public function getCssPathOfLess($lessFile) { return str_replace( - array(self::getLessPaths(), '.less'), - array(self::getCssPaths(), '.css'), + array($this->config->getLessPaths(), '.less'), + array($this->config->getCssPaths(), '.css'), $lessFile ); } - /** - * Update the response by fixing less stylesheet path and adding the less js engine when required - * - * @param sfWebResponse $response The response that will be sent back to the browser - * @param boolean $useJs Wether the less stylesheets should be processed by the js on the client side - */ - static public function findAndFixContentLinks(sfWebResponse $response, $useJs) - { - $hasLess = false; - - foreach ($response->getStylesheets() as $file => $options) - { - if ( - '.less' === substr($file, -5) && - (!isset($options['rel']) || 'stylesheet/less' !== $options['rel']) - ) - { - $response->removeStylesheet($file); - if ($useJs) - { - $response->addStylesheet('/less/' . $file, '', array_merge($options, array('rel' => 'stylesheet/less'))); - $hasLess = true; - } - else - { - $response->addStylesheet('/css/' . substr($file, 0, -5) . '.css', '', $options); - } - } - } - - if ($hasLess) - { - if (sfConfig::get('symfony.asset.javascripts_included', false)) - { - throw new LogicException("The stylesheets must be included before the javascript in your layout (less.js requirement)"); - } - else - { - $response->addJavascript( - sfConfig::get('app_sf_less_plugin_js_lib', '/sfLESSPlugin/js/less-1.0.30.min.js') - ); - } - } - } - - /** - * Listens to the routing.load_configuration event. Finds & compiles LESS files to CSS - * - * @param sfEvent $event an sfEvent instance - */ - static public function findAndCompile(sfEvent $event) - { - // Start compilation timer for debug info - $timer = sfTimerManager::getTimer('Less compilation'); - - // Create new helper object & compile LESS stylesheets with it - $lessHelper = new self; - foreach (self::findLessFiles() as $lessFile) - { - $lessHelper->compile($lessFile); - } - - // Stop timer - $timer->addTime(); - } - /** * Compiles LESS file to CSS * @@ -310,7 +142,7 @@ public function compile($lessFile) $timer = new sfTimer; // Gets CSS file path - $cssFile = self::getCssPathOfLess($lessFile); + $cssFile = $this->getCssPathOfLess($lessFile); // Checks if path exists & create if not if (!is_dir(dirname($cssFile))) @@ -324,7 +156,7 @@ public function compile($lessFile) $isCompiled = false; // If we check dates - recompile only really old CSS - if ($this->isCheckDates()) + if ($this->config->isCheckDates()) { try { @@ -356,18 +188,6 @@ public function compile($lessFile) return $isCompiled; } - /** - * Compress CSS by removing whitespaces, tabs, newlines, etc. - * - * @param string $css CSS to be compressed - * - * @return string compressed CSS - */ - static public function getCompressedCss($css) - { - return str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $css); - } - /** * Calls current LESS compiler for single file * @@ -394,13 +214,13 @@ public function callCompiler($lessFile, $cssFile) } // Compress CSS if we use compression - if ($this->isUseCompression()) + if ($this->config->isUseCompression()) { - $buffer = self::getCompressedCss($buffer); + $buffer = sfLESSUtils::getCompressedCss($buffer); } // Add compiler header to CSS & writes it to file - file_put_contents($cssFile, self::getCssHeader() . "\n\n" . $buffer); + file_put_contents($cssFile, sfLESSUtils::getCssHeader() . "\n\n" . $buffer); if ($setPermission) { diff --git a/lib/less/sfLESSListeners.php b/lib/less/sfLESSListeners.php new file mode 100644 index 0000000..31f03ca --- /dev/null +++ b/lib/less/sfLESSListeners.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * sfLESSListeners is LESS listeners manager for symfony. + * + * @package sfLESSPlugin + * @subpackage lib + * @author Konstantin Kudryashov + * @version 1.0.0 + */ +class sfLESSListeners +{ + /** + * Update the response by fixing less stylesheet path and adding the less js engine when required + * + * @param sfWebResponse $response The response that will be sent back to the browser + * @param boolean $useJs Wether the less stylesheets should be processed by the js on the client side + */ + static public function findAndFixContentLinks(sfWebResponse $response, $useJs) + { + $hasLess = false; + + foreach ($response->getStylesheets() as $file => $options) + { + if ( + '.less' === substr($file, -5) && + (!isset($options['rel']) || 'stylesheet/less' !== $options['rel']) + ) + { + $response->removeStylesheet($file); + if ($useJs) + { + $response->addStylesheet( + '/less/' . $file, '', array_merge($options, array('rel' => 'stylesheet/less')) + ); + $hasLess = true; + } + else + { + $response->addStylesheet('/css/' . substr($file, 0, -5) . '.css', '', $options); + } + } + } + + if ($hasLess) + { + if (sfConfig::get('symfony.asset.javascripts_included', false)) + { + throw new LogicException( + "The stylesheets must be included before the javascript in your layout" + ); + } + else + { + $response->addJavascript( + sfConfig::get('app_sf_less_plugin_js_lib', '/sfLESSPlugin/js/less-1.0.30.min.js') + ); + } + } + } + + /** + * Listens to the routing.load_configuration event. Finds & compiles LESS files to CSS + * + * @param sfEvent $event an sfEvent instance + */ + static public function findAndCompile(sfEvent $event) + { + // Start compilation timer for debug info + $timer = sfTimerManager::getTimer('Less compilation'); + + // Create config manager + $config = new sfLESSConfig; + + // Create new helper object & compile LESS stylesheets with it + $less = new sfLESS($config); + foreach ($less->findLessFiles() as $lessFile) + { + $less->compile($lessFile); + } + + // Stop timer + $timer->addTime(); + } +} diff --git a/lib/less/sfLESSUtils.class.php b/lib/less/sfLESSUtils.class.php index fd89af5..afa9976 100644 --- a/lib/less/sfLESSUtils.class.php +++ b/lib/less/sfLESSUtils.class.php @@ -14,7 +14,7 @@ * @package sfLESSPlugin * @subpackage lib * @author Victor Berchet - * @author Victor Berchet + * @author Konstantin Kudryashov * @version 1.0.0 */ @@ -44,8 +44,9 @@ public static function isPathAbsolute($path) /** * Strip comments from less content * - * @param string $less LESS code - * @return string LESS code without comments + * @param string $less LESS code + * + * @return string LESS code without comments */ public static function stripLessComments($less) { @@ -83,4 +84,44 @@ public static function getProjectRelativePath($fullPath) self::getSepFixedPath($fullPath) ); } -} \ No newline at end of file + + /** + * Checks if CSS file was compiled from LESS + * + * @param string $dir a path to file + * @param string $entry a filename + * + * @return boolean + */ + static public function isCssLessCompiled($dir, $entry) + { + $file = $dir . '/' . $entry; + $fp = fopen( $file, 'r' ); + $line = stream_get_line($fp, 1024, "\n"); + fclose($fp); + + return (0 === strcmp($line, self::getCssHeader())); + } + + /** + * Compress CSS by removing whitespaces, tabs, newlines, etc. + * + * @param string $css CSS to be compressed + * + * @return string compressed CSS + */ + static public function getCompressedCss($css) + { + return str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $css); + } + + /** + * Returns header text for CSS files + * + * @return string a header text for CSS files + */ + static public function getCssHeader() + { + return '/* This CSS is autocompiled by LESS parser. Don\'t edit it manually. */'; + } +} diff --git a/lib/task/lessCompileTask.class.php b/lib/task/lessCompileTask.class.php index 50cdae4..09bba28 100644 --- a/lib/task/lessCompileTask.class.php +++ b/lib/task/lessCompileTask.class.php @@ -66,49 +66,57 @@ protected function configure() */ protected function execute($arguments = array(), $options = array()) { + // Inits sfLESS instance for compilation help + $less = new sfLESS(new sfLESSConfig( + false, isset($options['compress']) && $options['compress'] + )); + // Remove old CSS files if --clean option specified if (isset($options['clean']) && $options['clean']) { - foreach (sfLESS::findCssFiles() as $cssFile) + foreach ($less->findCssFiles() as $cssFile) { if (!isset($arguments['file']) || (false !== strpos($cssFile, $arguments['file'] . '.css'))) { unlink($cssFile); - $this->logSection('removed', str_replace(sfLESS::getCssPaths(), '', $cssFile)); + $this->logSection( + 'removed', + str_replace($less->getConfig()->getCssPaths(), '', $cssFile) + ); } } } - // Inits sfLESS instance for compilation help - $lessHelper = new sfLESS(false, isset($options['compress']) && $options['compress']); - // Outputs debug info if (isset($options['debug']) && $options['debug']) { - foreach ($lessHelper->getDebugInfo() as $key => $value) + foreach ($less->getConfig()->getDebugInfo() as $key => $value) { $this->logSection('debug', sprintf("%s:\t%s", $key, $value), null, 'INFO'); } } // Compiles LESS files - foreach (sfLESS::findLessFiles() as $lessFile) + foreach ($less->findLessFiles() as $lessFile) { if (!isset($arguments['file']) || (false !== strpos($lessFile, $arguments['file'] . '.less'))) { - if ($lessHelper->compile($lessFile)) + if ($less->compile($lessFile)) { if (isset($options['debug']) && $options['debug']) { $this->logSection('compiled', sprintf("%s => %s", sfLESSUtils::getProjectRelativePath($lessFile), - sfLESSUtils::getProjectRelativePath(sfLESS::getCssPathOfLess($lessFile)) + sfLESSUtils::getProjectRelativePath($less->getCssPathOfLess($lessFile)) ), null, 'COMMAND'); } else { $this->logSection( - 'compiled', str_replace(sfLESS::getLessPaths(), '', $lessFile), null, 'COMMAND' + 'compiled', + str_replace($less->getConfig()->getLessPaths(), '', $lessFile), + null, + 'COMMAND' ); } }