leafo / lessphp Goto Github PK
View Code? Open in Web Editor NEWLESS compiler written in PHP
Home Page: http://leafo.net/lessphp
License: Other
LESS compiler written in PHP
Home Page: http://leafo.net/lessphp
License: Other
My guess is that it's something to do with the colon after "progid"
/ * For Internet Explorer 5.5 - 7 * /
filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=@color1, endColorstr=@Color2)";
/ * For Internet Explorer 8 * /
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=@color1, endColorstr=@Color2)";
Hi,
Using abstract block results in different output than using inline rules. For example
@test { a, span { font-weight: bold; } }
.bold { @test; }
.bold { a, span { font-weight: bold; } }
results in
.bold a { font-weight:bold; }
.bold span { font-weight:bold; }
.bold a, .bold span { font-weight:bold; }
The abstract block expands each tag which results in more bytes. I think the right output should be like the inline rules, isn't?
Currently, this is how lessc converts a file foo.less to bar.css:
lessc foo.less bar.css
and this how the same thing can be done with plessc:
plessc foo.less > bar.css
It would be nice to have the same behaviour in plessc. It will help people switch easily between lessc and plessc. And it makes it easier for tools (like wrapper scripts or Ant/Maven tasks) as well.
With themes it is useful to be able to specify files hierarchically, so that each file is pulled from the location of highest specificity. This can be facilitated by the parser with just a couple of tweaks:
Add $url = $this->processURL($url); just before the return on import.
add a function lib_url($arg) that calls processURL() on the input.
The default function processURL($url) can be a stub that just returns the URL. The point is to make it extensible by another class later.
The docs clearly state that you should be able to do the following:
@import url(test.less);
A parse error will be thrown, as it seems quotes are required around the file, even when using url()
.
The statement from the title of the bug does not work as expected.
from() and to() does not parse.
-webkit-gradient( linear, 0 0, 100% 0%, from(#eeeeee), to(#ffffff));
Regards Troels.
@charset "utf-8";
=> error
Please create phpDoc comments for the class and it functions, and eliminate the //.
First look at this for what's going on:
http://github.com/cloudhead/less/issues/#issue/109
Implementation
public $selfSelector = '&'; function multiplyTags($tags = array(' '), $d = null) { if ($d === null) $d = count($this->env) - 1; $parents = $d == 0 ? $this->env[$d]['__tags'] : $this->multiplyTags($this->env[$d]['__tags'], $d - 1); $rtags = array(); foreach ($parents as $p) { foreach ($tags as $t) { if ($t{0} == $this->mPrefix) continue; // skip functions $d = ' '; if ($t{0} == ':' || $t{0} == $this->selfSelector) { $t = ltrim($t, $this->selfSelector); $d = ''; } $rtags[] = trim($p.$d.$t); } } return $rtags; }
Example:
input{ &[type=text]{ width: 200px; } &[type=submit]{ width: 100px; } &[type=checkbox], &[type=radio]{ opacity: 0.7; } }
Output:
input[type=text] { width:200px; } input[type=submit] { width:100px; } input[type=checkbox], input[type=radio] { opacity:0.7; }
@grid_columns: 64;
@grid_col_width: 100% / @grid_columns;
.sp (@width: 1) { width: @grid_col_width * @width; }
.col (@width: 1) { .sp(@width); float: left; }
.sp { width:1.5625%; }
.col { width:1.5625%; float:left; }
.sp { width:1.5625%; }
.col { width:0%; float:left; }
Could you be so kind and fix this frustrating behaviour (width:0%) of dev build?
This line of css causes an error:
filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr=#550000FF, endColorstr=#55FFFF00);
I'd like to be able to have some custom processing for properties. Something like this would do it:
function compileProperty($rtags, $name, $value, $level = 0) { // output all repeated properties foreach ($value as $v) { $compiledvalue = $this->compileValue($v); $customprops = array(); if ($this->processProperty($rtags, $name, $compiledvalue, $customprops)) { $props[] = str_repeat(' ', $level).$name.':'.$compiledvalue.';'; } foreach ($customprops as $extraprop) { $props[] = str_repeat(' ', $level).$extraprop.';'; } } return implode("\n", $props); } // This function is a stub. Override in a derived class to customize property processing // // Return true to keep the original property and value // Return false to prevent the original property from being added to the output // // Regardless of return value, $customprops may be populated with extra properties // to include in the final style rule. function processProperty($rtags, $name, $compiledvalue, &$customprops) { return true; } With something like the above, I could then implement processProperty() in a derived class, and do something like this: function processProperty($rtags, $name, $compiledvalue, &$customprops) { switch($name) { case '-jquery': $this->addJqueryStyleScript($rtags, $compiledvalue); return false; case 'border-radius': ...generate vendor specific code and add to $customprops... return false; default: return parent::processProperty($rtags, $name, $compiledvalue, $customprops); } }
This proposal changes the signature of compileProperty, so two other places in the code will have to be tweaked, but I think the value of this is substantial. In the jquery example, style centered behaviors (such as drop menus, easing, or marquees) could be bound in the stylesheet, rather than requiring a separately maintained javascript file.
margin: 26-50px 290-190px;
=> actual result
margin:26 -50px 290 -190px;
=> expected result
margin:-24px 100px;
There is often problems with parsing (@media print, screen, filter(), etc.),
and it isn't easy for you (leafo) to solve them in the minute. That's ok :)
Can we so imagine a "litterral" flag to allow us to write raw CSS in less files (no variable, or mathematical operation) for a specified line, to solve "temporaly" our bugs ? :)
maybe something like
! filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFF0000, endColorstr=#FFFFFF00);
Slash "/" fails when using shorthanded font property:
font: 2em/1em Arial, Verdana;
Have to use full format:
font-family: Arial, Verdana;
font-size: 2em;
line-height: 1em;
Hi, the issue started with the next code (put together for demo):
@images: "/assets/images/";
@images: @images + "timeline/";
.topbar { background: url({@images}topbar.png);ย }
Results in:
background:url(/assets/images/" "timeline/topbar.png);
My solution (lessc.class.php[line826])
foreach ($replace as $var=>$val) {
// strip quotes
if (preg_match('/^(["\']).*?(\1)$/', $val)) {
$val = str_replace(array('"', '\''), '', $val);
}
$value[1] = str_replace('{'.$var.'}', $val, $value[1]);
}
And line 914:
return array('keyword', $this->compileValue($lft) .''. $this->compileValue($rgt));
Now, I haven't tested yet this behavior since compileValue() methods seems to do much more for string variables, so I'm not sure how removing the space would affect the join of other css keywords or params.
I hope a simple solution can be found within this context,
I think it would be useful to add a dataurl function to the core, which accepts a filename, and spits out a dataurl. Something like this:
function lib_dataurl($arg) { $file = $this->processURL($this->compileValue($arg)); return 'url("data:'.$this->getMimeType($file).';base64,'.base64_encode(file_get_contents($file)).'")'; } function getMimeType($file) { $pi = pathinfo($file); switch($pi['extension']) { case 'png': return 'image/png'; case 'bmp': return 'image/bmp'; case 'gif': return 'image/gif'; case 'jpe': case 'jpg': case 'jpeg': return 'image/jpeg'; case 'tif': case 'tiff': return 'image/tiff'; case 'ico': return 'image/x-icon'; default: return 'text/plain'; // unknown type } }
processURL() is from my previous issue, a minor tweak to allow URL postprocessing.
div {
color: green;
p { color: red; }
li { color: p['color']; } /*works*/
}
span {
color:div['color']; /*works*/
color:div>p['color']; /*doesn't work*/
}
possible workaround:
span {
div;
color:p['color']; /*now it works*/
}
but it has a drawback: in generated code, we have the div styles written, which is not what is intended:
/*outputted css:*/
span {
color:green; /*<-unwanted style*/
color:red;
}
It would be better to be able to use accessors with nested rules.
Don't you think it would be really useful to let lessphp generate vendor specific properties from standard ones?
For example, this:
border-radius: 5px;
Could give:
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
-khtml-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
$box(@col: 200px){ .column{ width: @col; } } .content{ $box(100px); }
=>
.content .column { width:; }
Expected:
.content .column { width:100px; }
In some instances, when importing a .less file into another .less file, if the included file begins with a comment, the compiler will error.
This is threated like mixin variable and not sent to output.
@font-face {
font-family: Delicious;
font-weight: bold;
src: url('Delicious-Bold.otf');
}
I have two files File1.css and File2.css. File2.css is being imported into File1.css:
FILE1.CSS:
@import "file2.css";
FILE2.CSS:
/* Comment */ @sampleVar = 1; .sampleClass { display:block; }
This Lessc::parse() method fires Lessc::throwParseError() on the condition:
if ($this->count != strlen($this->buffer)) $this->throwParseError();
If the comment is removed from file2.css or placed after declaring the variable, everything works as intended.
littte testcase
@border(@size: 5px) { border: @size; } @font (@size: 10pt) { font-size: @size; } #diva { @border; } #divb { #diva ; /* #diva style rules */ @font(10pt); }
I expected
#diva { border:5px; } #divb { border: 5px; /* #diva content */ font-size:10pt; }
And lessphp return me :
#diva { border:5px; } #divb { border:10pt; /* NOT #diva content */ font-size:10pt; }
Well I don't really like rgba a function. You know, it's annoying to rewrite your #rrggbb to rgba(r,g,b,a) just to add some transparency. Why it can't be like #rrggbbaa with aa as hexadecimal alpha value for example?
I've implemented this, but there is one more option to add transparency:
#rrggbb-aa
where aa is alpha value in %. So for example
background: #121-50; or background: #112211-50; => background:rgba(17,34,17,0.5);
Implementation:
function color(&$out) { $color = array('color'); if ($this->match('(#([0-9a-f]{3}-[0-9]{2})|#([0-9a-f]{6}-[0-9]{2})|#([0-9a-f]{8})|#([0-9a-f]{6})|#([0-9a-f]{4})|#([0-9a-f]{3}))', $m)) { $num = end($m); if (count($m) >= 4 && count($m) <= 6) { $width = 256; } else { $width = 16; } if (strpos($num, '-')) { $color[4] = (float) ('0.'.substr($num, -2)); $num = substr($num, 0, -3); } $num = hexdec($num); if (count($m) == 5 || count($m) == 7) { $color[4] = round($this->colorHelper($num, $width) / 256, 2); if ($color[4] == 1) { unset($color[4]); } } for ($i = 3; $i >= 1; $i--) { $color[$i] = $this->colorHelper($num, $width); } $out = $color; return true; } return false; }
I would like to write one function like this one:
.bggrad(@color: red; @start: #000000; @end: #ffffff) {
background: @color;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(@start), to(@end));
background: -moz-linear-gradient(top, @start, @end);
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='@start', endColorstr='@end', GradientType='0')";
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='@start', endColorstr='@end', GradientType='0');
}
in the line for IE (last two one), @start and @EnD are not replaced
Please make plessc return a non-zero exit value in case of an error. Then that can be detected from the environment.
Current behaviour:
$ echo "a{" > a.less
$ plessc a.less
Fatal Error:
====================
Failed to parse 1 unclosed block
$ echo $?
0
Requested behaviour:
$ echo "a{" > a.less
$ plessc a.less
Fatal Error:
====================
Failed to parse 1 unclosed block
$ echo $?
1
Or, instead of 1, some other return value could also be returned, just as long as it is not 0.
This allows me to easily detect an error when running plessc from another program, such as an Apache Ant build or from another script.
input{ width: 100px; &[type=text]{ width: 200px; } }
=>
input[type=text] { width:200px; } input { width:100px; }
That is wrong, because in cases like this, the last value takes the priority. I've tried to implemented some sort of buffer to stop the "input[type=text] { width:200px; }" and send it out after "input { width:100px; }". I'm not very sure about it's effectivity but it works.
Implementation:
// parse and compile buffer function parse($str = null) { if ($str) $this->buffer = $str; $this->env = array(); $this->expandStack = array(); $this->count = 0; $this->line = 1; $this->buffer = $this->removeComments($this->buffer); $this->push(); // set up global scope $this->set('__tags', array('')); // equivalent to 1 in tag multiplication // trim whitespace on head if (preg_match('/^\s+/', $this->buffer, $m)) { $this->line += substr_count($m[0], "\n"); $this->buffer = ltrim($this->buffer); } while (false !== ($compiled = $this->chunk())) { if (!is_string($compiled))$compiled = ''; if (!isset($buffer[$this->level-1])) $buffer[$this->level-1] = ''; $buffer[$this->level-1] .= $compiled; if (isset($buffer[$this->level])) { $buffer[$this->level-1] .= $buffer[$this->level]; unset($buffer[$this->level]); } } if ($this->count != strlen($this->buffer)) $this->throwParseError(); if (count($this->env) > 1) throw new exception('parse error: unclosed block'); //print_r($this->env); return $buffer[0]; }
Please add gr unit.
http://www.w3.org/TR/css3-grid/
First issue:
[foo] { test: test }
A selector starting with an attribute selector now results in a fatal error.
Second issue:
*[foo].bar { test: test }
... turns into ...
*[foo] .bar { test: test; }
Notice the added space before .bar.
The first issue is easily worked around for the time being by adding the universal selector, as seen in the example for the second issue. The second issue is quite annoying though :)
new fixColor method
function fixColor($c) { for ($i = 1; $i <= 3; $i++) { if ($c[$i] < 0) $c[$i] = 0; elseif ($c[$i] > 255) $c[$i] = 255; else $c[$i] = floor($c[$i]); } if (array_key_exists(4, $c)) { if ($c[4] < 0) $c[4] = 0; elseif ($c[4] >= 1) unset($c[4]); else $c[4] = round($c[4], 2); } return $c; }Also leafo please fix this one. There is a solution in one of my comments.
Better fix might be return ltrim($out);
at the end of removeComments.
After that this block in parse method should be useless. (But I'm not entirely sure.)
// trim whitespace on head if (preg_match('/^\s+/', $this->buffer, $m)) { $this->line += substr_count($m[0], "\n"); $this->buffer = ltrim($this->buffer); }
Unable to use :
@-webkit-keyframes greenPulse {
from { background-color: #749a02; -webkit-box-shadow: 0 0 9px #333; }
50% { background-color: #91bd09; -webkit-box-shadow: 0 0 18px #91bd09; }
to { background-color: #749a02; -webkit-box-shadow: 0 0 9px #333; }
}
parse error: failed at 50% { background-color: #91bd09; -webkit-box-shadow: 0 0 18px #91bd09; }
line: ...
@gradient($top; $bottom) { //I'm using $vPrefix = '$'; background-image: -moz-linear-gradient(left, $top, $bottom); background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, $top), color-stop(1, $bottom)); //filter is ok filter: progid:DXImageTransform.Microsoft.gradient(startColorStr=$top, EndColorStr=$bottom); //-ms-filter is not working - variables remains as they are and are not replaced with values -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr=$top, EndColorStr=$bottom)"; //another problem is with rgba colors of course }
@media screen, print { body { line-height: 1.2 } }
=> (if $vPrefix is @)
print body { line-height:1.2; }
=> (if
@media screen body, print body { line-height:1.2; }
Well, both are wrong...
I started testing 0.2 and the first problem I got is the compiler having trouble with this, which was previously working for me:
@boxshadow(@h:0; @v:0; @s:4px; @o:0.5) {
-moz-box-shadow: @h @v @s rgba(0, 0, 0, {@o});
-webkit-box-shadow: @h @v @s rgba(0, 0, 0, {@o});
box-shadow: @h @v @s rgba(0, 0, 0, {@o});
}
Well you know there is a problem with mixins. If we use @, it creates incompatibility with css, such as @media, @font-face (solved), @charset and so on. But, even if we find all the words we can't use for mixins, it would be still troublesome to know which word you can use and which word you can not. I've tried to replace all @ with $ and it is much better, but incompatible. Becaouse of incompatibility, I guess that you wont change the @ to anything else, but what about making it optional which character it is? It could be a variable or even a constant. What do you think?
CSS3 transitions can use both "s" and "ms" units, but "ms" doesn't work with Less.
Is being compatible with the official LESS parser a goal?
If I want to use CSS2 Attribute selectors and use a semicolon in them lessphp fails with a parse error.
Example:
img[style ~= "float: right;"] {
margin: 0 0 10px 10px;
}
Please allow the use of a -v argument for getting the version of the program.
Current behaviour:
$ plessc -v
Fatal Error: failed to find file: -v
Requested behaviour:
$ plessc -v
plessc 0.1.5
Note that lessc behaves in line with this request:
$ lessc -v
lessc 1.1.13
as do numerous other programs.
Optionally, the "--version" argument could also be supported, as lessc also does.
Here's a test .less file:
.a {background-position:0 0;}
.b {background-position:0 0;}
.c {background-position:1% 2%;}
.d {background-position:1px 2px;}
.e {background-position:1em 2em;}
.f {background-position:left 0;}
.g {background-position:left top;}
.h {background-position:left 0px;}
.i {background-position:left 1px;}
.j {background-position:left -1px;}
.k {background-position:right -1px;}
.l {background-position:1px bottom;}
.m {background-position:-1px bottom;}
Notice that it does not contain any computations or other Less-specific constructs. The result of this is, however, different from what it should be:
.a { background-position:0 0; }
.b { background-position:0 0; }
.c { background-position:1% 2%; }
.d { background-position:1px 2px; }
.e { background-position:1em 2em; }
.f { background-position:left 0; }
.g { background-position:left top; }
.h { background-position:left 0px; }
.i { background-position:left 1px; }
.j { background-position:-1px; }
.k { background-position:-1px; }
.l { background-position:1px bottom; }
.m { background-position:-1px bottom; }
Notice that the rules for .j and .k are now incorrect. This is inconsistent with lessc-behaviour and in my opinion a bug.
Perhaps the "-1px" is interpreted as a computation?
It would be nice (and useful) if in the output file, before each line will be its sources-lines, in the .less files. Also it would be nice if the output file will be minified.
I think it should be an option while compiling (something ilke: 0 - minified mode, 1 (default) - regular mode, 2 - explain-sources mode).
When I'm talking about sources-line noting, I'm thinking on somthing like that (from the homepage example):
/* source.less : 4 */ .underline { border-bottom:1px solid green; } /* source.less : 13, 4 */ #header .navigation a { border-bottom:1px solid green; } /* source.less : 11, 1 */ #header .navigation { font-size:12px; } /* source.less : 18 */ #header .logo:hover { text-decoration:none; } /* source.less : 17 */ #header .logo { width:300px; } #header { /* source.less : 7 */ color:black; /* source.less : 8, 2 */ border:1px solid #dd44dd; }
(the same should be done if there are multiple .less files involving; file-name + line-number for each source-line)
I've tried to check how to do it myself, but I've no idea how to dive in the code...
filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=0px, OffY=0px, Color='#ffffff');
=>
Fatal error: Uncaught exception 'Exception' with message 'parse error: failed at filter: progid:DXImageTransform.Microsoft.dropshadow(OffX=0px, OffY=0px, Color='#ffffff');
line: 20' in C:\Server\localhost\less2\lessc.inc.php:1149
Stack trace:
#0 C:\Server\localhost\less2\lessc.inc.php(1137): lessc->throwParseError()
#1 C:\Server\localhost\less2\example.php(23): lessc->parse()
#2 {main}
thrown in C:\Server\localhost\less2\lessc.inc.php on line 1149
I got this gradient code from http://gradients.glrzad.com/:
-webkit-gradient( linear, left top, left bottom, color-stop(0.19, rgb(236,233,227)), color-stop(0.6, rgb(246,246,245)) ) -moz-linear-gradient( center top, rgb(236,233,227) 19%, rgb(246,246,245) 60% )
lessphp is failing on the webkit line. I'm getting:
lessc fatal error: Failed to parse line 2791 Offending line: -webkit-gradient(linear, left top, left bottom, color-stop(0.19, rgb(236,233,227)), color-stop(0.6, rgb(246,246,245)));
Is there something I can do fix it?
Thx!
I've found this little bug.
LESS input:
.color { color: rgb(0, 0, 0); }
CSS output:
.color { color:rgb(0,0,0); }
expected output:
.color { color:#000000; }
I'm not sure where is the right place to call $this->funcToColor($func);
...
Right at the moment the Compilation-Interface only allows to enter an input and an output filename. Wouldn't it be nice also to be able to pass parameters as an array, which can be used as variables in LESS? This could e.g. allow to easily include features like allowing a user to set a custom background-color or setting a custom font size. (Especially if you use the symfony-Plugin this would be a powerful feature)
At the moment you could only get such a behavior it you write a LESS-File which defines variables in PHP to the filesystem and then import that with your base file. But this is difficult to use, especially if you want to use several versions of a CSS-file at a time.
The easiest behavior for using this feature would be, that variables in the LESS-File would simply be overwritten. So - to not cause errors without PHP-parameters - default parameters can be set in the LESS-file which will be used, when no parameters are passed. Maybe you could also think of an "important!" for variable definition which would protect a variable of overwriting, but this would not be a necessary feature in my eyes.
PHP:
lessc::ccompile('input.less', 'out.css', array('background-color' => '#ddd'));
LESS:
@background-color: #fff; body { background: @background-color; }
Compiled CSS:
body { background: #ddd; }
I sometimes use !important for debuging porposes but I hate to write the loooong !important word and it's also not much visible when I want to remove it. So what about this:
Example:
!font-family: Verdana, sans-serif; !border-radius: 3px -5px; border-radius: 3px -5px !important;
Output:
font-family: Verdana, sans-serif !important; border-radius:3px -5px !important; border-radius:3px -5px !important;
Implementation: (small change in chunk method)
public $important = '!'; // compile chunk off the head of buffer function chunk() { if (empty($this->buffer)) return false; $s = $this->seek(); // a property if ($this->keyword($key) && $this->literal(':') && $this->propertyValue($value) && $this->end()) { // THIS WAS ADDED if ($key{0} == '!') { $key = substr($key, 1); if ($value[0] == 'list' && $value[1] == ' ') { $value[2][] = array('keyword', '!important'); } else { $value = array('list', ' ', array($value, array('keyword', '!important'))); } } // END OF ADDED $this->append($key, $value); if (count($this->env) == 1) return $this->compileProperty($key, array($value))."\n"; else return true; } else { $this->seek($s); } //...chunk continues }
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.