Magemaven_Lesscss - Version 1.0.0

Version Notes

Release 1.0.0

Download this release

Release Info

Developer Sergey Storchay
Extension Magemaven_Lesscss
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

Files changed (67) hide show
  1. app/code/community/Magemaven/Lesscss/Helper/Data.php +75 -0
  2. app/code/community/Magemaven/Lesscss/Model/Design/Package.php +53 -0
  3. app/code/community/Magemaven/Lesscss/etc/config.xml +38 -0
  4. app/etc/modules/Magemaven_Lesscss.xml +25 -0
  5. lib/lessphp/.gitignore +6 -0
  6. lib/lessphp/LICENSE +660 -0
  7. lib/lessphp/README.md +64 -0
  8. lib/lessphp/docs/docs.md +992 -0
  9. lib/lessphp/lessc.inc.php +2622 -0
  10. lib/lessphp/lessify +23 -0
  11. lib/lessphp/lessify.inc.php +447 -0
  12. lib/lessphp/package.sh +22 -0
  13. lib/lessphp/plessc +193 -0
  14. lib/lessphp/tests/README.md +24 -0
  15. lib/lessphp/tests/bootstrap.sh +49 -0
  16. lib/lessphp/tests/inputs/accessors.less.disable +36 -0
  17. lib/lessphp/tests/inputs/arity.less +77 -0
  18. lib/lessphp/tests/inputs/attributes.less +41 -0
  19. lib/lessphp/tests/inputs/builtins.less +34 -0
  20. lib/lessphp/tests/inputs/colors.less +122 -0
  21. lib/lessphp/tests/inputs/compile_on_mixin.less +39 -0
  22. lib/lessphp/tests/inputs/escape.less +19 -0
  23. lib/lessphp/tests/inputs/font_family.less +28 -0
  24. lib/lessphp/tests/inputs/guards.less +88 -0
  25. lib/lessphp/tests/inputs/hacks.less +6 -0
  26. lib/lessphp/tests/inputs/import.less +21 -0
  27. lib/lessphp/tests/inputs/keyframes.less +48 -0
  28. lib/lessphp/tests/inputs/math.less +116 -0
  29. lib/lessphp/tests/inputs/media.less +38 -0
  30. lib/lessphp/tests/inputs/misc.less +78 -0
  31. lib/lessphp/tests/inputs/mixin_functions.less +40 -0
  32. lib/lessphp/tests/inputs/mixin_merging.less.disable +100 -0
  33. lib/lessphp/tests/inputs/mixins.less +122 -0
  34. lib/lessphp/tests/inputs/nested.less +60 -0
  35. lib/lessphp/tests/inputs/pattern_matching.less +113 -0
  36. lib/lessphp/tests/inputs/scopes.less +40 -0
  37. lib/lessphp/tests/inputs/site_demos.less +120 -0
  38. lib/lessphp/tests/inputs/test-imports/file1.less +16 -0
  39. lib/lessphp/tests/inputs/test-imports/file2.less +6 -0
  40. lib/lessphp/tests/inputs/variables.less +45 -0
  41. lib/lessphp/tests/outputs/accessors.css +14 -0
  42. lib/lessphp/tests/outputs/arity.css +25 -0
  43. lib/lessphp/tests/outputs/attributes.css +35 -0
  44. lib/lessphp/tests/outputs/builtins.css +18 -0
  45. lib/lessphp/tests/outputs/colors.css +69 -0
  46. lib/lessphp/tests/outputs/compile_on_mixin.css +11 -0
  47. lib/lessphp/tests/outputs/escape.css +13 -0
  48. lib/lessphp/tests/outputs/font_family.css +17 -0
  49. lib/lessphp/tests/outputs/guards.css +23 -0
  50. lib/lessphp/tests/outputs/hacks.css +1 -0
  51. lib/lessphp/tests/outputs/import.css +14 -0
  52. lib/lessphp/tests/outputs/keyframes.css +36 -0
  53. lib/lessphp/tests/outputs/math.css +61 -0
  54. lib/lessphp/tests/outputs/media.css +28 -0
  55. lib/lessphp/tests/outputs/misc.css +32 -0
  56. lib/lessphp/tests/outputs/mixin_functions.css +14 -0
  57. lib/lessphp/tests/outputs/mixin_merging.css +42 -0
  58. lib/lessphp/tests/outputs/mixins.css +49 -0
  59. lib/lessphp/tests/outputs/nested.css +16 -0
  60. lib/lessphp/tests/outputs/nesting.css +6 -0
  61. lib/lessphp/tests/outputs/pattern_matching.css +48 -0
  62. lib/lessphp/tests/outputs/scopes.css +7 -0
  63. lib/lessphp/tests/outputs/site_demos.css +54 -0
  64. lib/lessphp/tests/outputs/variables.css +20 -0
  65. lib/lessphp/tests/sort.php +57 -0
  66. lib/lessphp/tests/test.php +190 -0
  67. package.xml +18 -0
