1
0
Fork 0
mirror of https://github.com/Oreolek/kohana-less.git synced 2024-06-26 03:40:46 +03:00

updated the module, added sample-code

This commit is contained in:
mon 2010-06-24 23:14:03 +08:00
parent cbe2fa4793
commit bc29934fbf
10 changed files with 360 additions and 135 deletions

View file

@ -1,17 +1,19 @@
KO3 LESS Module
===============
KO3 LESS Module v.1.1
=====================
LESS Module is a port of Leaf Corcoran's [LESSPHP](http://leafo.net/lessphp) for Kohana 3
It adopts some of Alex Sancho's Kohana 2.3 Assets Module codes for CSS compression, credits goes to them
Thanks to [cheeaun](http://github.com/cheeaun) for helping out
Thanks to [cheeaun](http://github.com/cheeaun) for helping out!
You might also want to check out another implementation from [jeremeamia](http://github.com/jeremeamia/kohana-less).
To Use
-------
1. Put the less module folder in your Modules directory
2. Include less module in your application's bootstrap: 'less' => MODPATH.'less'
3. Copy the less config file from /modules/less/config/less.php to your application's config directory
4. From your less.php config file, put the path to where you want the CSS files compiled / compressed, the folder must be writable
5. You can set compression to TRUE on your less.php config file if you want your CSS files to be combined in to one file and compressed
4. From your less.php config file, put the 'path' to where you want the CSS files compiled / compressed, the folder must be writable
5. You can set 'compress' to TRUE on your less.php config file if you want your CSS files to be combined in to one file and compressed (to lessen server calls)
6. Checkout how to use through the included sample-code folder, that folder is not part of the module
Sample Code
------------
@ -19,46 +21,62 @@ Sample Code
** /media/css/style.less **
** MODPATH/baseModule/media/css/layout.less **
@bodyBkgColor: #EEE;
body {
background: @bodyBkgColor;
margin:0;
padding:0;
h1 { font-size: 3em; }
}
** APPPATH/media/css/style.less **
@divBkgColor: #DDD;
.roundedCorners (@radius:8px) {
-moz-border-radius:@radius;
-webkit-border-radius:@radius;
border-radius:@radius;
zoom:1;
}
div {
background: @divBkgColor;
.roundedCorners;
p { .roundedCorners(5px); }
}
** APPPATH/config/less.php **
return array(
'compress' => TRUE,
// relative PATH to a writable folder to store compiled / compressed css
// path below will be treated as: DOCROOT . 'media/css/'
'path' => 'media/css/',
'compress' => TRUE,
);
** APPPATH/classes/controller/sample.php **
Controller_Home extends Controller_Template {
class Controller_Sample extends Controller_Template {
public $template = 'template';
// no need to add .less extension
public $stylesheets = array('reset', 'style');
public function action_index()
{
$stylesheets = $this->stylesheets;
// no need to add .less extension
// you can put your less files anywhere
$less_files = array
(
MODPATH.'baseModule/media/css/layout',
APPPATH.'media/css/style',
);
foreach (stylesheets as $key => $value)
{
// I keep my less files inside APPPATH . 'media/less/' but can be anywhere
$stylesheets[$key] = APPPATH . 'media/less/' . $value;
}
$this->template->stylesheets = Less::set($this->stylesheets);
$this->template->stylesheet = Less::compile($less_files);
}
}
@ -67,7 +85,7 @@ Sample Code
<html>
<head>
<title>LESS for Kohana</title>
<?= $stylesheets ?>
<?= $stylesheet; // will give me ONE compressed css file located in /media/css/ ?>
</head>
<body>
<h1>LESS for Kohana or Kohana for LESS?</h1>

View file

@ -1,116 +1,3 @@
<?php defined('SYSPATH') or die('No direct script access.');
class Less
{
public static function set($files, $media = 'screen', $compress = NULL)
{
$config = Kohana::config('less');
if ($compress == NULL) $compress = $config->compress;
if ( ! $compress)
{
$stylesheets = array();
foreach ($files as $input)
{
$filename = substr($input, strripos('/' . $input, '/'), strlen($input));
$output = self::get_output($input, $filename);
array_push($stylesheets, html::style( self::compile($input, $output), array('media' => $media) ));
}
return implode("\n", $stylesheets);
}
return html::style( self::glue($files), array('media' => $media) );
}
public static function get_output($input, $filename)
{
$config = Kohana::config('less');
$filepath = $config->path . $filename;
if ( ! file_exists($filepath . '.css'))
{
touch($filepath . '.css', filemtime($input . '.less') - 3600);
}
return $filename;
}
public static function glue($files)
{
$config = Kohana::config('less');
$files_lastmodified = self::get_last_modified($files);
$filename = md5(implode('|', $files)) . '-' . $files_lastmodified;
$filepath = $config->path . $filename;
if ( ! file_exists($filepath . ' .css') OR filemtime($filepath . '.css') < $files_lastmodified )
{
ob_start();
foreach($files as $file)
{
echo file_get_contents($file . '.less');
}
file_put_contents($filepath . '.css', ob_get_clean(), LOCK_EX);
self::compile_compress($filepath);
}
return $filepath . '.css';
}
public static function compile($input, $output)
{
$config = Kohana::config('less');
try
{
lessc::ccompile($input . '.less', $config->path . $output . '.css');
}
catch (LessException $ex)
{
exit($ex->getMessage());
}
return $config->path . $output . '.css';
}
public static function compile_compress($filepath)
{
$less = new lessc($filepath . '.css');
try
{
$compiled = $less->parse();
$compressed = self::compress($compiled);
file_put_contents($filepath . '.css', $compressed);
}
catch (LessException $ex)
{
exit($ex->getMessage());
}
}
private static function compress($data)
{
$data = preg_replace('~/\*[^*]*\*+([^/][^*]*\*+)*/~', '', $data);
$data = preg_replace('~\s+~', ' ', $data);
$data = preg_replace('~ *+([{}+>:;,]) *~', '$1', trim($data));
$data = str_replace(';}', '}', $data);
$data = preg_replace('~[^{}]++\{\}~', '', $data);
return $data;
}
private static function get_last_modified($files)
{
$last_modified = 0;
foreach ($files as $file)
{
$modified = filemtime($file . '.less');
if ($modified !== false and $modified > $last_modified) $last_modified = $modified;
}
return $last_modified;
}
}
class Less extends Less_Core { }

BIN
classes/less/.DS_Store vendored Normal file

Binary file not shown.

216
classes/less/core.php Normal file
View file

@ -0,0 +1,216 @@
<?php defined('SYSPATH') or die('No direct script access.');
class Less_Core
{
/**
* Get the link tag of less paths
*
* @param array array of css paths
* @param string value of media css type
* @param boolean allow compression
* @return string link tag pointing to the css paths
*/
public static function compile($array = array(), $media = 'screen')
{
// return comment if array is empty
if (empty($array)) return self::_html_comment('no less files');
$stylesheets = array();
$assets = array();
// validate
foreach ($array as $file)
{
// remove extension if its present
$file = preg_replace('/\.less/', '', $file);
if (file_exists($file.'.less'))
{
array_push($stylesheets, $file);
}
else
{
array_push($assets, self::_html_comment('could not find '.Kohana::debug_path($file).'.less'));
}
}
// all stylesheets are invalid
if ( ! count($stylesheets)) return self::_html_comment('all less files are invalid');
// get less config
$config = Kohana::config('less');
// if compression is allowed
if ($config['compress'])
{
return html::style(self::_combine($stylesheets), array('media' => $media));
}
// if no compression
foreach ($stylesheets as $file)
{
$filename = self::_get_filename($file, $config['path']);
array_push($assets, html::style($filename, array('media' => $media)));
}
return implode("\n", $assets);
}
/**
* Compress the css file
*
* @param string css string to compress
* @return string compressed css string
*/
private static function _compress($data)
{
$data = preg_replace('~/\*[^*]*\*+([^/][^*]*\*+)*/~', '', $data);
$data = preg_replace('~\s+~', ' ', $data);
$data = preg_replace('~ *+([{}+>:;,]) *~', '$1', trim($data));
$data = str_replace(';}', '}', $data);
$data = preg_replace('~[^{}]++\{\}~', '', $data);
return $data;
}
/**
* Check if the asset exists already, if not generate an asset
*
* @param string path of the css file
* @return string path to the asset file
*/
protected static function _get_filename($file, $path)
{
// get the filename
$filename = preg_replace('/^.+\//', '', $file);
// get the last modified date
$last_modified = self::_get_last_modified(array($file));
// compose the expected filename to store in /media/css
$compiled = $filename.'-'.$last_modified.'.css';
// compose the expected file path
$filename = $path.$compiled;
// if the file exists no need to generate
if ( ! file_exists($filename))
{
// create data holder
$data = '';
touch($filename, filemtime($file.'.less') - 3600);
lessc::ccompile($file.'.less', $filename);
}
return $filename;
}
/**
* Combine the files
*
* @param array array of asset files
* @return string path to the asset file
*/
protected static function _combine($files)
{
// get assets' css config
$config = Kohana::config('less');
// get the most recent modified time of any of the files
$last_modified = self::_get_last_modified($files);
// compose the asset filename
$compiled = md5(implode('|', $files)).'-'.$last_modified.'.css';
// compose the path to the asset file
$filename = $config['path'].$compiled;
// if the file exists no need to generate
if ( ! file_exists($filename))
{
self::_generate_assets($filename, $files);
}
return $filename;
}
/**
* Generate an asset file
*
* @param string filename of the asset file
* @param array array of source files
*/
protected static function _generate_assets($filename, $files)
{
// create data holder
$data = '';
touch($filename);
ob_start();
foreach($files as $file)
{
$data .= file_get_contents($file.'.less');
}
echo $data;
file_put_contents($filename, ob_get_clean(), LOCK_EX);
self::_compile($filename);
}
/**
* Compiles the file from less to css format
*
* @param string path to the file to compile
*/
public static function _compile($filename)
{
$less = new lessc($filename);
try
{
$compiled = $less->parse();
$compressed = self::_compress($compiled);
file_put_contents($filename, $compressed);
}
catch (LessException $ex)
{
exit($ex->getMessage());
}
}
/**
* Get the most recent modified date of files
*
* @param array array of asset files
* @return string path to the asset file
*/
protected static function _get_last_modified($files)
{
$last_modified = 0;
foreach ($files as $file)
{
$modified = filemtime($file.'.less');
if ($modified !== false and $modified > $last_modified) $last_modified = $modified;
}
return $last_modified;
}
/**
* Format string to HTML comment format
*
* @param string string to format
* @return string HTML comment
*/
protected static function _html_comment($string = '')
{
return '<!-- '.$string.' -->';
}
}

View file

@ -0,0 +1,25 @@
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Sample extends Controller_Template {
public $template = 'template';
public function action_index()
{
/**
*
* No need to add .less extension, but if you REALLY want to it should still work.
* You can put your less files anywhere, APPPATH or MODPATH...
* I like to put my media files (less / css / js) on my applications for cleaner organization.
* Another trick is to use Kohana::find_file('media', '/less/filename', 'less') so you can abuse cascading.
*
*/
$less_files = array
(
APPPATH.'media/less/layout',
APPPATH.'media/less/style',
);
$this->template->stylesheet = Less::compile($less_files);
}
}

View file

@ -0,0 +1,8 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
return array(
'compress' => TRUE,
'path' => 'media/css/', // relative path to a writable folder from DOCROOT to store the compiled css
);

View file

@ -0,0 +1,14 @@
@bodyBkgColor: #000;
body {
background: @bodyBkgColor;
margin: 0;
padding: 0;
div {
margin: 30px auto;
width: 480px;
h1 { font-size: 3em; }
}
}

View file

@ -0,0 +1,44 @@
@divBkgColor: #DDD;
@headlineColor: #EEE;
.roundedCorners (@radius:8px) {
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
zoom: 1;
}
.shadow (@disperse: 5px) {
-moz-box-shadow:1px 1px @disperse #999;
-webkit-box-shadow:1px 1px @disperse #999;
}
div {
border:5px solid #666;
background: @divBkgColor;
padding: 60px;
.roundedCorners;
h1 {
background: @headlineColor;
font-family: Arial, sans-serif;
letter-spacing:-3px;
line-height:1;
padding: 30px;
margin:0 auto;
.roundedCorners(16px);
.shadow;
text-align:center;
width: 240px;
span {
color:#999;
display:block;
letter-spacing:1px;
font-size:14px;
font-weight:bold;
padding-top:10px;
text-transform:uppercase;
}
}
}

View file

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
<title>LESS for Kohana</title>
<?= $stylesheet; // will give me ONE compressed css file located in DOCROOT/media/css/ ?>
</head>
<body>
<div>
<h1>LESS port for KO3. <span>Because I want it CLEAN.</span></h1>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
body div h1{font-size:3em}body div{margin:30px auto;width:480px}body{background:#000000;margin:0;padding:0}.roundedCorners{-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px;zoom:1}.shadow{-moz-box-shadow:1px 1px 5px #999999;-webkit-box-shadow:1px 1px 5px #999999}div h1 span{color:#999999;display:block;letter-spacing:1px;font-size:14px;font-weight:bold;padding-top:10px;text-transform:uppercase}div h1{background:#eeeeee;font-family:Arial,sans-serif;letter-spacing:-3px;line-height:1;padding:30px;margin:0 auto;-moz-border-radius:16px;-webkit-border-radius:16px;border-radius:16px;zoom:1;-moz-box-shadow:1px 1px 5px #999999;-webkit-box-shadow:1px 1px 5px #999999;text-align:center;width:240px}div{border:5px solid #666666;background:#dddddd;padding:60px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px;zoom:1}