├── .gitmodules ├── README.md ├── classes ├── Less.php └── Less │ └── Core.php ├── config └── less.php ├── init.php └── vendor └── ASSETS /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/lessphp"] 2 | path = vendor/lessphp 3 | url = git://github.com/leafo/lessphp.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | KO3 LESS Module v.1.1.1 2 | ======================= 3 | 4 | LESS Module is a port of Leaf Corcoran's [LESSPHP](http://leafo.net/lessphp) for Kohana 3 5 | It adopts some of Alex Sancho's Kohana 2.3 Assets Module codes for CSS compression, credits goes to them 6 | Thanks to [cheeaun](http://github.com/cheeaun) for helping out! 7 | You might also want to check out another implementation from [jeremeamia](http://github.com/jeremeamia/kohana-less). 8 | 9 | To Use 10 | ------- 11 | 1. Put the less module folder in your Modules directory 12 | 2. Include less module in your application's bootstrap: 'less' => MODPATH.'less' 13 | 3. Copy the less config file from /modules/less/config/less.php to your application's config directory 14 | 4. From your less.php config file, put the 'path' to where you want the CSS files compiled / compressed, the folder must be writable 15 | 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) 16 | 17 | Sample Code 18 | ------------ 19 | 20 | Default less files extension is set in `Less::$extension` and is `.less`. 21 | 22 | 23 | ** MODPATH/baseModule/media/css/layout.less ** 24 | 25 | @bodyBkgColor: #EEE; 26 | 27 | body { 28 | background: @bodyBkgColor; 29 | margin:0; 30 | padding:0; 31 | 32 | h1 { font-size: 3em; } 33 | } 34 | 35 | ** APPPATH/media/css/style.less ** 36 | 37 | @divBkgColor: #DDD; 38 | 39 | .roundedCorners (@radius:8px) { 40 | -moz-border-radius:@radius; 41 | -webkit-border-radius:@radius; 42 | border-radius:@radius; 43 | zoom:1; 44 | } 45 | 46 | div { 47 | background: @divBkgColor; 48 | .roundedCorners; 49 | 50 | p { .roundedCorners(5px); } 51 | } 52 | 53 | ** APPPATH/config/less.php ** 54 | 55 | return array( 56 | // relative PATH to a writable folder to store compiled / compressed css 57 | // path below will be treated as: DOCROOT . 'media/css/' 58 | 'path' => 'media/css/', 59 | 'compress' => TRUE, 60 | ); 61 | 62 | ** In your controller ** 63 | 64 | class Controller_Sample extends Controller_Template { 65 | 66 | public $template = 'template'; 67 | 68 | public function action_example1() 69 | { 70 | // no need to add .less extension 71 | // you can put your less files anywhere 72 | $less_files = array 73 | ( 74 | MODPATH.'baseModule/media/css/layout.less', 75 | APPPATH.'media/css/style', 76 | ); 77 | 78 | $this->template->stylesheet = Less::compile($less_files); 79 | } 80 | 81 | public function action_example2() 82 | { 83 | // you can pass just single file 84 | 85 | $this->template->stylesheet = Less::compile(APPPATH.'media/css/style'); 86 | } 87 | } 88 | 89 | ** In your template ** 90 | 91 | 92 | 93 | LESS for Kohana 94 | 95 | 96 | 97 |

LESS for Kohana or Kohana for LESS?

