├── .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 | = $stylesheet; // will give me ONE compressed css file located in /media/css/ ?>
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 |