[EXTENSION] LESS Compile your LESS server-side
#1
Posted 30 November 2011 - 06:33 PM
This is the discussion thread for my LESS extension.
The extension allows you to use Agar's amazing less.php compiler to compile LESS into CSS in your Yii-application. It also allows for compiling the LESS before each request, which is very handy in development environments.
What is LESS?
LESS is a dynamic stylesheet language which supports variables, mixins, nested rules, functions, etc. If you haven't tried LESS you should definitely give it a go, you won't be disappointed.
Download the extension here:
http://www.yiiframew...extension/less/
Fork me on Bitbucket:
https://bitbucket.or...isu83/yii-less/
More about LESS here:
http://www.lesscss.org
#2
Posted 03 December 2011 - 10:18 AM
Thanks for this extention , it's exactly what i need for working whith your other amazing extention (bootstrap).
But i'm a newbie in yii so i did not succeed to combine the two extentions .
Did i must tu configure less extention to generate the style.css in folder generated by bootstrap extention /assets/95f7a8b8/css/bootstrap.min.css ?
thanks for your help
#3
Posted 03 December 2011 - 03:56 PM
yiiesss, on 03 December 2011 - 10:18 AM, said:
Thanks for this extention , it's exactly what i need for working whith your other amazing extention (bootstrap).
But i'm a newbie in yii so i did not succeed to combine the two extentions .
Did i must tu configure less extention to generate the style.css in folder generated by bootstrap extention /assets/95f7a8b8/css/bootstrap.min.css ?
thanks for your help
Hey yiiesss,
I use both extensions together on multiple projects and my setup is as follows:
I don't call Yii::app()->boostrap->registerBootstrap(); in my main layout (because I don't want to include the bootstrap css file). Instead I've configured the less compiler to compile less/styles.less to css/styles.css and include styles.css in my main layout. On the first line in my styles.less file I include the bootstrap.less:
@import "../protected/extensions/bootstrap/vendors/bootstrap/lib/bootstrap.less";
However, there is still a minor issue in the less.php compiler so you will need to remove the following comment from the bootstrap/lib/reset.less file:
/* Reset.less * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
This is because the compiler has an issue with parsing long comments so you won't be able to compile Bootstrap. I've reported this issue and the author should fix this soon.
Hopefully this helps. Please don't hesitate to ask if you have further questions.
#5
Posted 08 March 2012 - 02:41 PM
What's new
- Added support for checking if recompiling is necessary
- Added support for compressing compiled CSS
- Added support for enabling compiler debugging mode
- Removed LessCompilationBehavior (redundant)
Get the new version here:
http://www.yiiframew...s-0.9.1.r17.zip
#7
Posted 16 March 2012 - 10:33 AM
config/main.php
'preload'=>array
(
'less',
'log',
'bootstrap',
),
'components'=>array
(
'lessComplier'=>array(
'autoCompile'=>true,
'class'=>'ext.less.components.LessCompiler',
'paths'=>array(
'/less/styles.less'=>'/css/style.css',
)
),
[....]
[code]
16:15:21.978339 trace system.CModule
Loading "log" application component
in C:\Users\User\www\z3usproject\index.php (13)
16:15:21.983776 trace system.CModule
Loading "bootstrap" application component
in C:\Users\User\www\z3usproject\index.php (13)
#8
Posted 21 March 2012 - 07:30 AM
I tried to use this extension but I can't get it to work.
That's what I did:
1. copy files into /protected/extensions/less
2. edit main.php | config
'preload'=>array(
'less', // preload the component to allow for automatic compilation
),
'components'=>array(
'lessCompiler'=>array(
'class'=>'ext.less.components.LessCompiler',
'forceCompile'=>false, // indicates whether to force compiling
'compress'=>false, // indicates whether to compress compiled CSS
'debug'=>false, // indicates whether to enable compiler debugging mode
'paths'=>array(
'less/style.less'=>'css/style.css',
),
),
),
create a style.less file in my css directory and last including the styles.less in my main layout:
<link rel="stylesheet/less" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/styles.less" />
is there anything wrong with it? Have I missed something?
Cheers
-Seb
#9
Posted 28 March 2012 - 05:07 AM
demo88, on 14 March 2012 - 01:24 PM, said:
There are a few issues with the current twitter bootstrap version.
This is because of an outdated version of the less/less.php library. The last update of the library was 4 month ago so i don't think that there will be an update?
Hmm this issue still isn't been solved. I just wanted to start using the bootstrap extension with the less php class. How do you solving this issue? i tried to compile the less code with simpleless but this doesn't work at all.
@sebako look if you have the correct names
you are using
/css/style(s).less
and 'less/style.less'=>'css/style.css', in your config without the (s).
#10
Posted 28 March 2012 - 05:24 AM
Fork on github
Follow phundament on Twitter
DevSystem: Mac OS X 10.7 - PHP 5.3 - Apache2 - Yii 1.1 / trunk - Firefox or Safari
#11
Posted 02 April 2012 - 02:15 PM
#12
Posted 04 April 2012 - 09:22 AM
Less\Exception\CompilerException
#grid > .core is undefined
D:\Development\xampp\htdocs\vivaterra2.com.br\protected\extensions\less\lib\lessphp\lib\Less\Node\Mixin\Call.php(56)
44 return $rules;
45 } else {
46 throw new \Less\Exception\CompilerException('No matching definition was found for `'.
47 trim($this->selector->toCSS($env)) . '(' .
48 implode(', ', array_map(function ($a) use($env) {
49 return $a->toCss($env);
50 }, $this->arguments)) . ')`',
51 $this->index);
52 }
53 }
54 }
55
56 throw new \Less\Exception\CompilerException(trim($this->selector->toCSS($env)) . " is undefined", $this->index);
57 }
58 }
#13
Posted 04 April 2012 - 10:01 AM
I got the same problem, the current phpless version can not parse the LESS used in Bootstrap 2.0.2, you have to use 2.0.1 with the current lessCompiler.
@Chris: Where did you get the phpless from http://leafo.net/lessphp/ ?
thiagovidal, on 04 April 2012 - 09:22 AM, said:
Less\Exception\CompilerException
#grid > .core is undefined
Best regards,
schmunk
Fork on github
Follow phundament on Twitter
DevSystem: Mac OS X 10.7 - PHP 5.3 - Apache2 - Yii 1.1 / trunk - Firefox or Safari
#14
Posted 04 April 2012 - 12:18 PM
schmunk, on 04 April 2012 - 10:01 AM, said:
I got the same problem, the current phpless version can not parse the LESS used in Bootstrap 2.0.2, you have to use 2.0.1 with the current lessCompiler.
@Chris: Where did you get the phpless from http://leafo.net/lessphp/ ?
Best regards,
schmunk
#15
Posted 28 April 2012 - 10:37 AM
I don't yet understand caching in Yii so I'm not sure if it could be done better that way. Also as I understand it, the protected folder isn't writeable so writing .less.cache files and compiling .less from extensions etc wouldn't work with lessphp's inbuilt caching.
The only method I could come up with by myself was to use the webroot/css directory to store the compiled css and cache files. I added lessc.in.php and my LessCss.php to extensions/less and used Yii's method to hash the names so extensions wouldn't clash. I'd love to know how what I've done should be done if anyone has the time?
public static function compile( $lessPath )
{
$cssDir = Yii::getPathOfAlias('webroot') . '/css/';
$cacheDir = $cssDir . 'cache/';
// generate hashed filename clashes don't occur in webroot/css
$assetName = sprintf( '%x', crc32($lessPath) );
$cssPath = $cssDir . $assetName . '.css';
$cachePath = $cacheDir . $assetName . '.less.cache';
if ( !file_exists($cacheDir) ) {
mkdir( $cacheDir );
chmod( $cacheDir, 0755);
}
// get previously cached .less or use input .less
if ( file_exists($cachePath) )
$cache = unserialize( file_get_contents($cachePath) );
else
$cache = $lessPath;
// try compile .less
try {
require_once( dirname(__FILE__) . '/lessc.inc.php' );
$newCache = lessc::cexecute( $cache );
} catch ( exception $e ) {
Yii::log( 'Failed to compile .less file, reason: ' . $e->getMessage(), 'error', '{LESS}' );
return false;
}
// create new .less and .less.cache files if updated
if ( !is_array($cache) || $newCache['updated'] > $cache['updated'] ) {
Yii::trace( 'Passed and cached .less file: ' . $lessPath, '{LESS}' );
file_put_contents( $cachePath, serialize($newCache) );
file_put_contents( $cssPath, $newCache['compiled'] );
} else
Yii::trace('No modifications to .less file (since last cached): ' . $lessPath, '{LESS}' );
// return compiled .css location
return Yii::app()->baseUrl . '/css/' . $assetName . '.css';
}
}
Then I can just use it like this, e.g:
Yii::app()->clientScript->registerCSSFile(
LessCss::compile( Yii::getPathOfAlias('webroot') . '/css/normalize.less' )
);
#16
Posted 14 May 2012 - 12:57 PM
Thanks for taking the time of putting this together.
Quick question, how do you specify the paths for a less/css file living inside a theme? I've tried the following with no luck
...
'basePath'=> Yii:getPathOfAlias('webroot.themes.mytheme'),
'paths'=>array(
'less/style.less'=>'css/style.css',
),
Thanks
#17
Posted 17 May 2012 - 02:34 AM
belano, on 14 May 2012 - 12:57 PM, said:
Thanks for taking the time of putting this together.
Quick question, how do you specify the paths for a less/css file living inside a theme? I've tried the following with no luck
...
'basePath'=> Yii:getPathOfAlias('webroot.themes.mytheme'),
'paths'=>array(
'less/style.less'=>'css/style.css',
),
Thanks
Just define an alias
Yii::setPathOfAlias('themes', dirname(__FILE__).'/../../themes');
then declare the component as follows
'less'=>array(
'class'=>'ext.less.components.LessCompiler',
'basePath' => Yii::getPathOfAlias('themes.new'),
'forceCompile'=>true, // indicates whether to force compiling
'paths'=>array(
'less/main.less'=>'css/main.css',
),
),
#18
Posted 22 May 2012 - 07:35 AM
I've changed a couple of things just to make it work like I want with Bootstrap, and since the extension (well, the lessCompiler.php) didn't look correctly for files in the directory recursively (or it didn't work for me)
In main.php, path option I have the files wrapper of Bootstrap:
protected/extensions/bootstrap/lib/bootstrap/less/bootstrap.less=>protected/extensions/bootstrap/assets/css/bootstrap.min.css
I wanted to compile de bootstrap.less whenever I edit any of the .less files in the directory that bootstrap.less imports.
To do this I had to modify the lessCompiler.php of the extension these two methods which I believe were wrong:
/**
* Returns whether any of files configured to be compiled has changed.
* @return boolean the result.
*/
protected function hasChanges()
{
$dirs = array();
foreach ($this->paths as $source => $destination)
{
$compiled = $this->getLastModified($destination);
if (!isset($lastCompiled) || $compiled > $lastCompiled)
$lastCompiled = $compiled;
if (!in_array(dirname($source), $dirs))
$dirs[] = dirname($source);
}
foreach ($dirs as $dir) {
$modified = $this->getLastModified($dir);
if (!isset($lastModified) || $modified > $lastModified)
$lastModified = $modified;
}
//ChromePhp::log(array(date("Y-m-d H:i:s",$lastModified),date("Y-m-d H:i:s",$lastCompiled)));
return isset($lastCompiled) && isset($lastModified) && $lastModified > $lastCompiled;
}
/**
* Returns the last modified for a specific path.
* @param string $path the path.
* @return integer the last modified (as a timestamp).
*/
protected function getLastModified($path)
{
if (!file_exists($path))
return 0;
else
{
if (is_file($path))
{
$stat = stat($path);
return $stat['mtime'];
}
else
{
$lastModified = null;
/** @var Directory $dir */
$dir = dir($path);
while ($entry = $dir->read())
{
if (strpos($entry, '.') === 0)
continue;
$ruta = $path. '/'.$entry;
if (is_dir($ruta))
$modified = $this->getLastModified($ruta);
else
{
$stat = stat($ruta);
$modified = $stat['mtime'];
}
if (!isset($lastModified) || $modified > $lastModified)
$lastModified = $modified;
}
return $lastModified;
}
}
}
Good luck, and thanks for the great extensions anyway
#19
Posted 23 May 2012 - 12:39 AM
I want to make changes to bootstrap and hacking the css doesn't seem like a smart idea as versions will change often. I'm using your bootstrap extension and have just now implemented your less extension.
To start with I just want to modify the navigation bar but eventually will edit more.
The less compiler is working correctly but I'm pretty sure I'm not putting the right things in the style.less file. I basically added the variables.less and navbar.less . When I compile it I see the style.css and it looks correct to me but when I refresh the page it 's exactly the same and nothing has changed.
I guess the extension includes the bootstrap.css and I should force it to use mine instead of maybe as well as? Not to sure how to progress now so any help would be appreciated.
Thanks
Lux
PS: Something else I'm sure is obvious but I'm missing is how is this making things more efficient? I guess I still have to include the bootstrap.css and now it looks like I have to also include the style.css which just duplicates much of the bootstrap.css with some modifications. What's the point? What am I missing?
UPDATE: I just noticed the comment from Chris about not including bootstrap core with bootstrap by setting it to false in the bootstrap config which I've done so now everything is included in styles.css and my navigation changes are showing. Still not seeing the point other than I was able to use variables to change style sheet values easily.
#20
Posted 25 May 2012 - 08:12 AM
do you use only less/styles.less for design styles? On bootstrap site there is also docs.css
Your extension yii-bootstrap create
<link rel="stylesheet" type="text/css" href="/assets/9a4eed2/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="/assets/9a4eed2/css/bootstrap-responsive.min.css" />
<link rel="stylesheet" type="text/css" href="/assets/9a4eed2/css/bootstrap-yii.css" />
but there is no docs.css
So I need insert styles from docs.css into styles.less?

Help
