98 | 99 | 100 | 101 | Issues 102 | ------- 103 | Please report it to the [issues tracker](http://github.com/mongeslani/kohana-less/issues).. -------------------------------------------------------------------------------- /classes/Less.php: -------------------------------------------------------------------------------- 1 | load('less'); 51 | 52 | // Clear compiled folder? 53 | if ($config['clear_first']) { 54 | self::clear_folder($config['path']); 55 | } 56 | 57 | // if compression is allowed 58 | if ($config['compress']) 59 | { 60 | return HTML::style(self::_combine($stylesheets), array('media' => $media)); 61 | } 62 | 63 | // if no compression 64 | foreach ($stylesheets as $file) 65 | { 66 | $filename = self::_get_filename($file, $config['path'], $config['clear_first']); 67 | array_push($assets, html::style($filename, array('media' => $media))); 68 | } 69 | 70 | return implode("\n", $assets); 71 | } 72 | 73 | /** 74 | * Compress the css file 75 | * 76 | * @param string css string to compress 77 | * @return string compressed css string 78 | */ 79 | private static function _compress($data) 80 | { 81 | $data = preg_replace('~/\*[^*]*\*+([^/][^*]*\*+)*/~', '', $data); 82 | $data = preg_replace('~\s+~', ' ', $data); 83 | $data = preg_replace('~ *+([{}+>:;,]) *~', '$1', trim($data)); 84 | $data = str_replace(';}', '}', $data); 85 | $data = preg_replace('~[^{}]++\{\}~', '', $data); 86 | 87 | return $data; 88 | } 89 | 90 | /** 91 | * Check if the asset exists already, if not generate an asset 92 | * 93 | * @param string $file The filename to check. 94 | * @param string $path The path of the css file. 95 | * @param boolean $clear_first If we should clear the provided folder first. 96 | * @return string path to the asset file 97 | */ 98 | protected static function _get_filename($file, $path, $clear_first) 99 | { 100 | // get the filename 101 | $filename = preg_replace('/^.+\//', '', $file); 102 | 103 | // get the last modified date 104 | $last_modified = self::_get_last_modified(array($file)); 105 | 106 | // compose the expected filename to store in /media/css 107 | $compiled = $filename.'-'.$last_modified.'.css'; 108 | 109 | // compose the expected file path 110 | $filename = $path.$compiled; 111 | 112 | // if the file exists no need to generate 113 | if ( ! file_exists($filename)) 114 | { 115 | touch($filename, filemtime($file) - 3600); 116 | 117 | lessc::ccompile($file, $filename); 118 | } 119 | 120 | return $filename; 121 | } 122 | 123 | /** 124 | * Combine the files 125 | * 126 | * @param array array of asset files 127 | * @return string path to the asset file 128 | */ 129 | protected static function _combine($files) 130 | { 131 | // get assets' css config 132 | $config = Kohana::$config->load('less'); 133 | 134 | // get the most recent modified time of any of the files 135 | $last_modified = self::_get_last_modified($files); 136 | 137 | // compose the asset filename 138 | $compiled = md5(implode('|', $files)).'-'.$last_modified.'.css'; 139 | 140 | // compose the path to the asset file 141 | $filename = $config['path'].$compiled; 142 | 143 | // if the file exists no need to generate 144 | if ( ! file_exists($filename)) 145 | { 146 | self::_generate_assets($filename, $files); 147 | } 148 | 149 | return $filename; 150 | } 151 | 152 | /** 153 | * Generate an asset file 154 | * 155 | * @param string filename of the asset file 156 | * @param array array of source files 157 | */ 158 | protected static function _generate_assets($filename, $files) 159 | { 160 | // create data holder 161 | $data = ''; 162 | 163 | touch($filename); 164 | 165 | ob_start(); 166 | 167 | foreach($files as $file) 168 | { 169 | $data .= file_get_contents($file); 170 | } 171 | 172 | echo $data; 173 | 174 | file_put_contents($filename, ob_get_clean(), LOCK_EX); 175 | 176 | self::_compile($filename); 177 | } 178 | 179 | /** 180 | * Compiles the file from less to css format 181 | * 182 | * @param string path to the file to compile 183 | */ 184 | public static function _compile($filename) 185 | { 186 | $less = new lessc($filename); 187 | 188 | try 189 | { 190 | $compiled = $less->parse(); 191 | $compressed = self::_compress($compiled); 192 | file_put_contents($filename, $compressed); 193 | } 194 | catch (LessException $ex) 195 | { 196 | exit($ex->getMessage()); 197 | } 198 | } 199 | 200 | /** 201 | * Get the most recent modified date of files 202 | * 203 | * @param array array of asset files 204 | * @return string path to the asset file 205 | */ 206 | protected static function _get_last_modified($files) 207 | { 208 | $last_modified = 0; 209 | 210 | foreach ($files as $file) 211 | { 212 | $modified = filemtime($file); 213 | if ($modified !== false and $modified > $last_modified) $last_modified = $modified; 214 | } 215 | 216 | return $last_modified; 217 | } 218 | 219 | /** 220 | * Format string to HTML comment format 221 | * 222 | * @param string string to format 223 | * @return string HTML comment 224 | */ 225 | protected static function _html_comment($string = '') 226 | { 227 | return ''; 228 | } 229 | 230 | /** 231 | * Delete all files from a provided folder. 232 | * 233 | * @param string $path The path to clear. 234 | * 235 | * @return void 236 | */ 237 | private static function clear_folder($path) { 238 | $files = glob("$path*"); 239 | foreach ($files as $file){ 240 | if (is_file($file)) { 241 | unlink($file); 242 | } 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /config/less.php: -------------------------------------------------------------------------------- 1 | FALSE, 6 | 'path' => '', // relative path to a writable folder to store compiled / compressed css 7 | 'clear_first' => false, // Clear the provided folder before writing new file 8 | ); -------------------------------------------------------------------------------- /init.php: -------------------------------------------------------------------------------- 1 |