[EXTENSION] LESS

Hi Chris

I’ve used the version 0.9.1 r17 and it works perfectly without errors.

Now I’ve updated the less extension to ver 0.10.0 r20

I have an error like this

“Property ‘LessCompiler.compress’ is not defined”

What should I do?

Thanks :)

Dude, this question I will answer for Chris. Actually the folder docs in bootstrap download pack (https://github.com/twitter/bootstrap/tree/master/docs) is the documentation of the css framework. It does not have anything related with the framework, its just the documentantion. They use the framework and this additional file docs.css to style another things on page.

You can add your own css files on your templates. On my case I configured the bootstrap extension to do not load the default css so I can compile my own css files and then add on my templates.

You should remove the “Property ‘LessCompiler.compress’” from your config.

Great! It works now

Thanks :)

Hi Thiago, could you tell me how did you manage to configure bootstrap not do load the default css?

thank you

Hi guys

As i was having some trouble at first too, here is my solution for a smart, fast and smooth integration of both yii-bootstrap and the less-extension of chris. I’m sure this is going to help a lot of you guys, that’s why im posting this here.

I divide this guide into the following steps:

[list=1]

[*]Installation of Bootstrap- and Less-extension

[*]Configuring Yii and both extensions

[*]Additional Controller-Action for force-parsing the less-files

[*]Conclusion

[/list]

1. Installation of Bootstrap- and Less-extension

Download both extensions from the corresponding extension page and extract them under your <approot>/protected/extensions folder (foldernames: bootstarp, less).

2. Configuring Yii and both extensions

Then you need to make the entries in the global config-file (<approot>/protected/config/main.php). As you will see I disable the integration of the bootstrap css-files as I’d like to have one single css-file integrated into the website which consists of all the necessary css-files and gets parsed by the less-compiler.




...

'preload'=>array(

    'less',

    'log',

    'bootstrap',

}

...

//less compiler

'less'=>array(

    'class'=>'ext.less.components.LessCompiler',

    'forceCompile'=>false,

    'paths'=>array(

        'less/main.less'=>'css/style.css',

    ),

),

...

//bootstrap extension

'bootstrap'=>array(

    'class'=>'ext.bootstrap.components.Bootstrap',

    'coreCss'=>false,

    'yiiCss'=>false,

    'responsiveCss'=>false,

    'plugins'=>array(

        //Optionally you can configure the "global" plugins (button, popover, tooltip and transition)

        //To prevent a plugin from being loaded set it to false as demonstrated below

        'transition'=>true,

    ),

),



As you can see I created a master less-file in the following folder which i created manually: <approot>/less/main.less. Within this file I Included the following less files:

  • bootstrap less-files

  • my own vars in a less-file (color-definitions, font-definitions, etc.)

  • my own layout setup

  • my own navigation configs in a less-file

  • my own overrides (to override and configure existing css-rules without touching the extension-files) in a less-file

The contents of the main.less file:




//bootstrap, bootstrap-yii and responsive

@import "../protected/extensions/bootstrap/lib/bootstrap/less/bootstrap.less";

@import "../protected/extensions/bootstrap/lib/bootstrap/less/responsive.less";

@import "../protected/extensions/bootstrap/assets/less/bootstrap-yii.less";


//vars

@import "vars.less";


//layout

@import "layout.less";


//navigation

@import "navigation.less";


//overrides

@import "overrides.less";



The later four files reside in the same directory as my main.less (<approot>/less).

To make sure nothing interrupts with your newly created less-/css-files empty the standart css-folder of yii. Also remove any imports of css-files and create one single link looking like this:




<link href="/css/style.css" type="text/css" rel="stylesheet">



You can even remove them all and let clientScripts integrate the files via your base-controller like I did. Relevant part of my <approot>/protected/components/Controller.php:




<?php


/**

 * Controller is the customized base controller class.

 * All controller classes for this application should extend from this base class.

 */

class Controller extends CController

{

...

    /**

     * (non-PHPdoc)

     * @see CController::init()

     */

    public function init()

    {

        //include default css-file

        Yii::app()->clientScript->registerCssFile(Yii::app()->baseUrl . '/css/style.css');


        parent::init();

    }

...



3. Additional Controller-Action for force-parsing the less-files

Yes, the compiler should notice and auto-compile the less-files if changes occured. But as I am using nested files - at least in my installation - this didn’t work as it should. So I created a Debug-Controller with an action named ‘less’. The sole purpose of this action is to force-compile all the less files and return to the previous page. That’s how it looks like:

Contents of file <approot>/protected/controllers/DebugController.php




<?php


class DebugController extends Controller

{

...

    /**

     * recompile less files

     */

    public function actionLess()

