From 0b692595dd60feca1b63d4142406ea638180e452 Mon Sep 17 00:00:00 2001 From: ku Date: Wed, 26 Sep 2012 16:57:46 -0700 Subject: [PATCH 01/13] Correct documentation about Custom Functions --- docs/docs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs.md b/docs/docs.md index 7da9e1d3..c2306d47 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -1206,8 +1206,8 @@ like so: ```php $less->registerFunction("double", function($arg) { - list($type, $value) = $arg; - return array($type, $value*2); + list($type, $value, $unit) = $arg; + return array($type, $value*2, $unit); }); ``` From 04b3d316b90db1fdfa6e82a1c11a09faa7a489ef Mon Sep 17 00:00:00 2001 From: PeterKnight Date: Tue, 16 Oct 2012 05:32:49 +0200 Subject: [PATCH 02/13] Update lessc.inc.php Add support for the rem unit --- lessc.inc.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lessc.inc.php b/lessc.inc.php index c42147c5..91316152 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -814,6 +814,10 @@ protected function lib_isem($value) { return $this->toBool($value[0] == "number" && $value[2] == "em"); } + protected function lib_isrem($value) { + return $this->toBool($value[0] == "number" && $value[2] == "rem"); + } + protected function lib_rgbahex($color) { $color = $this->coerceColor($color); if (is_null($color)) From 340af3f352cbf967d38a06b74e7439c74ee274d3 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Sat, 27 Oct 2012 16:32:48 -0700 Subject: [PATCH 03/13] add contrast function #330 thanks @kaystrobach --- docs/docs.md | 3 +++ lessc.inc.php | 19 +++++++++++++++++++ tests/inputs/colors.less | 5 +++++ tests/outputs/colors.css | 4 ++++ 4 files changed, 31 insertions(+) diff --git a/docs/docs.md b/docs/docs.md index c2306d47..77c3fc98 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -847,6 +847,9 @@ function that let's you unquote any value. It is called `e`. the alpha of the colors if it exists. See . +* `constrast(color, dark, light)` -- if `color` has a lightness value greater + than 50% then `dark` is returned, otherwise return `light`. + * `rgbahex(color)` -- returns a string containing 4 part hex color. This is used to convert a CSS color into the hex format that IE's filter diff --git a/lessc.inc.php b/lessc.inc.php index c42147c5..9cc2a60b 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -1029,6 +1029,25 @@ protected function lib_mix($args) { return $this->fixColor($new); } + protected function lib_contrast($args) { + if ($args[0] != 'list' || count($args[2]) < 3) { + return array(array('color', 0, 0, 0), 0); + } + + list($inputColor, $darkColor, $lightColor) = $args[2]; + + $inputColor = $this->assertColor($inputColor); + $darkColor = $this->assertColor($darkColor); + $lightColor = $this->assertColor($lightColor); + $hsl = $this->toHSL($inputColor); + + if ($hsl[3] > 50) { + return $darkColor; + } + + return $lightColor; + } + protected function assertColor($value, $error = "expected color value") { $color = $this->coerceColor($value); if (is_null($color)) $this->throwError($error); diff --git a/tests/inputs/colors.less b/tests/inputs/colors.less index 40edb8c6..4c99599f 100644 --- a/tests/inputs/colors.less +++ b/tests/inputs/colors.less @@ -85,6 +85,11 @@ fade { color: mix(rgba(5,3,1,0.3), rgba(6,3,2, 0.8), 50%); } +.contrast { + color: contrast(#000, red, blue); + color: contrast(#fff, red, blue); +} + .percent { per: percentage(0.5); } diff --git a/tests/outputs/colors.css b/tests/outputs/colors.css index 2dd0d35f..07c59017 100644 --- a/tests/outputs/colors.css +++ b/tests/outputs/colors.css @@ -57,6 +57,10 @@ fade { color: #808080; color: rgba(6,3,2,-0.25); } +.contrast { + color: #0000ff; + color: #ff0000; +} .percent { per: 50%; } From f8a84b16b7b8f531beb673d4d7723624dd216a9d Mon Sep 17 00:00:00 2001 From: Lucas Green Date: Wed, 9 May 2012 10:10:23 -0700 Subject: [PATCH 04/13] Added: red(), green(), and blue() functions, they work much like hue(), saturation() and lightness() except that they return a unitless scalar between 0 and 255 for their respective color components, much like the expected inputs to rgb() Added: tests for new functions to colors.less and colors.css --- lessc.inc.php | 28 ++++++++++++++++++++++++++++ tests/inputs/colors.less | 4 ++++ tests/outputs/colors.css | 3 +++ 3 files changed, 35 insertions(+) diff --git a/lessc.inc.php b/lessc.inc.php index 94620cf2..916e6642 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -1468,6 +1468,34 @@ protected function op_color_color($op, $left, $right) { return $this->fixColor($out); } + function lib_red($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for red()'); + } + + return $color[1]; + } + + function lib_green($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for green()'); + } + + return $color[2]; + } + + function lib_blue($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for blue()'); + } + + return $color[3]; + } + + // operator on two numbers protected function op_number_number($op, $left, $right) { $unit = empty($left[2]) ? $right[2] : $left[2]; diff --git a/tests/inputs/colors.less b/tests/inputs/colors.less index 4c99599f..b887cb7e 100644 --- a/tests/inputs/colors.less +++ b/tests/inputs/colors.less @@ -1,5 +1,9 @@ body { + color:rgb(red(#f00), red(#0F0), red(#00f)); + color:rgb(red(#f00), green(#0F0), blue(#00f)); + color:rgb(red(#0ff), green(#f0f), blue(#ff0)); + color: hsl(34, 50%, 40%); color: hsla(34, 50%, 40%, 0.3); diff --git a/tests/outputs/colors.css b/tests/outputs/colors.css index 07c59017..d167a48f 100644 --- a/tests/outputs/colors.css +++ b/tests/outputs/colors.css @@ -1,4 +1,7 @@ body { + color: #ff0000; + color: #ffffff; + color: #000000; color: #996d33; color: rgba(153,109,51,0.3); lighten: #ffffff; From a764d0b9529862057c57181182dc20370eacb71f Mon Sep 17 00:00:00 2001 From: Nikolay Yordanov Date: Mon, 29 Oct 2012 15:47:39 +0000 Subject: [PATCH 05/13] "transparent" is a shorthand for rgba(0,0,0,0) http://www.w3.org/TR/css3-color/#transparent-def --- lessc.inc.php | 9 +++++++-- tests/inputs/colors.less | 7 ++++++- tests/outputs/colors.css | 6 ++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lessc.inc.php b/lessc.inc.php index 916e6642..6726f49a 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -1322,8 +1322,12 @@ protected function coerceColor($value) { case 'keyword': $name = $value[1]; if (isset(self::$cssColors[$name])) { - list($r, $g, $b) = explode(',', self::$cssColors[$name]); - return array('color', $r, $g, $b); + $rgba = explode(',', self::$cssColors[$name]); + + if(isset($rgba[3])) + return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]); + + return array('color', $rgba[0], $rgba[1], $rgba[2]); } return null; } @@ -1996,6 +2000,7 @@ public static function cexecute($in, $force = false, $less = null) { 'teal' => '0,128,128', 'thistle' => '216,191,216', 'tomato' => '255,99,71', + 'transparent' => '0,0,0,0', 'turquoise' => '64,224,208', 'violet' => '238,130,238', 'wheat' => '245,222,179', diff --git a/tests/inputs/colors.less b/tests/inputs/colors.less index b887cb7e..c9f3d14d 100644 --- a/tests/inputs/colors.less +++ b/tests/inputs/colors.less @@ -144,5 +144,10 @@ dd { c: 132- red; } - +.transparent { + r: red(transparent); + g: green(transparent); + b: blue(transparent); + a: alpha(transparent); +} diff --git a/tests/outputs/colors.css b/tests/outputs/colors.css index d167a48f..517f0da3 100644 --- a/tests/outputs/colors.css +++ b/tests/outputs/colors.css @@ -94,3 +94,9 @@ dd { c: 132 - #ff0000; c: 132- #ff0000; } +.transparent { + r: 0; + g: 0; + b: 0; + a: 0; +} From da15f54506ce5023eaeb9ad9cae83470ffe018a1 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Sat, 3 Nov 2012 10:24:58 -0700 Subject: [PATCH 06/13] remove -q --- lessify | 2 +- plessc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lessify b/lessify index 416f0ca4..df8e8686 100755 --- a/lessify +++ b/lessify @@ -1,4 +1,4 @@ -#!/usr/bin/php -q +#!/usr/bin/php , 2012 From 7979d6acea68a62e14cba188935cb1f90c62cf9d Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Tue, 5 Feb 2013 20:22:15 +0100 Subject: [PATCH 07/13] Add branch-alias This way people can require "0.3.*" and get stable vs unstable versions depending on their minimum-stability, without having to deal with the pains of dev-master. --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index 5a29a284..2b525a57 100644 --- a/composer.json +++ b/composer.json @@ -16,5 +16,10 @@ ], "autoload": { "classmap": ["lessc.inc.php"] + }, + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } } } From d77ac773d82ea0ad8b163591831143ca47532803 Mon Sep 17 00:00:00 2001 From: Matt Labrum Date: Fri, 11 Jan 2013 15:43:21 +1030 Subject: [PATCH 08/13] Add support for media query variables #335 --- lessc.inc.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lessc.inc.php b/lessc.inc.php index 6726f49a..26983dcf 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -327,6 +327,9 @@ protected function compileMediaQuery($queries) { $parts[] = "($q[1])"; } break; + case "variable": + $parts[] = $this->compileValue($this->reduce($q)); + break; } } @@ -2575,6 +2578,9 @@ protected function mediaExpression(&$out) { $out = array("mediaExp", $feature); if ($value) $out[] = $value; return true; + }elseif($this->variable($variable)) { + $out = array('variable', $variable); + return true; } $this->seek($s); From e226d1ee53d079437d640c88d1d8a553fcec9f39 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Wed, 6 Feb 2013 14:22:46 -0800 Subject: [PATCH 09/13] add test for variable in media --- lessc.inc.php | 2 +- tests/inputs/media.less | 6 +++++- tests/outputs/media.css | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lessc.inc.php b/lessc.inc.php index 26983dcf..6a5b0120 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -2578,7 +2578,7 @@ protected function mediaExpression(&$out) { $out = array("mediaExp", $feature); if ($value) $out[] = $value; return true; - }elseif($this->variable($variable)) { + } elseif ($this->variable($variable)) { $out = array('variable', $variable); return true; } diff --git a/tests/inputs/media.less b/tests/inputs/media.less index 80f0e859..8c16a3cf 100644 --- a/tests/inputs/media.less +++ b/tests/inputs/media.less @@ -61,4 +61,8 @@ } } - +// variable in query +@mobile: ~"(max-width: 599px)"; +@media @mobile { + .helloworld { color: blue } +} diff --git a/tests/outputs/media.css b/tests/outputs/media.css index 99f04b62..99da8c31 100644 --- a/tests/outputs/media.css +++ b/tests/outputs/media.css @@ -63,3 +63,8 @@ } } } +@media (max-width: 599px) { + .helloworld { + color: blue; + } +} From 655abb359b9f616e6db5a29534c8d1bf07a382eb Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Wed, 6 Feb 2013 14:47:20 -0800 Subject: [PATCH 10/13] add unit function, fixes #367 --- lessc.inc.php | 10 ++++++++++ tests/inputs/builtins.less | 8 ++++++++ tests/outputs/builtins.css | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/lessc.inc.php b/lessc.inc.php index 6a5b0120..4f99e9cc 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -897,6 +897,16 @@ protected function lib_round($arg) { return array("number", round($value), $arg[2]); } + protected function lib_unit($arg) { + if ($arg[0] == "list") { + list($number, $newUnit) = $arg[2]; + return array("number", $this->assertNumber($number), + $this->compileValue($this->lib_e($newUnit))); + } else { + return array("number", $this->assertNumber($arg), ""); + } + } + /** * Helper function to get arguments for color manipulation functions. * takes a list that contains a color like thing and a percentage diff --git a/tests/inputs/builtins.less b/tests/inputs/builtins.less index f091428d..f0ce68a7 100644 --- a/tests/inputs/builtins.less +++ b/tests/inputs/builtins.less @@ -63,3 +63,11 @@ format { } +#unit { + @unit: "em"; + height: unit(10px); + height: unit(10px, "s"); + height: unit(10px, @unit); + height: unit(0.07407s) * 100%; +} + diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css index 7a99aac5..c8f74d60 100644 --- a/tests/outputs/builtins.css +++ b/tests/outputs/builtins.css @@ -39,3 +39,9 @@ format { em: true; em: false; } +#unit { + height: 10; + height: 10s; + height: 10em; + height: 7.407%; +} From 21a012ff48b289e3e500ebd7c45ca90d5acbd39c Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Mon, 11 Feb 2013 20:15:53 -0800 Subject: [PATCH 11/13] support nested interpolations #345 --- lessc.inc.php | 19 +++++++++++-------- tests/inputs/interpolation.less | 11 +++++++++++ tests/outputs/interpolation.css | 5 +++++ 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 tests/inputs/interpolation.less create mode 100644 tests/outputs/interpolation.css diff --git a/lessc.inc.php b/lessc.inc.php index 4f99e9cc..4a819d73 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -1215,6 +1215,10 @@ protected function funcToColor($func) { protected function reduce($value, $forExpression = false) { switch ($value[0]) { + case "interpolate": + $reduced = $this->reduce($value[1]); + $var = $this->compileValue($reduced); + return $this->lib_e($this->reduce(array("variable", $this->vPrefix . $var))); case "variable": $key = $value[1]; if (is_array($key)) { @@ -1490,7 +1494,7 @@ function lib_red($color){ if (is_null($color)) { $this->throwError('color expected for red()'); } - + return $color[1]; } @@ -1499,7 +1503,7 @@ function lib_green($color){ if (is_null($color)) { $this->throwError('color expected for green()'); } - + return $color[2]; } @@ -1508,7 +1512,7 @@ function lib_blue($color){ if (is_null($color)) { $this->throwError('color expected for blue()'); } - + return $color[3]; } @@ -2644,12 +2648,11 @@ protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null continue; } - if (in_array($tok, $rejectStrs)) { - $count = null; + if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) { + $ount = null; break; } - $content[] = $tok; $this->count+= strlen($tok); } @@ -2724,10 +2727,10 @@ protected function interpolation(&$out) { $s = $this->seek(); if ($this->literal("@{") && - $this->keyword($var) && + $this->openString("}", $interp, null, array("'", '"', ";")) && $this->literal("}", false)) { - $out = array("variable", $this->lessc->vPrefix . $var); + $out = array("interpolate", $interp); $this->eatWhiteDefault = $oldWhite; if ($this->eatWhiteDefault) $this->whitespace(); return true; diff --git a/tests/inputs/interpolation.less b/tests/inputs/interpolation.less new file mode 100644 index 00000000..6f270054 --- /dev/null +++ b/tests/inputs/interpolation.less @@ -0,0 +1,11 @@ + +@cool-hello: "yes"; +@cool-yes: "okay"; +@var: "hello"; + +div { + color: ~"@{cool-hello}"; + color: ~"@{cool-@{var}}"; + color: ~"@{cool-@{cool-@{var}}}"; +} + diff --git a/tests/outputs/interpolation.css b/tests/outputs/interpolation.css new file mode 100644 index 00000000..95e5cc33 --- /dev/null +++ b/tests/outputs/interpolation.css @@ -0,0 +1,5 @@ +div { + color: yes; + color: yes; + color: okay; +} From ee5b675b482585647725ede4061f023473d379e3 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Tue, 12 Feb 2013 20:12:28 -0800 Subject: [PATCH 12/13] support interpolation inside of selectors fixes #370 #372 #369 #356 --- lessc.inc.php | 63 ++++++++++++++++++++++++++------- tests/inputs/interpolation.less | 22 ++++++++++++ tests/outputs/interpolation.css | 12 +++++++ 3 files changed, 84 insertions(+), 13 deletions(-) diff --git a/lessc.inc.php b/lessc.inc.php index 4a819d73..be2c884b 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -437,7 +437,7 @@ protected function compileSelectors($selectors) { foreach ($selectors as $s) { if (is_array($s)) { list(, $value) = $s; - $out[] = $this->compileValue($this->reduce($value)); + $out[] = trim($this->compileValue($this->reduce($value))); } else { $out[] = $s; } @@ -1218,7 +1218,11 @@ protected function reduce($value, $forExpression = false) { case "interpolate": $reduced = $this->reduce($value[1]); $var = $this->compileValue($reduced); - return $this->lib_e($this->reduce(array("variable", $this->vPrefix . $var))); + $res = $this->reduce(array("variable", $this->vPrefix . $var)); + + if (empty($value[2])) $res = $this->lib_e($res); + + return $res; case "variable": $key = $value[1]; if (is_array($key)) { @@ -2904,38 +2908,71 @@ protected function tagExpression(&$value) { return false; } - // a single tag + // a space separated list of selectors protected function tag(&$tag, $simple = false) { if ($simple) - $chars = '^,:;{}\][>\(\) "\''; + $chars = '^@,:;{}\][>\(\) "\''; else - $chars = '^,;{}["\''; + $chars = '^@,;{}["\''; + + $s = $this->seek(); if (!$simple && $this->tagExpression($tag)) { return true; } - $tag = ''; - while ($this->tagBracket($first)) $tag .= $first; + $hasExpression = false; + $parts = array(); + while ($this->tagBracket($first)) $parts[] = $first; + + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; while (true) { if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) { - $tag .= $m[1]; + $parts[] = $m[1]; if ($simple) break; - while ($this->tagBracket($brack)) $tag .= $brack; + while ($this->tagBracket($brack)) { + $parts[] = $brack; + } continue; - } elseif ($this->unit($unit)) { // for keyframes - $tag .= $unit[1] . $unit[2]; + } + + if ($this->interpolation($interp)) { + $hasExpression = true; + $interp[2] = true; // don't unescape + $parts[] = $interp; continue; } + + if ($this->literal("@")) { + $parts[] = "@"; + continue; + } + + if ($this->unit($unit)) { // for keyframes + $parts[] = $unit[1]; + $parts[] = $unit[2]; + continue; + } + break; } + $this->eatWhiteDefault = $oldWhite; + if (!$parts) { + $this->seek($s); + return false; + } - $tag = trim($tag); - if ($tag == '') return false; + if ($hasExpression) { + $tag = array("exp", array("string", "", $parts)); + } else { + $tag = trim(implode($parts)); + } + $this->whitespace(); return true; } diff --git a/tests/inputs/interpolation.less b/tests/inputs/interpolation.less index 6f270054..58ffa2fc 100644 --- a/tests/inputs/interpolation.less +++ b/tests/inputs/interpolation.less @@ -9,3 +9,25 @@ div { color: ~"@{cool-@{cool-@{var}}}"; } +// interpolation in selectors + +@hello: 10; +@world: "yeah"; + +@{hello}@{world} { + color: blue; +} + +@{hello} { + color: blue; +} + +hello world @{hello} { + color: red; +} + +#@{world} { + color: "hello @{hello}"; +} + + diff --git a/tests/outputs/interpolation.css b/tests/outputs/interpolation.css index 95e5cc33..40873e01 100644 --- a/tests/outputs/interpolation.css +++ b/tests/outputs/interpolation.css @@ -3,3 +3,15 @@ div { color: yes; color: okay; } +10"yeah" { + color: blue; +} +10 { + color: blue; +} +hello world 10 { + color: red; +} +#"yeah" { + color: "hello 10"; +} From 00fdb9ea66c6d89b3864a9025374e52c338c06a3 Mon Sep 17 00:00:00 2001 From: leaf corcoran Date: Tue, 12 Feb 2013 20:14:39 -0800 Subject: [PATCH 13/13] performance boost for selector parsing with interpolations --- lessc.inc.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lessc.inc.php b/lessc.inc.php index be2c884b..90a1a1e8 100644 --- a/lessc.inc.php +++ b/lessc.inc.php @@ -2939,16 +2939,18 @@ protected function tag(&$tag, $simple = false) { continue; } - if ($this->interpolation($interp)) { - $hasExpression = true; - $interp[2] = true; // don't unescape - $parts[] = $interp; - continue; - } + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") { + if ($this->interpolation($interp)) { + $hasExpression = true; + $interp[2] = true; // don't unescape + $parts[] = $interp; + continue; + } - if ($this->literal("@")) { - $parts[] = "@"; - continue; + if ($this->literal("@")) { + $parts[] = "@"; + continue; + } } if ($this->unit($unit)) { // for keyframes