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:
parent
cbe2fa4793
commit
bc29934fbf
60
README.md
60
README.md
|
@ -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>
|
||||
|
|
115
classes/less.php
115
classes/less.php
|
@ -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
BIN
classes/less/.DS_Store
vendored
Normal file
Binary file not shown.
216
classes/less/core.php
Normal file
216
classes/less/core.php
Normal 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.' -->';
|
||||
}
|
||||
}
|
25
sample-code/application/classes/controller/sample.php
Normal file
25
sample-code/application/classes/controller/sample.php
Normal 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);
|
||||
}
|
||||
}
|
8
sample-code/application/config/less.php
Normal file
8
sample-code/application/config/less.php
Normal 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
|
||||
|
||||
);
|
14
sample-code/application/media/less/layout.less
Normal file
14
sample-code/application/media/less/layout.less
Normal file
|
@ -0,0 +1,14 @@
|
|||
@bodyBkgColor: #000;
|
||||
|
||||
body {
|
||||
background: @bodyBkgColor;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
div {
|
||||
margin: 30px auto;
|
||||
width: 480px;
|
||||
|
||||
h1 { font-size: 3em; }
|
||||
}
|
||||
}
|
44
sample-code/application/media/less/style.less
Normal file
44
sample-code/application/media/less/style.less
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
12
sample-code/application/views/template.php
Normal file
12
sample-code/application/views/template.php
Normal 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>
|
|
@ -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}
|
Loading…
Reference in a new issue