    {

        $less = Yii::app()->less;

        $basePath = str_replace('\'', '/', Yii::getPathOfAlias('webroot') . '/');

        foreach ($less->paths as $from=>$to) {

            $fromPath = $basePath . $from;

            $toPath = $basePath . $to;

            $less->compile($fromPath, $toPath);

        }

        $this->redirect(Yii::app()->request->urlReferrer);

    }

...	

}



So when you now call this action via http://chris83.rocks.com/debug/less you get your stuff recompiled and forwarded to the page you were before. The final css-file is now called style.css and gets compiled into the following folder: <approot>/css/style.css.

4. Conclusion

So what have we done!? We have installed both extensions…surprise surprise ;). More iomportantly we have setup a clean css-configuration without files interacting with each other. This way we can be sure to not load additional files and using unnecessary traffic and connections. But more importantly we have one single point of entrance to our style-stuff, which is main.less.

From there on we can now integrate, override etc. whatever we want. The js-files still get integrated automatically and we get an awesome and clean page-header like this:

Further we have created a an action, which can easily be bound to any menu, to force-compile our less-stuff.

I hope this guide helped you guys as it makes this two already awesome extensions even easier to use.

If you have any further questions or input, don’t hesitate to contact me!

Greetz from switzerland :),

pascal

Hello, I got the behavior i didn’t expect.

conf




'less'=>array(

            'class'=>'ext.less.components.LessCompiler',

            'forceCompile'=>false, // indicates whether to force compiling

            'paths'=>array(

                "../protected/less/print.less" => "web/assets/print.css",

                "../protected/less/common.less" => "web/assets/common.css",

            ),

        ),



LessCompiler.init




		if ($this->forceCompile || $this->hasChanges())

			$this->compileAll();



What I thought: if I change one of my less files, all of them will be recompiled. But that didn’t happen, because LessCompiler.hasChanges compares time of last change of the earliest less-file and the earliest compiled css




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[] = $source;

		}


		foreach ($dirs as $dir) {

			$modified = $this->getLastModified($dir);

			if (!isset($lastModified) || $modified < $lastModified)

				$lastModified = $modified;

		}


		return isset($lastCompiled) && isset($lastModified) && $lastModified > $lastCompiled;

	}



To get behavior i’m expecting I’ve modified the code this way


protected function hasChanges()

	{

		$dirs = array();

		foreach ($this->paths as $source => $destination)

		{

			$compiled = $this->getLastModified($destination);

			if (!isset($firstCompiled) || $compiled < $firstCompiled)

				$firstCompiled = $compiled;


			if (!in_array(dirname($source), $dirs))

				$dirs[] = $source;

		}


		foreach ($dirs as $dir) {

			$modified = $this->getLastModified($dir);

			if (!isset($lastModified) || $modified > $lastModified)

				$lastModified = $modified;

		}

		return isset($firstCompiled) && isset($lastModified) && $lastModified > $firstCompiled;

	}



Now it compares last modified less and earliest compiled css. So if I change only one less-file, all of them are recompiled. And that’s what I want.

PS of course it would be better to compare each less with it’s css, but we don’t change less so often and it’s fine to compile them all and forget about this

Could someone please expand on this? The link doesn’t work and I’m not sure how to call this action…

Thanks!

Hey mtzmedia

The link is only an example ;)! If you want to get your stuff recompiled call the action via controller (debug) and action (less). So whatever the url to your site is, just put it in front.

if your app is located at http://www.mtzmedia.com, the link to the created action would be http://www.mtzmedia.com/debug/less

got it? ;)

Less compilers fails to compile latest version of Boostrap (v2.1.1)

I believe the less compilers needs to be updated, they released a new version


 LessCompiler: Failed to compile less file with message: parse error: failed at `@props: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`;` C:/xampp/htdocs/soedu/less/bootstrap/mixins.less on line 253. 

Well I tried the new version of leafo’s lessphp & it still fails to compile v2.1.1 of bootstrap

The error occurs due to this mixen in mixen.less


.box-shadow(@shadowA, @shadowB:X, ...){

  @props: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`;

  -webkit-box-shadow: @props;

     -moz-box-shadow: @props;

          box-shadow: @props;

}

you can try it at leafo’s demo

Well it appears it’s a known issue

github dot com/leafo/lessphp/issues/315

Apparently this will be removed in the next version - there was a lot of debate about using JavaScript directly in Lees and, for bootstrap anyway, they seem to have decided that it goes against the idea of the ‘language’

I was previously using the "original" version of this compiler and had it working just as I needed it: Setup my less directory and files, added the files to my components config, and set autoCompile to true whenever I made a change and needed my less compiled into a new css.

With the new version released on Jan 17 I am unable to accomplish these same basic tasks. Can someone point me in the right direction? Just the couple things I’m trying to figure out:

  • How do I get this to compile my less into css?

  • What happened to autoCompile and how to I reproduce the behavior I had before (only compile when I set that to true)

Clearly I have more to learn about the fine points of Yii and these wonderful extensions.