Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote branch 'upstream/master'

  • Loading branch information...
commit 66120fee33dd9e48e43e07182d33076c3c7f9eab 2 parents 952aeb1 + ebf202c
@vicb vicb authored
View
67 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:
<file: web/less/clients/partials/_form.less>
@@ -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:
- <?php use_helper('LessCss'); ?>
+ <?php use_helper('LESS'); ?>
* update the way stylesheets are included by changing `<?php include_stylesheets() ?>` for `<?php include_less_stylesheets() ?>`
-### 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]
- <?php use_stylesheet('header/main.less') ?>
+* a template view file:
-In this case, it will be automatically changed from something like
+ <?php use_stylesheet('header/main.less') ?>
+
+In this case, it will be automatically changed from something like:
<link href="/css/header/main.less" media="screen" rel="stylesheet" type="text/css" />
-to
+to link like:
<link href="/less/header/main.less" media="screen" rel="stylesheet/less" type="text/css" />
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
* [client side] less.js updated to version 1.0.31
View
2  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)
View
121 lib/config/LESSConfig.class.php
@@ -0,0 +1,121 @@
+<?php
+
+/*
+ * This file is part of the sfLESSPlugin.
+ * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * 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 <ever.zet@gmail.com>
+ * @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()
+ );
+ }
+}
View
52 lib/config/sfLESSConfig.class.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the sfLESSPlugin.
+ * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * 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 <ever.zet@gmail.com>
+ * @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/';
+ }
+}
View
0  lib/sfWebDebugPanelLESS.class.php → lib/debug/sfWebDebugPanelLESS.class.php
File renamed without changes
View
5 lib/helper/LessCssHelper.php → lib/helper/LESSHelper.php
@@ -14,6 +14,7 @@
* @package sfLESSPlugin
* @subpackage helper
* @author Victor Berchet <victor@suumit.com>
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
* @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)
View
309 lib/less/sfLESS.class.php
@@ -0,0 +1,309 @@
+<?php
+
+/*
+ * This file is part of the sfLESSPlugin.
+ * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * 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 <ever.zet@gmail.com>
+ * @version 1.0.0
+ */
+class sfLESS
+{
+ /**
+ * Array of LESS styles
+ *
+ * @var array
+ */
+ protected static $results = array();
+
+ /**
+ * Errors of compiler
+ *
+ * @var array
+ */
+ protected static $errors = array();
+
+ /**
+ * Current LESS file to be parsed. This var used to help output errors in callCompiler()
+ *
+ * @var string
+ */
+ protected $currentFile;
+
+ /**
+ * LESS configuration manager
+ *
+ * @var LESSConfig
+ */
+ protected $config;
+
+ /**
+ * Constructor
+ *
+ * @param LESSConfig $config configuration manager
+ */
+ public function __construct(LESSConfig $config)
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * Returns configuration manager
+ *
+ * @return LESSConfig configurator instance
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ /**
+ * Returns array of compiled styles info
+ *
+ * @return array
+ */
+ public static function getCompileResults()
+ {
+ return self::$results;
+ }
+
+ /**
+ * Returns array of compiled styles errors
+ *
+ * @return array
+ */
+ public static function getCompileErrors()
+ {
+ return self::$errors;
+ }
+
+ /**
+ * Returns all CSS files under the CSS directory
+ *
+ * @return array an array of CSS files
+ */
+ public function findCssFiles()
+ {
+ return sfFinder::type('file')
+ ->exec(array('sfLESSUtils', 'isCssLessCompiled'))
+ ->name('*.css')
+ ->in($this->config->getCssPaths());
+ }
+
+ /**
+ * Returns all LESS files under the LESS directories
+ *
+ * @return array an array of LESS files
+ */
+ public function findLessFiles()
+ {
+ return sfFinder::type('file')
+ ->name('*.less')
+ ->discard('_*')
+ ->follow_link()
+ ->in($this->config->getLessPaths());
+ }
+
+ /**
+ * Returns CSS file path by its LESS alternative
+ *
+ * @param string $lessFile LESS file path
+ *
+ * @return string CSS file path
+ */
+ static public function getCssPathOfLess($lessFile)
+ {
+ return str_replace(
+ array($this->config->getLessPaths(), '.less'),
+ array($this->config->getCssPaths(), '.css'),
+ $lessFile
+ );
+ }
+
+ /**
+ * Compiles LESS file to CSS
+ *
+ * @param string $lessFile a LESS file
+ *
+ * @return boolean true if succesfully compiled & false in other way
+ */
+ public function compile($lessFile)
+ {
+ // Creates timer
+ $timer = new sfTimer;
+
+ // Gets CSS file path
+ $cssFile = $this->getCssPathOfLess($lessFile);
+
+ // Checks if path exists & create if not
+ if (!is_dir(dirname($cssFile)))
+ {
+ mkdir(dirname($cssFile), 0777, true);
+ // PHP workaround to fix nested folders
+ chmod(dirname($cssFile), 0777);
+ }
+
+ // Is file compiled
+ $isCompiled = false;
+
+ // If we check dates - recompile only really old CSS
+ if ($this->config->isCheckDates())
+ {
+ try
+ {
+ $d = new sfLESSDependency(sfConfig::get('sf_web_dir'),
+ sfConfig::get('app_sf_less_plugin_check_dependencies', false));
+ if (!is_file($cssFile) || $d->getMtime($lessFile) > filemtime($cssFile))
+ {
+ $isCompiled = $this->callCompiler($lessFile, $cssFile);
+ }
+ }
+ catch (Exception $e)
+ {
+ $isCompiled = false;
+ }
+ }
+ else
+ {
+ $isCompiled = $this->callCompiler($lessFile, $cssFile);
+ }
+
+ // Adds debug info to debug array
+ self::$results[] = array(
+ 'lessFile' => $lessFile,
+ 'cssFile' => $cssFile,
+ 'compTime' => $timer->getElapsedTime(),
+ 'isCompiled' => $isCompiled
+ );
+
+ return $isCompiled;
+ }
+
+ /**
+ * Calls current LESS compiler for single file
+ *
+ * @param string $lessFile a LESS file
+ * @param string $cssFile a CSS file
+ *
+ * @return boolean true if succesfully compiled & false in other way
+ */
+ public function callCompiler($lessFile, $cssFile)
+ {
+ // Setting current file. We will output this var if compiler throws error
+ $this->currentFile = $lessFile;
+
+ // Do not try to change the permission of an existing file which we might not own
+ $setPermission = !is_file($cssFile);
+
+ // Call compiler
+ $buffer = $this->callLesscCompiler($lessFile, $cssFile);
+
+ // Checks if compiler returns false
+ if (false === $buffer)
+ {
+ return $buffer;
+ }
+
+ // Compress CSS if we use compression
+ if ($this->config->isUseCompression())
+ {
+ $buffer = sfLESSUtils::getCompressedCss($buffer);
+ }
+
+ // Add compiler header to CSS & writes it to file
+ file_put_contents($cssFile, sfLESSUtils::getCssHeader() . "\n\n" . $buffer);
+
+ if ($setPermission)
+ {
+ // Set permissions for fresh files only
+ chmod($cssFile, 0666);
+ }
+
+ // Setting current file to null
+ $this->currentFile = null;
+
+ return true;
+ }
+
+ /**
+ * Calls lessc compiler for LESS file
+ *
+ * @param string $lessFile a LESS file
+ * @param string $cssFile a CSS file
+ *
+ * @return string output
+ */
+ public function callLesscCompiler($lessFile, $cssFile)
+ {
+ // Compile with lessc
+ $fs = new sfFilesystem;
+ $command = sprintf('lessc "%s" "%s"', $lessFile, $cssFile);
+
+ if ('1.3.0' <= SYMFONY_VERSION)
+ {
+ try
+ {
+ $fs->execute($command, null, array($this, 'throwCompilerError'));
+ }
+ catch (RuntimeException $e)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ $fs->sh($command);
+ }
+
+ return file_get_contents($cssFile);
+ }
+
+ /**
+ * Returns true if compiler can throw RuntimeException
+ *
+ * @return boolean
+ */
+ public function canThrowExceptions()
+ {
+ return (('prod' !== sfConfig::get('sf_environment') || !sfConfig::get('sf_app')) &&
+ !(sfConfig::get('sf_web_debug') && sfConfig::get('app_sf_less_plugin_toolbar', true))
+ );
+ }
+
+ /**
+ * Throws formatted compiler error
+ *
+ * @param string $line error line
+ *
+ * @return boolean
+ */
+ public function throwCompilerError($line)
+ {
+ // Generate error description
+ $errorDescription = sprintf("LESS parser error in \"%s\":\n\n%s", $this->currentFile, $line);
+
+ // Adds error description to list of errors
+ self::$errors[$this->currentFile] = $errorDescription;
+
+ // Throw exception if allowed & log error otherwise
+ if ($this->canThrowExceptions())
+ {
+ throw new sfException($errorDescription);
+ }
+ else
+ {
+ sfContext::getInstance()->getLogger()->err($errorDescription);
+ }
+
+ return false;
+ }
+}
View
19 lib/sfLESSDependency.class.php → lib/less/sfLESSDependency.class.php
@@ -1,4 +1,5 @@
<?php
+
/*
* This file is part of the sfLESSPlugin.
* (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
@@ -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();
}
}
-}
+}
View
93 lib/less/sfLESSListeners.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of the sfLESSPlugin.
+ * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * 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 <ever.zet@gmail.com>
+ * @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.31.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();
+ }
+}
View
127 lib/less/sfLESSUtils.class.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * This file is part of the sfLESSPlugin.
+ * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Various utility functions
+ *
+ * @package sfLESSPlugin
+ * @subpackage lib
+ * @author Victor Berchet <victor@suumit.com>
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ * @version 1.0.0
+ */
+
+class sfLESSUtils
+{
+ /**
+ * Determine if a filesystem path is absolute.
+ *
+ * @param path $path A filesystem path.
+ *
+ * @return bool true, if the path is absolute, otherwise false.
+ */
+ public static function isPathAbsolute($path)
+ {
+ if ($path[0] == '/' || $path[0] == '\\' ||
+ (strlen($path) > 3 && ctype_alpha($path[0]) &&
+ $path[1] == ':' &&
+ ($path[2] == '\\' || $path[2] == '/')
+ )
+ )
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Strip comments from less content
+ *
+ * @param string $less LESS code
+ *
+ * @return string LESS code without comments
+ */
+ public static function stripLessComments($less)
+ {
+ // strip /* */ style comments
+ $less = preg_replace('#/\*.*?\*/#ms', '', $less);
+ // stip // style comments
+ $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)
+ );
+ }
+
+ /**
+ * 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. */';
+ }
+}
View
514 lib/sfLESS.class.php
@@ -1,514 +0,0 @@
-<?php
-
-/*
- * This file is part of the sfLESSPlugin.
- * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
- *
- * 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 <ever.zet@gmail.com>
- * @version 1.0.0
- */
-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
- *
- * @var boolean
- */
- protected $checkDates = true;
-
- /**
- * Do we need compression for CSS files
- *
- * @var boolean
- */
- protected $useCompression = false;
-
- /**
- * Current LESS file to be parsed. This var used to help output errors in callCompiler()
- *
- * @var string
- */
- protected $currentFile;
-
- /**
- * Constructor
- *
- * @param boolean $checkDates Do we need to check dates before compile
- * @param boolean $useCompression Do we need compression for CSS files
- */
- public function __construct($checkDates = true, $useCompression = false)
- {
- $this->setIsCheckDates($checkDates);
- $this->setIsUseCompression($useCompression);
- }
-
- /**
- * Returns array of compiled styles info
- *
- * @return array
- */
- public static function getCompileResults()
- {
- return self::$results;
- }
-
- /**
- * Returns array of compiled styles errors
- *
- * @return array
- */
- 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()
- );
- }
-
- /**
- * 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
- *
- * @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 self::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()
- {
- return sfFinder::type('file')
- ->exec(array('sfLESS', '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 self::getSepFixedPath(sfConfig::get('sf_web_dir')) . '/less/';
- }
-
- /**
- * Returns all LESS files under the LESS directories
- *
- * @return array an array of LESS files
- */
- static public function findLessFiles()
- {
- return sfFinder::type('file')
- ->name('*.less')
- ->discard('_*')
- ->follow_link()
- ->in(self::getLessPaths());
- }
-
- /**
- * Returns CSS file path by its LESS alternative
- *
- * @param string $lessFile LESS file path
- *
- * @return string CSS file path
- */
- static public function getCssPathOfLess($lessFile)
- {
- return str_replace(
- array(self::getLessPaths(), '.less'),
- array(self::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");
- }
- else
- {
- $response->addJavascript(
- sfConfig::get('app_sf_less_plugin_js_lib', '/sfLESSPlugin/js/less-1.0.31.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
- *
- * @param string $lessFile a LESS file
- *
- * @return boolean true if succesfully compiled & false in other way
- */
- public function compile($lessFile)
- {
- // Creates timer
- $timer = new sfTimer;
-
- // Gets CSS file path
- $cssFile = self::getCssPathOfLess($lessFile);
-
- // Checks if path exists & create if not
- if (!is_dir(dirname($cssFile)))
- {
- mkdir(dirname($cssFile), 0777, true);
- // PHP workaround to fix nested folders
- chmod(dirname($cssFile), 0777);
- }
-
- // Is file compiled
- $isCompiled = false;
-
- // If we check dates - recompile only really old CSS
- if ($this->isCheckDates())
- {
- try
- {
- $d = new sfLESSDependency(sfConfig::get('sf_web_dir'),
- sfConfig::get('app_sf_less_plugin_check_dependencies', false));
- if (!is_file($cssFile) || $d->getMtime($lessFile) > filemtime($cssFile))
- {
- $isCompiled = $this->callCompiler($lessFile, $cssFile);
- }
- }
- catch (Exception $e)
- {
- $isCompiled = false;
- }
- }
- else
- {
- $isCompiled = $this->callCompiler($lessFile, $cssFile);
- }
-
- // Adds debug info to debug array
- self::$results[] = array(
- 'lessFile' => $lessFile,
- 'cssFile' => $cssFile,
- 'compTime' => $timer->getElapsedTime(),
- 'isCompiled' => $isCompiled
- );
-
- 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
- *
- * @param string $lessFile a LESS file
- * @param string $cssFile a CSS file
- *
- * @return boolean true if succesfully compiled & false in other way
- */
- public function callCompiler($lessFile, $cssFile)
- {
- // Setting current file. We will output this var if compiler throws error
- $this->currentFile = $lessFile;
-
- // Do not try to change the permission of an existing file which we might not own
- $setPermission = !is_file($cssFile);
-
- // Call compiler
- $buffer = $this->callLesscCompiler($lessFile, $cssFile);
-
- // Checks if compiler returns false
- if (false === $buffer)
- {
- return $buffer;
- }
-
- // Compress CSS if we use compression
- if ($this->isUseCompression())
- {
- $buffer = self::getCompressedCss($buffer);
- }
-
- // Add compiler header to CSS & writes it to file
- file_put_contents($cssFile, self::getCssHeader() . "\n\n" . $buffer);
-
- if ($setPermission)
- {
- // Set permissions for fresh files only
- chmod($cssFile, 0666);
- }
-
- // Setting current file to null
- $this->currentFile = null;
-
- return true;
- }
-
- /**
- * Calls lessc compiler for LESS file
- *
- * @param string $lessFile a LESS file
- * @param string $cssFile a CSS file
- *
- * @return string output
- */
- public function callLesscCompiler($lessFile, $cssFile)
- {
- // Compile with lessc
- $fs = new sfFilesystem;
- $command = sprintf('lessc "%s" "%s"', $lessFile, $cssFile);
-
- if ('1.3.0' <= SYMFONY_VERSION)
- {
- try
- {
- $fs->execute($command, null, array($this, 'throwCompilerError'));
- }
- catch (RuntimeException $e)
- {
- return false;
- }
- }
- else
- {
- $fs->sh($command);
- }
-
- return file_get_contents($cssFile);
- }
-
- /**
- * Returns true if compiler can throw RuntimeException
- *
- * @return boolean
- */
- public function canThrowExceptions()
- {
- return (('prod' !== sfConfig::get('sf_environment') || !sfConfig::get('sf_app')) &&
- !(sfConfig::get('sf_web_debug') && sfConfig::get('app_sf_less_plugin_toolbar', true))
- );
- }
-
- /**
- * Throws formatted compiler error
- *
- * @param string $line error line
- *
- * @return boolean
- */
- public function throwCompilerError($line)
- {
- // Generate error description
- $errorDescription = sprintf("LESS parser error in \"%s\":\n\n%s", $this->currentFile, $line);
-
- // Adds error description to list of errors
- self::$errors[$this->currentFile] = $errorDescription;
-
- // Throw exception if allowed & log error otherwise
- if ($this->canThrowExceptions())
- {
- throw new sfException($errorDescription);
- }
- else
- {
- sfContext::getInstance()->getLogger()->err($errorDescription);
- }
-
- return false;
- }
-}
View
56 lib/sfLESSUtils.class.php
@@ -1,56 +0,0 @@
-<?php
-/*
- * This file is part of the sfLESSPlugin.
- * (c) 2010 Konstantin Kudryashov <ever.zet@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-/**
- * Various utility functions
- *
- * @package sfLESSPlugin
- * @subpackage lib
- * @author Victor Berchet <victor@suumit.com>
- * @version 1.0.0
- */
-
-class sfLESSUtils
-{
- /**
- * Determine if a filesystem path is absolute.
- *
- * @param path $path A filesystem path.
- *
- * @return bool true, if the path is absolute, otherwise false.
- */
- public static function isPathAbsolute($path)
- {
- if ($path[0] == '/' || $path[0] == '\\' ||
- (strlen($path) > 3 && ctype_alpha($path[0]) &&
- $path[1] == ':' &&
- ($path[2] == '\\' || $path[2] == '/')
- )
- )
- {
- return true;
- }
- return false;
- }
-
- /**
- * Strip comments from less content
- *
- * @param string $less LESS code
- * @return string LESS code without comments
- */
- public static function stripLessComments($less)
- {
- // strip /* */ style comments
- $less = preg_replace('#/\*.*?\*/#ms', '', $less);
- // stip // style comments
- $less = preg_replace('#//.*$#m', '', $less);
- return $less;
- }
-}
View
30 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",
- sfLESS::getProjectRelativePath($lessFile),
- sfLESS::getProjectRelativePath(sfLESS::getCssPathOfLess($lessFile))
+ sfLESSUtils::getProjectRelativePath($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'
);
}
}
View
2  package.xml
@@ -23,7 +23,7 @@
<notes>-</notes>
<contents>
<dir name="/">
- <file role="data" name="README.markdown" />
+ <file role="data" name="README" />
<file role="data" name="LICENSE" />
<dir name="web">
<dir name="images">
View
0  lib/test/fixtures/a/a.less → test/fixtures/a/a.less
File renamed without changes
View
0  lib/test/fixtures/b/b.less → test/fixtures/b/b.less
File renamed without changes
View
0  lib/test/fixtures/c/c.c.less → test/fixtures/c/c.c.less
File renamed without changes
View
0  lib/test/fixtures/d/d.less → test/fixtures/d/d.less
File renamed without changes
View
0  lib/test/fixtures/e/e.css → test/fixtures/e/e.css
File renamed without changes
View
0  lib/test/fixtures/not/not.less → test/fixtures/not/not.less
File renamed without changes
View
0  lib/test/fixtures/root.less → test/fixtures/root.less
File renamed without changes
View
0  lib/test/unit/dependencyTest.php → test/unit/dependencyTest.php
File renamed without changes
Please sign in to comment.
Something went wrong with that request. Please try again.