app/code/community/Magemaven/Lesscss/Helper/Data.php ADDED
@@ -0,0 +1,75 @@
1
+ <?php
2
+ /**
3
+ * This source file is subject to the Academic Free License (AFL 3.0)
4
+ * that is bundled with this package in the file LICENSE_AFL.txt.
5
+ * It is also available through the world-wide-web at this URL:
6
+ * http://opensource.org/licenses/afl-3.0.php
7
+ *
8
+ * @category Magemaven
9
+ * @package Magemaven_Lesscss
10
+ * @copyright Copyright (c) 2012 Sergey Storchay <r8@r8.com.ua>
11
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
12
+ */
13
+ require_once(Mage::getBaseDir('lib') . DS . 'lessphp' . DS .'lessc.inc.php');
14
+
15
+ class Magemaven_Lesscss_Helper_Data extends Mage_Core_Helper_Abstract
16
+ {
17
+ /**
18
+ * Get file extension in lower case
19
+ *
20
+ * @param $file
21
+ * @return string
22
+ */
23
+ public function getFileExtension($file)
24
+ {
25
+ return strtolower(pathinfo($file, PATHINFO_EXTENSION));
26
+ }
27
+
28
+ /**
29
+ * Compile less file and return full path to created css
30
+ *
31
+ * @param $file
32
+ * @return string
33
+ */
34
+ public function compile($file)
35
+ {
36
+ if (!$file) {
37
+ return '';
38
+ }
39
+
40
+ try {
41
+ $targetFilename = Mage::getBaseDir('media')
42
+ . DS . 'lesscss' . DS . md5($file) . '.css';
43
+ $cacheKey = 'less_' . $file;
44
+
45
+ /** @var $cacheModel Mage_Core_Model_Cache */
46
+ $cacheModel = $cache = Mage::getSingleton('core/cache');
47
+ $cache = $cacheModel->load($cacheKey);
48
+ if ($cache) {
49
+ $cache = @unserialize($cache);
50
+ }
51
+
52
+ if (!file_exists($targetFilename)) {
53
+ $cache = false;
54
+ }
55
+
56
+ $lastUpdated = (isset($cache['updated'])) ? $cache['updated'] : 0;
57
+ $cache = lessc::cexecute(($cache) ? $cache : $file);
58
+
59
+ if ($cache['updated'] > $lastUpdated) {
60
+ if (!file_exists(dirname($targetFilename))) {
61
+ mkdir(dirname($targetFilename), 0777, true);
62
+ }
63
+
64
+ file_put_contents($targetFilename, $cache['compiled']);
65
+ $cacheModel->save(serialize($cache), $cacheKey);
66
+ }
67
+
68
+ } catch (Exception $e) {
69
+ Mage::logException($e);
70
+ $targetFilename = '';
71
+ }
72
+
73
+ return $targetFilename;
74
+ }
75
+ }
app/code/community/Magemaven/Lesscss/Model/Design/Package.php ADDED
@@ -0,0 +1,53 @@
1
+ <?php
2
+ /**
3
+ * This source file is subject to the Academic Free License (AFL 3.0)
4
+ * that is bundled with this package in the file LICENSE_AFL.txt.
5
+ * It is also available through the world-wide-web at this URL:
6
+ * http://opensource.org/licenses/afl-3.0.php
7
+ *
8
+ * @category Magemaven
9
+ * @package Magemaven_Lesscss
10
+ * @copyright Copyright (c) 2012 Sergey Storchay <r8@r8.com.ua>
11
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
12
+ */
13
+ class Magemaven_Lesscss_Model_Design_Package extends Mage_Core_Model_Design_Package
14
+ {
15
+ public function getSkinUrl($file = null, array $params = array())
16
+ {
17
+ if (empty($params['_type'])) {
18
+ $params['_type'] = 'skin';
19
+ }
20
+
21
+ /** @var $helper Magemaven_Lesscss_Helper_Data */
22
+ $helper = Mage::helper('lesscss');
23
+
24
+ if ($helper->getFileExtension($file) == 'less') {
25
+ $file = $this->getFilename($file, $params);
26
+
27
+ if ($file) {
28
+ $file = str_replace(Mage::getBaseDir('media') . DS, '', $file);
29
+ $file = str_replace('\\', '/', $file);
30
+ $file = Mage::getBaseUrl('media',
31
+ isset($params['_secure']) ? (bool)$params['_secure'] : null
32
+ ) . $file;
33
+ }
34
+ } else {
35
+ $file = parent::getSkinUrl($file, $params);
36
+ }
37
+
38
+ return $file;
39
+ }
40
+
41
+ public function getFilename($file, array $params)
42
+ {
43
+ /** @var $helper Magemaven_Lesscss_Helper_Data */
44
+ $helper = Mage::helper('lesscss');
45
+
46
+ $file = parent::getFilename($file, $params);
47
+ if ($helper->getFileExtension($file) == 'less') {
48
+ $file = $helper->compile($file);
49
+ }
50
+
51
+ return $file;
52
+ }
53
+ }
app/code/community/Magemaven/Lesscss/etc/config.xml ADDED
@@ -0,0 +1,38 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * This source file is subject to the Academic Free License (AFL 3.0)
5
+ * that is bundled with this package in the file LICENSE_AFL.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://opensource.org/licenses/afl-3.0.php
8
+ *
9
+ * @category Magemaven
10
+ * @package Magemaven_Lesscss
11
+ * @copyright Copyright (c) 2012 Sergey Storchay <r8@r8.com.ua>
12
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
13
+ */
14
+ -->
15
+ <config>
16
+ <modules>
17
+ <Magemaven_Lesscss>
18
+ <version>1.0.0.0</version>
19
+ </Magemaven_Lesscss>
20
+ </modules>
21
+ <global>
22
+ <models>
23
+ <lesscss>
24
+ <class>Magemaven_Lesscss_Model</class>
25
+ </lesscss>
26
+ <core>
27
+ <rewrite>
28
+ <design_package>Magemaven_Lesscss_Model_Design_Package</design_package>
29
+ </rewrite>
30
+ </core>
31
+ </models>
32
+ <helpers>
33
+ <lesscss>
34
+ <class>Magemaven_Lesscss_Helper</class>
35
+ </lesscss>
36
+ </helpers>
37
+ </global>
38
+ </config>
app/etc/modules/Magemaven_Lesscss.xml ADDED
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * This source file is subject to the Academic Free License (AFL 3.0)
5
+ * that is bundled with this package in the file LICENSE_AFL.txt.
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://opensource.org/licenses/afl-3.0.php
8
+ *
9
+ * @category Magemaven
10
+ * @package Magemaven_Lesscss
11
+ * @copyright Copyright (c) 2012 Sergey Storchay <r8@r8.com.ua>
12
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
13
+ */
14
+ -->
15
+ <config>
16
+ <modules>
17
+ <Magemaven_Lesscss>
18
+ <active>true</active>
19
+ <codePool>community</codePool>
20
+ <depends>
21
+ <Mage_Core />
22
+ </depends>
23
+ </Magemaven_Lesscss>
24
+ </modules>
25
+ </config>
lib/lessphp/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.swp
2
+ *~
3
+ /*.less
4
+ /*.css
5
+ tests/bootstrap
6
+ tests/tmp
lib/lessphp/LICENSE ADDED
@@ -0,0 +1,660 @@
1
+ For ease of distribution, lessphp 0.2.0 is under a dual license.
2
+ You are free to pick which one suits your needs.
3
+
4
+
5
+
6
+
7
+ MIT LICENSE
8
+
9
+
10
+
11
+
12
+ Copyright (c) 2010 Leaf Corcoran, http://leafo.net/lessphp
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining
15
+ a copy of this software and associated documentation files (the
16
+ "Software"), to deal in the Software without restriction, including
17
+ without limitation the rights to use, copy, modify, merge, publish,
18
+ distribute, sublicense, and/or sell copies of the Software, and to
19
+ permit persons to whom the Software is furnished to do so, subject to
20
+ the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be
23
+ included in all copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
+
33
+
34
+
35
+
36
+ GPL VERSION 3
37
+
38
+
39
+
40
+
41
+ GNU GENERAL PUBLIC LICENSE
42
+ Version 3, 29 June 2007
43
+
44
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
45
+ Everyone is permitted to copy and distribute verbatim copies
46
+ of this license document, but changing it is not allowed.
47
+
48
+ Preamble
49
+
50
+ The GNU General Public License is a free, copyleft license for
51
+ software and other kinds of works.
52
+
53
+ The licenses for most software and other practical works are designed
54
+ to take away your freedom to share and change the works. By contrast,
55
+ the GNU General Public License is intended to guarantee your freedom to
56
+ share and change all versions of a program--to make sure it remains free
57
+ software for all its users. We, the Free Software Foundation, use the
58
+ GNU General Public License for most of our software; it applies also to
59
+ any other work released this way by its authors. You can apply it to
60
+ your programs, too.
61
+
62
+ When we speak of free software, we are referring to freedom, not
63
+ price. Our General Public Licenses are designed to make sure that you
64
+ have the freedom to distribute copies of free software (and charge for
65
+ them if you wish), that you receive source code or can get it if you
66
+ want it, that you can change the software or use pieces of it in new
67
+ free programs, and that you know you can do these things.
68
+
69
+ To protect your rights, we need to prevent others from denying you
70
+ these rights or asking you to surrender the rights. Therefore, you have
71
+ certain responsibilities if you distribute copies of the software, or if
72
+ you modify it: responsibilities to respect the freedom of others.
73
+
74
+ For example, if you distribute copies of such a program, whether
75
+ gratis or for a fee, you must pass on to the recipients the same
76
+ freedoms that you received. You must make sure that they, too, receive
77
+ or can get the source code. And you must show them these terms so they
78
+ know their rights.
79
+
80
+ Developers that use the GNU GPL protect your rights with two steps:
81
+ (1) assert copyright on the software, and (2) offer you this License
82
+ giving you legal permission to copy, distribute and/or modify it.
83
+
84
+ For the developers' and authors' protection, the GPL clearly explains
85
+ that there is no warranty for this free software. For both users' and
86
+ authors' sake, the GPL requires that modified versions be marked as
87
+ changed, so that their problems will not be attributed erroneously to
88
+ authors of previous versions.
89
+
90
+ Some devices are designed to deny users access to install or run
91
+ modified versions of the software inside them, although the manufacturer
92
+ can do so. This is fundamentally incompatible with the aim of
93
+ protecting users' freedom to change the software. The systematic
94
+ pattern of such abuse occurs in the area of products for individuals to
95
+ use, which is precisely where it is most unacceptable. Therefore, we
96
+ have designed this version of the GPL to prohibit the practice for those
97
+ products. If such problems arise substantially in other domains, we
98
+ stand ready to extend this provision to those domains in future versions
99
+ of the GPL, as needed to protect the freedom of users.
100
+
101
+ Finally, every program is threatened constantly by software patents.
102
+ States should not allow patents to restrict development and use of
103
+ software on general-purpose computers, but in those that do, we wish to
104
+ avoid the special danger that patents applied to a free program could
105
+ make it effectively proprietary. To prevent this, the GPL assures that
106
+ patents cannot be used to render the program non-free.
107
+
108
+ The precise terms and conditions for copying, distribution and
109
+ modification follow.
110
+
111
+ TERMS AND CONDITIONS
112
+
113
+ 0. Definitions.
114
+
115
+ "This License" refers to version 3 of the GNU General Public License.
116
+
117
+ "Copyright" also means copyright-like laws that apply to other kinds of
118
+ works, such as semiconductor masks.
119
+
120
+ "The Program" refers to any copyrightable work licensed under this
121
+ License. Each licensee is addressed as "you". "Licensees" and
122
+ "recipients" may be individuals or organizations.
123
+
124
+ To "modify" a work means to copy from or adapt all or part of the work
125
+ in a fashion requiring copyright permission, other than the making of an
126
+ exact copy. The resulting work is called a "modified version" of the
127
+ earlier work or a work "based on" the earlier work.
128
+
129
+ A "covered work" means either the unmodified Program or a work based
130
+ on the Program.
131
+
132
+ To "propagate" a work means to do anything with it that, without
133
+ permission, would make you directly or secondarily liable for
134
+ infringement under applicable copyright law, except executing it on a
135
+ computer or modifying a private copy. Propagation includes copying,
136
+ distribution (with or without modification), making available to the
137
+ public, and in some countries other activities as well.
138
+
139
+ To "convey" a work means any kind of propagation that enables other
140
+ parties to make or receive copies. Mere interaction with a user through
141
+ a computer network, with no transfer of a copy, is not conveying.
142
+
143
+ An interactive user interface displays "Appropriate Legal Notices"
144
+ to the extent that it includes a convenient and prominently visible
145
+ feature that (1) displays an appropriate copyright notice, and (2)
146
+ tells the user that there is no warranty for the work (except to the
147
+ extent that warranties are provided), that licensees may convey the
148
+ work under this License, and how to view a copy of this License. If
149
+ the interface presents a list of user commands or options, such as a
150
+ menu, a prominent item in the list meets this criterion.
151
+
152
+ 1. Source Code.
153
+
154
+ The "source code" for a work means the preferred form of the work
155
+ for making modifications to it. "Object code" means any non-source
156
+ form of a work.
157
+
158
+ A "Standard Interface" means an interface that either is an official
159
+ standard defined by a recognized standards body, or, in the case of
160
+ interfaces specified for a particular programming language, one that
161
+ is widely used among developers working in that language.
162
+
163
+ The "System Libraries" of an executable work include anything, other
164
+ than the work as a whole, that (a) is included in the normal form of
165
+ packaging a Major Component, but which is not part of that Major
166
+ Component, and (b) serves only to enable use of the work with that
167
+ Major Component, or to implement a Standard Interface for which an
168
+ implementation is available to the public in source code form. A
169
+ "Major Component", in this context, means a major essential component
170
+ (kernel, window system, and so on) of the specific operating system
171
+ (if any) on which the executable work runs, or a compiler used to
172
+ produce the work, or an object code interpreter used to run it.
173
+
174
+ The "Corresponding Source" for a work in object code form means all
175
+ the source code needed to generate, install, and (for an executable
176
+ work) run the object code and to modify the work, including scripts to
177
+ control those activities. However, it does not include the work's
178
+ System Libraries, or general-purpose tools or generally available free
179
+ programs which are used unmodified in performing those activities but
180
+ which are not part of the work. For example, Corresponding Source
181
+ includes interface definition files associated with source files for
182
+ the work, and the source code for shared libraries and dynamically
183
+ linked subprograms that the work is specifically designed to require,
184
+ such as by intimate data communication or control flow between those
185
+ subprograms and other parts of the work.
186
+
187
+ The Corresponding Source need not include anything that users
188
+ can regenerate automatically from other parts of the Corresponding
189
+ Source.
190
+
191
+ The Corresponding Source for a work in source code form is that
192
+ same work.
193
+
194
+ 2. Basic Permissions.
195
+
196
+ All rights granted under this License are granted for the term of
197
+ copyright on the Program, and are irrevocable provided the stated
198
+ conditions are met. This License explicitly affirms your unlimited
199
+ permission to run the unmodified Program. The output from running a
200
+ covered work is covered by this License only if the output, given its
201
+ content, constitutes a covered work. This License acknowledges your
202
+ rights of fair use or other equivalent, as provided by copyright law.
203
+
204
+ You may make, run and propagate covered works that you do not
205
+ convey, without conditions so long as your license otherwise remains
206
+ in force. You may convey covered works to others for the sole purpose
207
+ of having them make modifications exclusively for you, or provide you
208
+ with facilities for running those works, provided that you comply with
209
+ the terms of this License in conveying all material for which you do
210
+ not control copyright. Those thus making or running the covered works
211
+ for you must do so exclusively on your behalf, under your direction
212
+ and control, on terms that prohibit them from making any copies of
213
+ your copyrighted material outside their relationship with you.
214
+
215
+ Conveying under any other circumstances is permitted solely under
216
+ the conditions stated below. Sublicensing is not allowed; section 10
217
+ makes it unnecessary.
218
+
219
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
220
+
221
+ No covered work shall be deemed part of an effective technological
222
+ measure under any applicable law fulfilling obligations under article
223
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
224
+ similar laws prohibiting or restricting circumvention of such
225
+ measures.
226
+
227
+ When you convey a covered work, you waive any legal power to forbid
228
+ circumvention of technological measures to the extent such circumvention
229
+ is effected by exercising rights under this License with respect to
230
+ the covered work, and you disclaim any intention to limit operation or
231
+ modification of the work as a means of enforcing, against the work's
232
+ users, your or third parties' legal rights to forbid circumvention of
233
+ technological measures.
234
+
235
+ 4. Conveying Verbatim Copies.
236
+
237
+ You may convey verbatim copies of the Program's source code as you
238
+ receive it, in any medium, provided that you conspicuously and
239
+ appropriately publish on each copy an appropriate copyright notice;
240
+ keep intact all notices stating that this License and any
241
+ non-permissive terms added in accord with section 7 apply to the code;
242
+ keep intact all notices of the absence of any warranty; and give all
243
+ recipients a copy of this License along with the Program.
244
+
245
+ You may charge any price or no price for each copy that you convey,
246
+ and you may offer support or warranty protection for a fee.
247
+
248
+ 5. Conveying Modified Source Versions.
249
+
250
+ You may convey a work based on the Program, or the modifications to
251
+ produce it from the Program, in the form of source code under the
252
+ terms of section 4, provided that you also meet all of these conditions:
253
+
254
+ a) The work must carry prominent notices stating that you modified
255
+ it, and giving a relevant date.
256
+
257
+ b) The work must carry prominent notices stating that it is
258
+ released under this License and any conditions added under section
259
+ 7. This requirement modifies the requirement in section 4 to
260
+ "keep intact all notices".
261
+
262
+ c) You must license the entire work, as a whole, under this
263
+ License to anyone who comes into possession of a copy. This
264
+ License will therefore apply, along with any applicable section 7
265
+ additional terms, to the whole of the work, and all its parts,
266
+ regardless of how they are packaged. This License gives no
267
+ permission to license the work in any other way, but it does not
268
+ invalidate such permission if you have separately received it.
269
+
270
+ d) If the work has interactive user interfaces, each must display
271
+ Appropriate Legal Notices; however, if the Program has interactive
272
+ interfaces that do not display Appropriate Legal Notices, your
273
+ work need not make them do so.
274
+
275
+ A compilation of a covered work with other separate and independent
276
+ works, which are not by their nature extensions of the covered work,
277
+ and which are not combined with it such as to form a larger program,
278
+ in or on a volume of a storage or distribution medium, is called an
279
+ "aggregate" if the compilation and its resulting copyright are not
280
+ used to limit the access or legal rights of the compilation's users
281
+ beyond what the individual works permit. Inclusion of a covered work
282
+ in an aggregate does not cause this License to apply to the other
283
+ parts of the aggregate.
284
+
285
+ 6. Conveying Non-Source Forms.
286
+
287
+ You may convey a covered work in object code form under the terms
288
+ of sections 4 and 5, provided that you also convey the
289
+ machine-readable Corresponding Source under the terms of this License,
290
+ in one of these ways:
291
+
292
+ a) Convey the object code in, or embodied in, a physical product
293
+ (including a physical distribution medium), accompanied by the
294
+ Corresponding Source fixed on a durable physical medium
295
+ customarily used for software interchange.
296
+
297
+ b) Convey the object code in, or embodied in, a physical product
298
+ (including a physical distribution medium), accompanied by a
299
+ written offer, valid for at least three years and valid for as
300
+ long as you offer spare parts or customer support for that product
301
+ model, to give anyone who possesses the object code either (1) a
302
+ copy of the Corresponding Source for all the software in the
303
+ product that is covered by this License, on a durable physical
304
+ medium customarily used for software interchange, for a price no
305
+ more than your reasonable cost of physically performing this
306
+ conveying of source, or (2) access to copy the
307
+ Corresponding Source from a network server at no charge.
308
+
309
+ c) Convey individual copies of the object code with a copy of the
310
+ written offer to provide the Corresponding Source. This
311
+ alternative is allowed only occasionally and noncommercially, and
312
+ only if you received the object code with such an offer, in accord
313
+ with subsection 6b.
314
+
315
+ d) Convey the object code by offering access from a designated
316
+ place (gratis or for a charge), and offer equivalent access to the
317
+ Corresponding Source in the same way through the same place at no
318
+ further charge. You need not require recipients to copy the
319
+ Corresponding Source along with the object code. If the place to
320
+ copy the object code is a network server, the Corresponding Source
321
+ may be on a different server (operated by you or a third party)
322
+ that supports equivalent copying facilities, provided you maintain
323
+ clear directions next to the object code saying where to find the
324
+ Corresponding Source. Regardless of what server hosts the
325
+ Corresponding Source, you remain obligated to ensure that it is
326
+ available for as long as needed to satisfy these requirements.
327
+
328
+ e) Convey the object code using peer-to-peer transmission, provided
329
+ you inform other peers where the object code and Corresponding
330
+ Source of the work are being offered to the general public at no
331
+ charge under subsection 6d.
332
+
333
+ A separable portion of the object code, whose source code is excluded
334
+ from the Corresponding Source as a System Library, need not be
335
+ included in conveying the object code work.
336
+
337
+ A "User Product" is either (1) a "consumer product", which means any
338
+ tangible personal property which is normally used for personal, family,
339
+ or household purposes, or (2) anything designed or sold for incorporation
340
+ into a dwelling. In determining whether a product is a consumer product,
341
+ doubtful cases shall be resolved in favor of coverage. For a particular
342
+ product received by a particular user, "normally used" refers to a
343
+ typical or common use of that class of product, regardless of the status
344
+ of the particular user or of the way in which the particular user
345
+ actually uses, or expects or is expected to use, the product. A product
346
+ is a consumer product regardless of whether the product has substantial
347
+ commercial, industrial or non-consumer uses, unless such uses represent
348
+ the only significant mode of use of the product.
349
+
350
+ "Installation Information" for a User Product means any methods,
351
+ procedures, authorization keys, or other information required to install
352
+ and execute modified versions of a covered work in that User Product from
353
+ a modified version of its Corresponding Source. The information must
354
+ suffice to ensure that the continued functioning of the modified object
355
+ code is in no case prevented or interfered with solely because
356
+ modification has been made.
357
+
358
+ If you convey an object code work under this section in, or with, or
359
+ specifically for use in, a User Product, and the conveying occurs as
360
+ part of a transaction in which the right of possession and use of the
361
+ User Product is transferred to the recipient in perpetuity or for a
362
+ fixed term (regardless of how the transaction is characterized), the
363
+ Corresponding Source conveyed under this section must be accompanied
364
+ by the Installation Information. But this requirement does not apply
365
+ if neither you nor any third party retains the ability to install
366
+ modified object code on the User Product (for example, the work has
367
+ been installed in ROM).
368
+
369
+ The requirement to provide Installation Information does not include a
370
+ requirement to continue to provide support service, warranty, or updates
371
+ for a work that has been modified or installed by the recipient, or for
372
+ the User Product in which it has been modified or installed. Access to a
373
+ network may be denied when the modification itself materially and
374
+ adversely affects the operation of the network or violates the rules and
375
+ protocols for communication across the network.
376
+
377
+ Corresponding Source conveyed, and Installation Information provided,
378
+ in accord with this section must be in a format that is publicly
379
+ documented (and with an implementation available to the public in
380
+ source code form), and must require no special password or key for
381
+ unpacking, reading or copying.
382
+
383
+ 7. Additional Terms.
384
+
385
+ "Additional permissions" are terms that supplement the terms of this
386
+ License by making exceptions from one or more of its conditions.
387
+ Additional permissions that are applicable to the entire Program shall
388
+ be treated as though they were included in this License, to the extent
389
+ that they are valid under applicable law. If additional permissions
390
+ apply only to part of the Program, that part may be used separately
391
+ under those permissions, but the entire Program remains governed by
392
+ this License without regard to the additional permissions.
393
+
394
+ When you convey a copy of a covered work, you may at your option
395
+ remove any additional permissions from that copy, or from any part of
396
+ it. (Additional permissions may be written to require their own
397
+ removal in certain cases when you modify the work.) You may place
398
+ additional permissions on material, added by you to a covered work,
399
+ for which you have or can give appropriate copyright permission.
400
+
401
+ Notwithstanding any other provision of this License, for material you
402
+ add to a covered work, you may (if authorized by the copyright holders of
403
+ that material) supplement the terms of this License with terms:
404
+
405
+ a) Disclaiming warranty or limiting liability differently from the
406
+ terms of sections 15 and 16 of this License; or
407
+
408
+ b) Requiring preservation of specified reasonable legal notices or
409
+ author attributions in that material or in the Appropriate Legal
410
+ Notices displayed by works containing it; or
411
+
412
+ c) Prohibiting misrepresentation of the origin of that material, or
413
+ requiring that modified versions of such material be marked in
414
+ reasonable ways as different from the original version; or
415
+
416
+ d) Limiting the use for publicity purposes of names of licensors or
417
+ authors of the material; or
418
+
419
+ e) Declining to grant rights under trademark law for use of some
420
+ trade names, trademarks, or service marks; or
421
+
422
+ f) Requiring indemnification of licensors and authors of that
423
+ material by anyone who conveys the material (or modified versions of
424
+ it) with contractual assumptions of liability to the recipient, for
425
+ any liability that these contractual assumptions directly impose on
426
+ those licensors and authors.
427
+
428
+ All other non-permissive additional terms are considered "further
429
+ restrictions" within the meaning of section 10. If the Program as you
430
+ received it, or any part of it, contains a notice stating that it is
431
+ governed by this License along with a term that is a further
432
+ restriction, you may remove that term. If a license document contains
433
+ a further restriction but permits relicensing or conveying under this
434
+ License, you may add to a covered work material governed by the terms
435
+ of that license document, provided that the further restriction does
436
+ not survive such relicensing or conveying.
437
+
438
+ If you add terms to a covered work in accord with this section, you
439
+ must place, in the relevant source files, a statement of the
440
+ additional terms that apply to those files, or a notice indicating
441
+ where to find the applicable terms.
442
+
443
+ Additional terms, permissive or non-permissive, may be stated in the
444
+ form of a separately written license, or stated as exceptions;
445
+ the above requirements apply either way.
446
+
447
+ 8. Termination.
448
+
449
+ You may not propagate or modify a covered work except as expressly
450
+ provided under this License. Any attempt otherwise to propagate or
451
+ modify it is void, and will automatically terminate your rights under
452
+ this License (including any patent licenses granted under the third
453
+ paragraph of section 11).
454
+
455
+ However, if you cease all violation of this License, then your
456
+ license from a particular copyright holder is reinstated (a)
457
+ provisionally, unless and until the copyright holder explicitly and
458
+ finally terminates your license, and (b) permanently, if the copyright
459
+ holder fails to notify you of the violation by some reasonable means
460
+ prior to 60 days after the cessation.
461
+
462
+ Moreover, your license from a particular copyright holder is
463
+ reinstated permanently if the copyright holder notifies you of the
464
+ violation by some reasonable means, this is the first time you have
465
+ received notice of violation of this License (for any work) from that
466
+ copyright holder, and you cure the violation prior to 30 days after
467
+ your receipt of the notice.
468
+
469
+ Termination of your rights under this section does not terminate the
470
+ licenses of parties who have received copies or rights from you under
471
+ this License. If your rights have been terminated and not permanently
472
+ reinstated, you do not qualify to receive new licenses for the same
473
+ material under section 10.
474
+
475
+ 9. Acceptance Not Required for Having Copies.
476
+
477
+ You are not required to accept this License in order to receive or
478
+ run a copy of the Program. Ancillary propagation of a covered work
479
+ occurring solely as a consequence of using peer-to-peer transmission
480
+ to receive a copy likewise does not require acceptance. However,
481
+ nothing other than this License grants you permission to propagate or
482
+ modify any covered work. These actions infringe copyright if you do
483
+ not accept this License. Therefore, by modifying or propagating a
484
+ covered work, you indicate your acceptance of this License to do so.
485
+
486
+ 10. Automatic Licensing of Downstream Recipients.
487
+
488
+ Each time you convey a covered work, the recipient automatically
489
+ receives a license from the original licensors, to run, modify and
490
+ propagate that work, subject to this License. You are not responsible
491
+ for enforcing compliance by third parties with this License.
492
+
493
+ An "entity transaction" is a transaction transferring control of an
494
+ organization, or substantially all assets of one, or subdividing an
495
+ organization, or merging organizations. If propagation of a covered
496
+ work results from an entity transaction, each party to that
497
+ transaction who receives a copy of the work also receives whatever
498
+ licenses to the work the party's predecessor in interest had or could
499
+ give under the previous paragraph, plus a right to possession of the
500
+ Corresponding Source of the work from the predecessor in interest, if
501
+ the predecessor has it or can get it with reasonable efforts.
502
+
503
+ You may not impose any further restrictions on the exercise of the
504
+ rights granted or affirmed under this License. For example, you may
505
+ not impose a license fee, royalty, or other charge for exercise of
506
+ rights granted under this License, and you may not initiate litigation
507
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
508
+ any patent claim is infringed by making, using, selling, offering for
509
+ sale, or importing the Program or any portion of it.
510
+
511
+ 11. Patents.
512
+
513
+ A "contributor" is a copyright holder who authorizes use under this
514
+ License of the Program or a work on which the Program is based. The
515
+ work thus licensed is called the contributor's "contributor version".
516
+
517
+ A contributor's "essential patent claims" are all patent claims
518
+ owned or controlled by the contributor, whether already acquired or
519
+ hereafter acquired, that would be infringed by some manner, permitted
520
+ by this License, of making, using, or selling its contributor version,
521
+ but do not include claims that would be infringed only as a
522
+ consequence of further modification of the contributor version. For
523
+ purposes of this definition, "control" includes the right to grant
524
+ patent sublicenses in a manner consistent with the requirements of
525
+ this License.
526
+
527
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
528
+ patent license under the contributor's essential patent claims, to
529
+ make, use, sell, offer for sale, import and otherwise run, modify and
530
+ propagate the contents of its contributor version.
531
+
532
+ In the following three paragraphs, a "patent license" is any express
533
+ agreement or commitment, however denominated, not to enforce a patent
534
+ (such as an express permission to practice a patent or covenant not to
535
+ sue for patent infringement). To "grant" such a patent license to a
536
+ party means to make such an agreement or commitment not to enforce a
537
+ patent against the party.
538
+
539
+ If you convey a covered work, knowingly relying on a patent license,
540
+ and the Corresponding Source of the work is not available for anyone
541
+ to copy, free of charge and under the terms of this License, through a
542
+ publicly available network server or other readily accessible means,
543
+ then you must either (1) cause the Corresponding Source to be so
544
+ available, or (2) arrange to deprive yourself of the benefit of the
545
+ patent license for this particular work, or (3) arrange, in a manner
546
+ consistent with the requirements of this License, to extend the patent
547
+ license to downstream recipients. "Knowingly relying" means you have
548
+ actual knowledge that, but for the patent license, your conveying the
549
+ covered work in a country, or your recipient's use of the covered work
550
+ in a country, would infringe one or more identifiable patents in that
551
+ country that you have reason to believe are valid.
552
+
553
+ If, pursuant to or in connection with a single transaction or
554
+ arrangement, you convey, or propagate by procuring conveyance of, a
555
+ covered work, and grant a patent license to some of the parties
556
+ receiving the covered work authorizing them to use, propagate, modify
557
+ or convey a specific copy of the covered work, then the patent license
558
+ you grant is automatically extended to all recipients of the covered
559
+ work and works based on it.
560
+
561
+ A patent license is "discriminatory" if it does not include within
562
+ the scope of its coverage, prohibits the exercise of, or is
563
+ conditioned on the non-exercise of one or more of the rights that are
564
+ specifically granted under this License. You may not convey a covered
565
+ work if you are a party to an arrangement with a third party that is
566
+ in the business of distributing software, under which you make payment
567
+ to the third party based on the extent of your activity of conveying
568
+ the work, and under which the third party grants, to any of the
569
+ parties who would receive the covered work from you, a discriminatory
570
+ patent license (a) in connection with copies of the covered work
571
+ conveyed by you (or copies made from those copies), or (b) primarily
572
+ for and in connection with specific products or compilations that
573
+ contain the covered work, unless you entered into that arrangement,
574
+ or that patent license was granted, prior to 28 March 2007.
575
+
576
+ Nothing in this License shall be construed as excluding or limiting
577
+ any implied license or other defenses to infringement that may
578
+ otherwise be available to you under applicable patent law.
579
+
580
+ 12. No Surrender of Others' Freedom.
581
+
582
+ If conditions are imposed on you (whether by court order, agreement or
583
+ otherwise) that contradict the conditions of this License, they do not
584
+ excuse you from the conditions of this License. If you cannot convey a
585
+ covered work so as to satisfy simultaneously your obligations under this
586
+ License and any other pertinent obligations, then as a consequence you may
587
+ not convey it at all. For example, if you agree to terms that obligate you
588
+ to collect a royalty for further conveying from those to whom you convey
589
+ the Program, the only way you could satisfy both those terms and this
590
+ License would be to refrain entirely from conveying the Program.
591
+
592
+ 13. Use with the GNU Affero General Public License.
593
+
594
+ Notwithstanding any other provision of this License, you have
595
+ permission to link or combine any covered work with a work licensed
596
+ under version 3 of the GNU Affero General Public License into a single
597
+ combined work, and to convey the resulting work. The terms of this
598
+ License will continue to apply to the part which is the covered work,
599
+ but the special requirements of the GNU Affero General Public License,
600
+ section 13, concerning interaction through a network will apply to the
601
+ combination as such.
602
+
603
+ 14. Revised Versions of this License.
604
+
605
+ The Free Software Foundation may publish revised and/or new versions of
606
+ the GNU General Public License from time to time. Such new versions will
607
+ be similar in spirit to the present version, but may differ in detail to
608
+ address new problems or concerns.
609
+
610
+ Each version is given a distinguishing version number. If the
611
+ Program specifies that a certain numbered version of the GNU General
612
+ Public License "or any later version" applies to it, you have the
613
+ option of following the terms and conditions either of that numbered
614
+ version or of any later version published by the Free Software
615
+ Foundation. If the Program does not specify a version number of the
616
+ GNU General Public License, you may choose any version ever published
617
+ by the Free Software Foundation.
618
+
619
+ If the Program specifies that a proxy can decide which future
620
+ versions of the GNU General Public License can be used, that proxy's
621
+ public statement of acceptance of a version permanently authorizes you
622
+ to choose that version for the Program.
623
+
624
+ Later license versions may give you additional or different
625
+ permissions. However, no additional obligations are imposed on any
626
+ author or copyright holder as a result of your choosing to follow a
627
+ later version.
628
+
629
+ 15. Disclaimer of Warranty.
630
+
631
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
632
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
633
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
634
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
635
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
636
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
637
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
638
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
639
+
640
+ 16. Limitation of Liability.
641
+
642
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
643
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
644
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
645
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
646
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
647
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
648
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
649
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
650
+ SUCH DAMAGES.
651
+
652
+ 17. Interpretation of Sections 15 and 16.
653
+
654
+ If the disclaimer of warranty and limitation of liability provided
655
+ above cannot be given local legal effect according to their terms,
656
+ reviewing courts shall apply local law that most closely approximates
657
+ an absolute waiver of all civil liability in connection with the
658
+ Program, unless a warranty or assumption of liability accompanies a
659
+ copy of the Program in return for a fee.
660
+
lib/lessphp/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # lessphp v0.3.3
2
+ ### <http://leafo.net/lessphp>
3
+
4
+ `lessphp` is a compiler for LESS written in PHP. The documentation is great,
5
+ so check it out: <http://leafo.net/lessphp/docs/>.
6
+
7
+ Here's a quick tutorial:
8
+
9
+ ### How to use in your PHP project
10
+
11
+ Copy `lessc.inc.php` to your include directory and include it into your project.
12
+
13
+ There are a few ways to interface with the compiler. The easiest is to have it
14
+ compile a LESS file when the page is requested. The static function
15
+ `lessc::ccompile`, checked compile, will compile the input LESS file only when it
16
+ is newer than the output file.
17
+
18
+ try {
19
+ lessc::ccompile('input.less', 'output.css');
20
+ } catch (exception $ex) {
21
+ exit($ex->getMessage());
22
+ }
23
+
24
+ `lessc::ccompile` is not aware of imported files that change. Read [about
25
+ `lessc::cexecute`](http://leafo.net/lessphp/docs/#compiling_automatically).
26
+
27
+ Note that all failures with lessc are reported through exceptions.
28
+ If you need more control you can make your own instance of lessc.
29
+
30
+ $input = 'mystyle.less';
31
+
32
+ $lc = new lessc($input);
33
+
34
+ try {
35
+ file_put_contents('mystyle.css', $lc->parse());
36
+ } catch (exception $ex) { ... }
37
+
38
+ In addition to loading from file, you can also parse from a string like so:
39
+
40
+ $lc = new lessc();
41
+ $lesscode = 'body { ... }';
42
+ $out = $lc->parse($lesscode);
43
+
44
+ ### How to use from the command line
45
+
46
+ An additional script has been included to use the compiler from the command
47
+ line. In the simplest invocation, you specify an input file and the compiled
48
+ css is written to standard out:
49
+
50
+ $ plessc input.less > output.css
51
+
52
+ Using the -r flag, you can specify LESS code directly as an argument or, if
53
+ the argument is left off, from standard in:
54
+
55
+ $ plessc -r "my less code here"
56
+
57
+ Finally, by using the -w flag you can watch a specified input file and have it
58
+ compile as needed to the output file
59
+
60
+ $ plessc -w input-file output-file
61
+
62
+ Errors from watch mode are written to standard out.
63
+
64
+
lib/lessphp/docs/docs.md ADDED
@@ -0,0 +1,992 @@
1
+ title: v0.3.3 documentation
2
+ link_to_home: true
3
+ --
4
+
5
+ <h2 skip="true">Documentation v0.3.3</h2>
6
+
7
+ <div style="margin-bottom: 1em;">$index</div>
8
+
9
+ **lessphp** is a compiler that generates CSS from a superset language which
10
+ adds a collection of convenient features often seen in other languages. All CSS
11
+ is compatible with LESS, so you can start using new features with your existing CSS.
12
+
13
+ It is designed to be compatible with [less.js](http://lesscss.org), and suitable
14
+ as a drop in replacement for PHP projects.
15
+
16
+ ## Getting Started
17
+
18
+ The homepage for **lessphp** can be found at [http://leafo.net/lessphp/][1].
19
+
20
+ You can follow development at the project's [GitHub][2].
21
+
22
+ Including **lessphp** in your project is as simple as dropping the single
23
+ include file into your code base and running the appropriate compile method as
24
+ described in the [PHP Interface](#php_interface).
25
+
26
+ [1]: http://leafo.net/lessphp "lessphp homepage"
27
+ [2]: https://github.com/leafo/lessphp "lessphp GitHub page"
28
+
29
+ ## Installation
30
+
31
+ **lessphp** is distributed entirely in a single stand-alone file. Download the
32
+ latest version from either [the homepage][1] or [GitHub][2].
33
+
34
+ Development versions can also be downloading from GitHub.
35
+
36
+ Place `lessphp.inc.php` in a location available to your PHP scripts, and
37
+ include it. That's it! you're ready to begin.
38
+
39
+ ## The Language
40
+
41
+ **lessphp** is very easy to learn because it generally functions how you would
42
+ expect it to. If you feel something is challenging or missing, feel free to
43
+ open an issue on the [bug tracker](https://github.com/leafo/lessphp/issues).
44
+
45
+ It is also easy to learn because any standards-compliant CSS code is valid LESS
46
+ code. You are free to gradually enhance your existing CSS code base with LESS
47
+ features without having to worry about rewriting anything.
48
+
49
+ The following is a description of the new languages features provided by LESS.
50
+
51
+ ### Line Comments
52
+
53
+ Simple but very useful; line comments are started with `//`:
54
+
55
+ ```less
56
+ // this is a comment
57
+ body {
58
+ color: red; // as is this
59
+ /* block comments still work also */
60
+ }
61
+ ```
62
+
63
+ ### Variables
64
+ Variables are identified with a name that starts with `@`. To declare a
65
+ variable, you create an appropriately named CSS property and assign it a value:
66
+
67
+ ```less
68
+ @family: "verdana";
69
+ @color: red;
70
+ body {
71
+ @mycolor: red;
72
+ font-family: @family;
73
+ color: @color;
74
+ border-bottom: 1px solid @color;
75
+ }
76
+ ```
77
+
78
+ Variable declarations will not appear in the output. Variables can be declared
79
+ in the outer most scope of the file, or anywhere else a CSS property may
80
+ appear. They can hold any CSS property value.
81
+
82
+ Variables are only visible for use from their current scope, or any enclosed
83
+ scopes.
84
+
85
+ If you have a string or keyword in a variable, you can reference another
86
+ variable by that name by repeating the `@`:
87
+
88
+ ```less
89
+ @value: 20px;
90
+ @value_name: "value";
91
+
92
+ width: @@value_name;
93
+ ```
94
+
95
+ ### Expressions
96
+
97
+ Expressions let you combine values and variables in meaningful ways. For
98
+ example you can add to a color to make it a different shade. Or divide up the
99
+ width of your layout logically. You can even concatenate strings.
100
+
101
+ Use the mathematical operators to evaluate an expression:
102
+
103
+ ```less
104
+ @width: 960px;
105
+ .nav {
106
+ width: @width / 3;
107
+ color: #001 + #abc;
108
+ }
109
+ .body {
110
+ width: 2 * @width / 3;
111
+ font-family: "hel" + "vetica";
112
+ }
113
+ ```
114
+
115
+ Parentheses can be used to control the order of evaluation. They can also be
116
+ used to force an evaluation for cases where CSS's syntax makes the expression
117
+ ambiguous.
118
+
119
+ The following property will produce two numbers, instead of doing the
120
+ subtraction:
121
+
122
+ ```less
123
+ margin: 10px -5px;
124
+ ```
125
+
126
+ To force the subtraction:
127
+
128
+ ```less
129
+ margin: (10px -5px);
130
+ ```
131
+
132
+ It is also safe to surround mathematical operators by spaces to ensure that
133
+ they are evaluated:
134
+
135
+ ```less
136
+ margin: 10px - 5px;
137
+ ```
138
+
139
+ Division has a special quirk. There are certain CSS properties that use the `/`
140
+ operator as part of their value's syntax. Namely, the [font][4] shorthand and
141
+ [border-radius][3].
142
+
143
+ [3]: https://developer.mozilla.org/en/CSS/border-radius
144
+ [4]: https://developer.mozilla.org/en/CSS/font
145
+
146
+
147
+ Thus, **lessphp** will ignore any division in these properties unless it is
148
+ wrapped in parentheses. For example, no division will take place here:
149
+
150
+ ```less
151
+ .font {
152
+ font: 20px/80px "Times New Roman";
153
+ }
154
+ ```
155
+
156
+ In order to force division we must wrap the expression in parentheses:
157
+
158
+ ```less
159
+ .font {
160
+ font: (20px/80px) "Times New Roman";
161
+ }
162
+ ```
163
+
164
+ If you want to write a literal `/` expression without dividing in another
165
+ property (or a variable), you can use [string unquoting](#string_unquoting):
166
+
167
+ ```less
168
+ .var {
169
+ @size: ~"20px/80px";
170
+ font: @size sans-serif;
171
+ }
172
+ ```
173
+
174
+ ### Nested Blocks
175
+
176
+ By nesting blocks we can build up a chain of CSS selectors through scope
177
+ instead of repeating them. In addition to reducing repetition, this also helps
178
+ logically organize the structure of our CSS.
179
+
180
+ ```less
181
+ ol.list {
182
+ li.special {
183
+ border: 1px solid red;
184
+ }
185
+
186
+ li.plain {
187
+ font-weight: bold;
188
+ }
189
+ }
190
+ ```
191
+
192
+
193
+ This will produce two blocks, a `ol.list li.special` and `ol.list li.plain`.
194
+
195
+ Blocks can be nested as deep as required in order to build a hierarchy of
196
+ relationships.
197
+
198
+ The `&` operator can be used in a selector to represent its parent's selector.
199
+ If the `&` operator is used, then the default action of appending the parent to
200
+ the front of the child selector separated by space is not performed.
201
+
202
+ ```less
203
+ b {
204
+ a & {
205
+ color: red;
206
+ }
207
+
208
+ // the following have the same effect
209
+
210
+ & i {
211
+ color: blue;
212
+ }
213
+
214
+ i {
215
+ color: blue;
216
+ }
217
+ }
218
+ ```
219
+
220
+
221
+ Because the `&` operator respects the whitespace around it, we can use it to
222
+ control how the child blocks are joined. Consider the differences between the
223
+ following:
224
+
225
+ ```less
226
+ div {
227
+ .child-class { color: purple; }
228
+
229
+ &.isa-class { color: green; }
230
+
231
+ #child-id { height: 200px; }
232
+
233
+ &#div-id { height: 400px; }
234
+
235
+ &:hover { color: red; }
236
+
237
+ :link { color: blue; }
238
+ }
239
+ ```
240
+
241
+ The `&` operator also works with [mixins](#mixins), which produces interesting results:
242
+
243
+ ```less
244
+ .within_box_style() {
245
+ .box & {
246
+ color: blue;
247
+ }
248
+ }
249
+
250
+ #menu {
251
+ .within_box_style;
252
+ }
253
+ ```
254
+
255
+ ### Mixins
256
+
257
+ Any block can be mixed in just by naming it:
258
+
259
+ ```less
260
+ .mymixin {
261
+ color: blue;
262
+ border: 1px solid red;
263
+
264
+ .special {
265
+ font-weight: bold;
266
+ }
267
+ }
268
+
269
+
270
+ h1 {
271
+ font-size: 200px;
272
+ .mixin;
273
+ }
274
+ ```
275
+
276
+ All properties and child blocks are mixed in.
277
+
278
+ Mixins can be made parametric, meaning they can take arguments, in order to
279
+ enhance their utility. A parametric mixin all by itself is not outputted when
280
+ compiled. Its properties will only appear when mixed into another block.
281
+
282
+ The canonical example is to create a rounded corners mixin that works across
283
+ browsers:
284
+
285
+ ```less
286
+ .rounded-corners(@radius: 5px) {
287
+ border-radius: @radius;
288
+ -webkit-border-radius: @radius;
289
+ -moz-border-radius: @radius;
290
+ }
291
+
292
+ .header {
293
+ .rounded-corners();
294
+ }
295
+
296
+ .info {
297
+ background: red;
298
+ .rounded-corners(14px);
299
+ }
300
+ ```
301
+
302
+ If you have a mixin that doesn't have any arguments, but you don't want it to
303
+ show up in the output, give it a blank argument list:
304
+
305
+ ```less
306
+ .secret() {
307
+ font-size: 6000px;
308
+ }
309
+
310
+ .div {
311
+ .secret;
312
+ }
313
+ ```
314
+
315
+ If the mixin doesn't need any arguments, you can leave off the parentheses when
316
+ mixing it in, as seen above.
317
+
318
+ You can also mixin a block that is nested inside other blocks. You can think of
319
+ the outer block as a way of making a scope for your mixins. You just list the
320
+ names of the mixins separated by spaces, which describes the path to the mixin
321
+ you want to include. Optionally you can separate them by `>`.
322
+
323
+ ```less
324
+ .my_scope {
325
+ .some_color {
326
+ color: red;
327
+ .inner_block {
328
+ text-decoration: underline;
329
+ }
330
+ }
331
+ .bold {
332
+ font-weight: bold;
333
+ color: blue;
334
+ }
335
+ }
336
+
337
+ .a_block {
338
+ .my_scope .some_color;
339
+ .my_scope .some_color .inner_block;
340
+ }
341
+
342
+ .another_block {
343
+ // the alternative syntax
344
+ .my_scope > .bold;
345
+ }
346
+ ```
347
+
348
+ #### `@arguments` Variable
349
+
350
+ Within an mixin there is a special variable named `@arguments` that contains
351
+ all the arguments passed to the mixin along with any remaining arguments that
352
+ have default values. The value of the variable has all the values separated by
353
+ spaces.
354
+
355
+ This useful for quickly assigning all the arguments:
356
+
357
+ ```less
358
+ .box-shadow(@x, @y, @blur, @color) {
359
+ box-shadow: @arguments;
360
+ -webkit-box-shadow: @arguments;
361
+ -moz-box-shadow: @arguments;
362
+ }
363
+ .menu {
364
+ .box-shadow(1px, 1px, 5px, #aaa);
365
+ }
366
+ ```
367
+
368
+ In addition to the arguments passed to the mixin, `@arguments` will also include
369
+ remaining default values assigned by the mixin:
370
+
371
+
372
+ ```less
373
+ .border-mixin(@width, @style: solid, @color: black) {
374
+ border: @arguments;
375
+ }
376
+
377
+ pre {
378
+ .border-mixin(4px, dotted);
379
+ }
380
+
381
+ ```
382
+
383
+
384
+ #### Pattern Matching
385
+
386
+ When you *mix in* a mixin, all the available mixins of that name in the current
387
+ scope are checked to see if they match based on what was passed to the mixin
388
+ and how it was declared.
389
+
390
+ The simplest case is matching by number of arguments. Only the mixins that
391
+ match the number of arguments passed in are used, with the exception of 0
392
+ argument mixins, which are always included.
393
+
394
+ ```less
395
+ .simple() { // no argument mixin always included
396
+ height: 10px;
397
+ }
398
+
399
+ .simple(@a, @b) {
400
+ color: red;
401
+ }
402
+
403
+ .simple(@a) {
404
+ color: blue;
405
+ }
406
+
407
+ div {
408
+ .simple(10);
409
+ }
410
+
411
+ span {
412
+ .simple(10, 20);
413
+ }
414
+ ```
415
+
416
+ Another way of controlling whether a mixin matches is by specifying a value in
417
+ place of an argument name when declaring the mixin:
418
+
419
+ ```less
420
+ .style(old, @size) {
421
+ font: @size serif;
422
+ }
423
+
424
+ .style(new, @size) {
425
+ font: @size sans-serif;
426
+ }
427
+
428
+ .style(@_, @size) {
429
+ letter-spacing: floor(@size / 6px);
430
+ }
431
+
432
+ em {
433
+ @switch: old;
434
+ .style(@switch, 15px);
435
+ }
436
+ ```
437
+
438
+ Notice that two of the three mixins were matched. The mixin with a matching
439
+ first argument, and the generic mixin that matches two arguments. It's common
440
+ to use `@_` as the name of a variable we intend to not use. It has no special
441
+ meaning to LESS, just to the reader of the code.
442
+
443
+ #### Guards
444
+
445
+ Another way of restricting when a mixin is mixed in is by using guards. A guard
446
+ is a special expression that is associated with a mixin declaration that is
447
+ evaluated during the mixin process. It must evaluate to true before the mixin
448
+ can be used.
449
+
450
+ We use the `when` keyword to begin describing a list of guard expressions.
451
+
452
+ Here's a simple example:
453
+
454
+ ```less
455
+ .guarded(@arg) when (@arg = hello) {
456
+ color: blue;
457
+ }
458
+
459
+ div {
460
+ .guarded(hello); // match
461
+ }
462
+
463
+ span {
464
+ .guarded(world); // no match
465
+ }
466
+ ```
467
+ Only the `div`'s mixin will match in this case, because the guard expression
468
+ requires that `@arg` is equal to `hello`.
469
+
470
+ We can include many different guard expressions by separating them by commas.
471
+ Only one of them needs to match to trigger the mixin:
472
+
473
+ ```less
474
+ .x(@a, @b) when (@a = hello), (@b = world) {
475
+ width: 960px;
476
+ }
477
+
478
+ div {
479
+ .x(hello, bar); // match
480
+ }
481
+
482
+ span {
483
+ .x(foo, world); // match
484
+ }
485
+
486
+ pre {
487
+ .x(foo, bar); // no match
488
+ }
489
+ ```
490
+
491
+ Instead of a comma, we can use `and` keyword to make it so all of the guards
492
+ must match in order to trigger the mixin. `and` has higher precedence than the
493
+ comma.
494
+
495
+ ```less
496
+ .y(@a, @b) when (@a = hello) and (@b = world) {
497
+ height: 600px;
498
+ }
499
+
500
+ div {
501
+ .y(hello, world); // match
502
+ }
503
+
504
+ span {
505
+ .y(hello, bar); // no match
506
+ }
507
+ ```
508
+
509
+ Commas and `and`s can be mixed and matched.
510
+
511
+ You can also negate a guard expression by using `not` in from of the parentheses:
512
+
513
+ ```less
514
+ .x(@a) when not (@a = hello) {
515
+ color: blue;
516
+ }
517
+
518
+ div {
519
+ .x(hello); // no match
520
+ }
521
+ ```
522
+
523
+ The `=` operator is used to check equality between any two values. For numbers
524
+ the following comparison operators are also defined:
525
+
526
+ `<`, `>`, `=<`, `>=`
527
+
528
+ There is also a collection of predicate functions that can be used to test the
529
+ type of a value.
530
+
531
+ These are `isnumber`, `iscolor`, `iskeyword`, `isstring`, `ispixel`,
532
+ `ispercentage` and `isem`.
533
+
534
+ ```less
535
+ .mix(@a) when (ispercentage(@a)) {
536
+ height: 500px * @a;
537
+ }
538
+ .mix(@a) when (ispixel(@a)) {
539
+ height: @a;
540
+ }
541
+
542
+ div.a {
543
+ .mix(50%);
544
+ }
545
+
546
+ div.a {
547
+ .mix(350px);
548
+ }
549
+ ```
550
+
551
+ ### Import
552
+
553
+ Multiple LESS files can be compiled into a single CSS file by using the
554
+ `@import` statement. Be careful, the LESS import statement shares syntax with
555
+ the CSS import statement. If the file being imported ends in a `.less`
556
+ extension, or no extension, then it is treated as a LESS import. Otherwise it
557
+ is left alone and outputted directly:
558
+
559
+ ```less
560
+ // my_file.less
561
+ .some-mixin(@height) {
562
+ height: @height;
563
+ }
564
+
565
+ // main.less
566
+ @import "main.less" // will import the file if it can be found
567
+ @import "main.css" // will be left alone
568
+
569
+ body {
570
+ .some-mixin(400px);
571
+ }
572
+ ```
573
+
574
+ All of the following lines are valid ways to import the same file:
575
+
576
+ ```less
577
+ @import "file";
578
+ @import 'file.less';
579
+ @import url("file");
580
+ @import url('file');
581
+ @import url(file);
582
+ ```
583
+
584
+ When importing, the `importDir` is searched for files. This can be configured,
585
+ see [PHP Interface](#php_interface).
586
+
587
+ ### String Interpolation
588
+
589
+ String interpolation is a convenient way to insert the value of a variable
590
+ right into a string literal. Given some variable named `@var_name`, you just
591
+ need to write it as `@{var_name}` from within the string to have its value
592
+ inserted:
593
+
594
+ ```less
595
+ @symbol: ">";
596
+ h1:before {
597
+ content: "@{symbol}: ";
598
+ }
599
+
600
+ h2:before {
601
+ content: "@{symbol}@{symbol}: ";
602
+ }
603
+ ```
604
+
605
+ There are two kinds of strings, implicit and explicit strings. Explicit strings
606
+ are wrapped by double quotes, `"hello I am a string"`, or single quotes `'I am
607
+ another string'`. Implicit strings only appear when using `url()`. The text
608
+ between the parentheses is considered a string and thus string interpolation is
609
+ possible:
610
+
611
+ ```less
612
+ @path: "files/";
613
+ body {
614
+ background: url(@{path}my_background.png);
615
+ }
616
+ ```
617
+
618
+ ### String Format Function
619
+
620
+ The `%` function can be used to insert values into strings using a *format
621
+ string*. It works similar to `printf` seen in other languages. It has the
622
+ same purpose as string interpolation above, but gives explicit control over
623
+ the output format.
624
+
625
+ ```less
626
+ @symbol: ">";
627
+ h1:before {
628
+ content: %("%s: ", @symbol);
629
+ }
630
+ ```
631
+
632
+ The `%` function takes as its first argument the format string, following any
633
+ number of addition arguments that are inserted in place of the format
634
+ directives.
635
+
636
+ A format directive starts with a `%` and is followed by a single character that
637
+ is either `a`, `d`, or `s`:
638
+
639
+ ```less
640
+ strings: %("%a %d %s %a", hi, 1, 'ok', 'cool');
641
+ ```
642
+
643
+ `%a` and `%d` format the value the same way: they compile the argument to its
644
+ CSS value and insert it directly. When used with a string, the quotes are
645
+ included in the output. This typically isn't what we want, so we have the `%s`
646
+ format directive which strips quotes from strings before inserting them.
647
+
648
+ The `%d` directive functions the same as `%a`, but is typically used for numbers
649
+ assuming the output format of numbers might change in the future.
650
+
651
+ ### String Unquoting
652
+
653
+ Sometimes you will need to write proprietary CSS syntax that is unable to be
654
+ parsed. As a workaround you can place the code into a string and unquote it.
655
+ Unquoting is the process of outputting a string without its surrounding quotes.
656
+ There are two ways to unquote a string.
657
+
658
+ The `~` operator in front of a string will unquote that string:
659
+
660
+ ```less
661
+ .class {
662
+ // a made up, but problematic vendor specific CSS
663
+ filter: ~"Microsoft.AlphaImage(src='image.png')";
664
+ }
665
+ ```
666
+
667
+ If you are working with other types, such as variables, there is a built in
668
+ function that let's you unquote any value. It is called `e`.
669
+
670
+ ```less
671
+ @color: "red";
672
+ .class {
673
+ color: e(@color);
674
+ }
675
+ ```
676
+
677
+ ### Built In Functions
678
+
679
+ **lessphp** has a collection of built in functions:
680
+
681
+ * `e(str)` -- returns a string without the surrounding quotes.
682
+ See [String Unquoting](#string_unquoting)
683
+
684
+ * `floor(number)` -- returns the floor of a numerical input
685
+ * `round(number)` -- returns the rounded value of numerical input
686
+
687
+ * `lighten(color, percent)` -- lightens `color` by `percent` and returns it
688
+ * `darken(color, percent)` -- darkens `color` by `percent` and returns it
689
+
690
+ * `saturate(color, percent)` -- saturates `color` by `percent` and returns it
691
+ * `desaturate(color, percent)` -- desaturates `color` by `percent` and returns it
692
+
693
+ * `fadein(color, percent)` -- makes `color` less transparent by `percent` and returns it
694
+ * `fadeout(color, percent)` -- makes `color` more transparent by `percent` and returns it
695
+
696
+ * `spin(color, amount)` -- returns a color with `amount` degrees added to hue
697
+
698
+ * `fade(color, amount)` -- returns a color with the alpha set to `amount`
699
+
700
+ * `hue(color)` -- returns the hue of `color`
701
+
702
+ * `saturation(color)` -- returns the saturation of `color`
703
+
704
+ * `lightness(color)` -- returns the lightness of `color`
705
+
706
+ * `alpha(color)` -- returns the alpha value of `color` or 1.0 if it doesn't have an alpha
707
+
708
+ * `percentage(number)` -- converts a floating point number to a percentage, e.g. `0.65` -> `65%`
709
+
710
+ * `mix(color1, color1, percent)` -- mixes two colors by percentage where 100%
711
+ keeps all of `color1`, and 0% keeps all of `color2`. Will take into account
712
+ the alpha of the colors if it exists. See
713
+ <http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method>.
714
+
715
+ * `rgbahex(color)` -- returns a string containing 4 part hex color.
716
+
717
+ This is used to convert a CSS color into the hex format that IE's filter
718
+ method expects when working with an alpha component.
719
+
720
+ ```less
721
+ .class {
722
+ @start: rgbahex(rgba(25, 34, 23, .5));
723
+ @end: rgbahex(rgba(85, 74, 103, .6));
724
+ // abridged example
725
+ -ms-filter:
726
+ e("gradient(start=@{start},end=@{end})");
727
+ }
728
+ ```
729
+
730
+ ## PHP Interface
731
+
732
+ The PHP interface lets you control the compiler from your PHP scripts. There is
733
+ only one file to include to get access to everything:
734
+
735
+ ```php
736
+ <?php
737
+ include "lessc.inc.php";
738
+ ```
739
+
740
+ To compile a file to a string (of CSS code):
741
+
742
+ ```php
743
+ $less = new lessc("myfile.less");
744
+ $css = $less->parse();
745
+ ```
746
+
747
+ To compile a string to a string:
748
+
749
+ ```php
750
+ $less = new lessc(); // a blank lessc
751
+ $css = $less->parse("body { a { color: red } }");
752
+ ```
753
+
754
+ ### Compiling Automatically
755
+
756
+ Often, you want to write the compiled CSS to a file, and only recompile when
757
+ the original LESS file has changed. The following function will check if the
758
+ modification date of the LESS file is more recent than the CSS file. The LESS
759
+ file will be compiled if it is. If the CSS file doesn't exist yet, then it will
760
+ also compile the LESS file.
761
+
762
+ ```php
763
+ lessc::ccompile('myfile.less', 'mystyle.css');
764
+ ```
765
+
766
+ `ccompile` is very basic, it only checks if the input file's modification time.
767
+ It is not of any files that are brought in using `@import`.
768
+
769
+ For this reason we also have `lessc::cexecute`. It functions slightly
770
+ differently, but gives us the ability to check changes to all files used during
771
+ the compile. It takes one argument, either the name of the file we want to
772
+ compile, or an existing *cache object*. Its return value is an updated cache
773
+ object.
774
+
775
+ If we don't have a cache object, then we call the function with the name of the
776
+ file to get the initial cache object. If we do have a cache object, then we
777
+ call the function with it. In both cases, an updated cache object is returned.
778
+
779
+ The cache object keeps track of all the files that must be checked in order to
780
+ determine if a rebuild is required.
781
+
782
+ The cache object is a plain PHP `array`. It stores the last time it compiled in
783
+ `$cache['updated']` and output of the compile in `$cache['compiled']`.
784
+
785
+ Here we demonstrate creating an new cache object, then using it to see if we
786
+ have a recompiled version available to be written:
787
+
788
+
789
+ ```php
790
+ $less_file = 'myfile.less';
791
+ $css_file = 'myfile.css';
792
+
793
+ // create a new cache object, and compile
794
+ $cache = lessc::cexecute('myfile.less');
795
+ file_put_contents($css_file, $cache['compiled']);
796
+
797
+ // the next time we run, write only if it has updated
798
+ $last_updated = $cache['updated'];
799
+ $cache = lessc::cexecute($cache);
800
+ if ($cache['updated'] > $last_updated) {
801
+ file_put_contents($css_file, $cache['compiled']);
802
+ }
803
+
804
+ ```
805
+
806
+ In order for the system to fully work, we must save cache object between
807
+ requests. Because it's a plain PHP `array`, it's sufficient to
808
+ [`serialize`](http://php.net/serialize) it and save it the string somewhere
809
+ like a file or in persistent memory.
810
+
811
+ An example with saving cache object to a file:
812
+
813
+ ```php
814
+ function auto_compile_less($less_fname, $css_fname) {
815
+ // load the cache
816
+ $cache_fname = $less_fname.".cache";
817
+ if (file_exists($cache_fname)) {
818
+ $cache = unserialize(file_get_contents($cache_fname));
819
+ } else {
820
+ $cache = $less_fname;
821
+ }
822
+
823
+ $new_cache = lessc::cexecute($cache);
824
+ if (!is_array($cache) || $new_cache['updated'] > $cache['updated']) {
825
+ file_put_contents($cache_fname, serialize($new_cache));
826
+ file_put_contents($css_fname, $new_cache['compiled']);
827
+ }
828
+ }
829
+
830
+ auto_compile_less('myfile.less', 'myfile.css');
831
+ ```
832
+
833
+ `lessc:cexecute` takes an optional second argument, `$force`. Passing in true
834
+ will cause the input to always be recompiled.
835
+
836
+ ### Error Handling
837
+
838
+ All of the following methods will throw an `Exception` if the parsing fails:
839
+
840
+ ```php
841
+ $less = new lessc();
842
+ try {
843
+ $less->parse("} invalid LESS }}}");
844
+ } catch (Exception $ex) {
845
+ echo "lessphp fatal error: ".$ex->getMessage();
846
+ }
847
+ ```
848
+ ### Setting Variables From PHP
849
+
850
+ The `parse` function takes a second optional argument. If you want to
851
+ initialize variables from outside the LESS file then you can pass in an
852
+ associative array of names and values. The values will parsed as CSS values:
853
+
854
+ ```php
855
+ $less = new lessc();
856
+ echo $less->parse(".magic { color: @color; width: @base - 200; }",
857
+ array(
858
+ 'color' => 'red';
859
+ 'base' => '960px';
860
+ ));
861
+ ```
862
+
863
+ You can also do this when loading from a file, but remember to set the first
864
+ argument of the parse function to `null`, otherwise it will try to compile that
865
+ instead of the file:
866
+
867
+ ```php
868
+ $less = new lessc("myfile.less");
869
+ echo $less->parse(null, array('color' => 'blue'));
870
+ ```
871
+
872
+ ### Custom Functions
873
+
874
+ **lessphp** has a simple extension interface where you can implement user
875
+ functions that will be exposed in LESS code during the compile. They can be a
876
+ little tricky though because you need to work with the **lessphp** type system.
877
+
878
+ An instance of `lessc`, the **lessphp** compiler has two relevant methods:
879
+ `registerFunction` and `unregisterFunction`. `registerFunction` takes two
880
+ arguments, a name and a callable value. `unregisterFunction` just takes the
881
+ name of an existing function to remove.
882
+
883
+ Here's an example that adds a function called `double` that doubles any numeric
884
+ argument:
885
+
886
+ ```php
887
+ <?php
888
+ include "lessc.inc.php";
889
+
890
+ function lessphp_double($arg) {
891
+ list($type, $value) = $arg;
892
+ return array($type, $value*2);
893
+ }
894
+
895
+ $myless = new myless();
896
+ $myless->registerFunction("double", "lessphp_double");
897
+
898
+ // gives us a width of 800px
899
+ echo $myless->parse("div { width: double(400px); }");
900
+ ```
901
+
902
+ The second argument to `registerFunction` is any *callable value* that is
903
+ understood by [`call_user_func`](http://php.net/call_user_func).
904
+
905
+ If we are using PHP 5.3 or above then we are free to pass a function literal
906
+ like so:
907
+
908
+ ```php
909
+ $myless->registerFunction("double", function($arg) {
910
+ list($type, $value) = $arg;
911
+ return array($type, $value*2);
912
+ });
913
+ ```
914
+
915
+ Now let's talk about the `double` function itself.
916
+
917
+ Although a little verbose, the implementation gives us some insight on the type
918
+ system. All values in **lessphp** are stored in an array where the 0th element
919
+ is a string representing the type, and the other elements make up the
920
+ associated data for that value.
921
+
922
+ The best way to get an understanding of the system is to register is dummy
923
+ function which does a `vardump` on the argument. Try passing the function
924
+ different values from LESS and see what the results are.
925
+
926
+ The return value of the registered function must also be a **lessphp** type, but if it is
927
+ a string or numeric value, it will automatically be coerced into an appropriate
928
+ typed value. In our example, we reconstruct the value with our modifications
929
+ while making sure that we preserve the original type.
930
+
931
+ In addition to the arguments passed from **lessphp**, the instance of
932
+ **lessphp** itself is sent to the registered function as the second argument.
933
+
934
+ ## Command Line Interface
935
+
936
+ **lessphp** comes with a command line script written in PHP that can be used to
937
+ invoke the compiler from the terminal. On Linux an OSX, all you need to do is
938
+ place `plessc` and `lessc.inc.php` somewhere in your PATH (or you can run it in
939
+ the current directory as well). On windows you'll need a copy of `php.exe` to
940
+ run the file. To compile a file, `input.less` to CSS, run:
941
+
942
+ ```bash
943
+ $ plessc input.less
944
+ ```
945
+
946
+ To write to a file, redirect standard out:
947
+
948
+ ```bash
949
+ $ plessc input.less > output.css
950
+ ```
951
+
952
+ To compile code directly on the command line:
953
+
954
+ ```bash
955
+ $ plessc -r "@color: red; body { color: @color; }"
956
+ ```
957
+
958
+ To watch a file for changes, and compile it as needed, use the `-w` flag:
959
+
960
+ ```bash
961
+ $ plessc -w input-file output-file
962
+ ```
963
+
964
+ Errors from watch mode are written to standard out.
965
+
966
+
967
+ ## License
968
+
969
+ Copyright (c) 2010 Leaf Corcoran, <http://leafo.net/lessphp>
970
+
971
+ Permission is hereby granted, free of charge, to any person obtaining
972
+ a copy of this software and associated documentation files (the
973
+ "Software"), to deal in the Software without restriction, including
974
+ without limitation the rights to use, copy, modify, merge, publish,
975
+ distribute, sublicense, and/or sell copies of the Software, and to
976
+ permit persons to whom the Software is furnished to do so, subject to
977
+ the following conditions:
978
+
979
+ The above copyright notice and this permission notice shall be
980
+ included in all copies or substantial portions of the Software.
981
+
982
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
983
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
984
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
985
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
986
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
987
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
988
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
989
+
990
+
991
+ *Also under GPL3 if required, see `LICENSE` file*
992
+
lib/lessphp/lessc.inc.php ADDED
@@ -0,0 +1,2622 @@