Version Notes
Support of Magento CE 1.8
phpsass library updated.
Download this release
Release Info
Developer | Laurent Clouet |
Extension | Sass |
Version | 1.1.4 |
Comparing to | |
See all releases |
Code changes from version 1.1.3 to 1.1.4
- app/code/community/Laurent/Sass/etc/config.xml +1 -1
- lib/phpsass/Extensions/Compass/Compass.php +25 -9
- lib/phpsass/Extensions/Own/Own.php +2 -1
- lib/phpsass/Extensions/Susy/Susy.php +2 -2
- lib/phpsass/Extensions/example.php +1 -5
- lib/phpsass/SassException.php +5 -3
- lib/phpsass/SassFile.php +20 -8
- lib/phpsass/SassParser.php +95 -60
- lib/phpsass/VERSION +2 -0
- lib/phpsass/renderers/SassCompactRenderer.php +25 -13
- lib/phpsass/renderers/SassCompressedRenderer.php +22 -11
- lib/phpsass/renderers/SassExpandedRenderer.php +14 -7
- lib/phpsass/renderers/SassNestedRenderer.php +17 -10
- lib/phpsass/renderers/SassRenderer.php +9 -7
- lib/phpsass/script/SassScriptFunction.php +35 -24
- lib/phpsass/script/SassScriptFunctions.php +155 -65
- lib/phpsass/script/SassScriptLexer.php +27 -31
- lib/phpsass/script/SassScriptOperation.php +17 -11
- lib/phpsass/script/SassScriptParser.php +27 -30
- lib/phpsass/script/SassScriptParserExceptions.php +1 -1
- lib/phpsass/script/SassScriptVariable.php +11 -7
- lib/phpsass/script/literals/SassBoolean.php +18 -12
- lib/phpsass/script/literals/SassColour.php +132 -103
- lib/phpsass/script/literals/SassList.php +38 -29
- lib/phpsass/script/literals/SassLiteral.php +78 -42
- lib/phpsass/script/literals/SassLiteralExceptions.php +1 -1
- lib/phpsass/script/literals/SassNumber.php +106 -69
- lib/phpsass/script/literals/SassString.php +30 -16
- lib/phpsass/tests/alt.css +15 -14
- lib/phpsass/tests/extend_included.css +0 -3
- lib/phpsass/tests/functions.css +9 -69
- lib/phpsass/tests/phpSassTest.php +134 -73
- lib/phpsass/tree/SassCommentNode.php +12 -6
- lib/phpsass/tree/SassContentNode.php +9 -4
- lib/phpsass/tree/SassContext.php +35 -20
- lib/phpsass/tree/SassDebugNode.php +9 -6
- lib/phpsass/tree/SassDirectiveNode.php +24 -16
- lib/phpsass/tree/SassEachNode.php +8 -5
- lib/phpsass/tree/SassElseNode.php +5 -3
- lib/phpsass/tree/SassExtendNode.php +8 -4
- lib/phpsass/tree/SassForNode.php +11 -7
- lib/phpsass/tree/SassFunctionDefinitionNode.php +13 -6
- lib/phpsass/tree/SassIfNode.php +19 -16
- lib/phpsass/tree/SassImportNode.php +10 -6
- lib/phpsass/tree/SassMediaNode.php +6 -4
- lib/phpsass/tree/SassMixinDefinitionNode.php +11 -5
- lib/phpsass/tree/SassMixinNode.php +8 -4
- lib/phpsass/tree/SassNode.php +89 -56
- lib/phpsass/tree/SassNodeExceptions.php +0 -1
- lib/phpsass/tree/SassPropertyNode.php +33 -21
- lib/phpsass/tree/SassReturnNode.php +15 -9
- lib/phpsass/tree/SassRootNode.php +17 -7
- lib/phpsass/tree/SassRuleNode.php +51 -37
- lib/phpsass/tree/SassVariableNode.php +10 -5
- lib/phpsass/tree/SassWarnNode.php +10 -8
- lib/phpsass/tree/SassWhileNode.php +9 -6
- package.xml +7 -6
app/code/community/Laurent/Sass/etc/config.xml
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
<config>
|
15 |
<modules>
|
16 |
<Laurent_Sass>
|
17 |
-
<version>1.1.
|
18 |
</Laurent_Sass>
|
19 |
</modules>
|
20 |
<global>
|
14 |
<config>
|
15 |
<modules>
|
16 |
<Laurent_Sass>
|
17 |
+
<version>1.1.4</version>
|
18 |
</Laurent_Sass>
|
19 |
</modules>
|
20 |
<global>
|
lib/phpsass/Extensions/Compass/Compass.php
CHANGED
@@ -152,6 +152,7 @@ class Compass implements ExtensionInterface
|
|
152 |
if ($path) {
|
153 |
return $path;
|
154 |
}
|
|
|
155 |
return false;
|
156 |
}
|
157 |
|
@@ -160,6 +161,7 @@ class Compass implements ExtensionInterface
|
|
160 |
if ($info = self::compassImageInfo($file)) {
|
161 |
return new SassNumber($info[0] . 'px');
|
162 |
}
|
|
|
163 |
return new SassNumber('0px');
|
164 |
}
|
165 |
|
@@ -168,6 +170,7 @@ class Compass implements ExtensionInterface
|
|
168 |
if ($info = self::compassImageInfo($file)) {
|
169 |
return new SassNumber($info[1] . 'px');
|
170 |
}
|
|
|
171 |
return new SassNumber('0px');
|
172 |
}
|
173 |
|
@@ -178,10 +181,10 @@ class Compass implements ExtensionInterface
|
|
178 |
return $info;
|
179 |
}
|
180 |
}
|
|
|
181 |
return false;
|
182 |
}
|
183 |
|
184 |
-
|
185 |
public static function compassInlineImage($file, $mime = null)
|
186 |
{
|
187 |
if ($path = self::compassUrl($file, true, false)) {
|
@@ -189,8 +192,10 @@ class Compass implements ExtensionInterface
|
|
189 |
$mime = $info['mime'];
|
190 |
$data = base64_encode(file_get_contents($path));
|
191 |
# todo - do not return encoded if file size > 32kb
|
|
|
192 |
return new SassString("url('data:$mime;base64,$data')");
|
193 |
}
|
|
|
194 |
return new SassString('');
|
195 |
}
|
196 |
|
@@ -252,7 +257,7 @@ class Compass implements ExtensionInterface
|
|
252 |
if (is_object($v)) {
|
253 |
$string = (isset($v->value) ? $v->value : false);
|
254 |
} else {
|
255 |
-
$string = (string)$v;
|
256 |
}
|
257 |
if (empty($string) || $string == 'false') {
|
258 |
unset($args[$k]);
|
@@ -260,6 +265,7 @@ class Compass implements ExtensionInterface
|
|
260 |
}
|
261 |
$list[] = $string;
|
262 |
}
|
|
|
263 |
return new SassString(implode($sep, $list));
|
264 |
}
|
265 |
|
@@ -282,6 +288,7 @@ class Compass implements ExtensionInterface
|
|
282 |
if (isset($list[$place])) {
|
283 |
return current(SassScriptLexer::$instance->lex($list[$place], new SassContext()));
|
284 |
}
|
|
|
285 |
return new SassBoolean(false);
|
286 |
}
|
287 |
|
@@ -292,6 +299,7 @@ class Compass implements ExtensionInterface
|
|
292 |
foreach ($args as $arg) {
|
293 |
$list = array_merge($list, self::compassList($arg));
|
294 |
}
|
|
|
295 |
return new SassString(implode(', ', $list));
|
296 |
}
|
297 |
|
@@ -299,6 +307,7 @@ class Compass implements ExtensionInterface
|
|
299 |
{
|
300 |
$args = func_get_args();
|
301 |
$list = self::compassList($args, ',');
|
|
|
302 |
return new SassString(implode(' ', $list));
|
303 |
}
|
304 |
|
@@ -306,6 +315,7 @@ class Compass implements ExtensionInterface
|
|
306 |
{
|
307 |
$args = func_get_args();
|
308 |
$list = self::compassList($args, ',');
|
|
|
309 |
return new SassNumber(count($list));
|
310 |
}
|
311 |
|
@@ -315,6 +325,7 @@ class Compass implements ExtensionInterface
|
|
315 |
$end = array_pop($args);
|
316 |
$start = array_pop($args);
|
317 |
$list = self::compassList($args, ',');
|
|
|
318 |
return implode(',', array_slice($list, $start, $end));
|
319 |
}
|
320 |
|
@@ -322,6 +333,7 @@ class Compass implements ExtensionInterface
|
|
322 |
{
|
323 |
$args = array();
|
324 |
$args[] = 'first';
|
|
|
325 |
return call_user_func_array('self::compassCompassNth', $args);
|
326 |
}
|
327 |
|
@@ -366,6 +378,7 @@ class Compass implements ExtensionInterface
|
|
366 |
}
|
367 |
}
|
368 |
$out[] = $stack;
|
|
|
369 |
return $out;
|
370 |
}
|
371 |
|
@@ -395,6 +408,7 @@ class Compass implements ExtensionInterface
|
|
395 |
foreach ($list as $k => $selector) {
|
396 |
$list[$k] = trim($selector) . $new;
|
397 |
}
|
|
|
398 |
return new SassString(implode(', ', $list));
|
399 |
}
|
400 |
|
@@ -414,13 +428,14 @@ class Compass implements ExtensionInterface
|
|
414 |
$to = 6;
|
415 |
}
|
416 |
|
417 |
-
$from = (int)$from;
|
418 |
-
$to = (int)$to;
|
419 |
|
420 |
$output = array();
|
421 |
for ($i = $from; $i <= $to; $i++) {
|
422 |
$output[] = 'h' . $i;
|
423 |
}
|
|
|
424 |
return new SassString(implode(', ', $output));
|
425 |
}
|
426 |
|
@@ -459,7 +474,6 @@ class Compass implements ExtensionInterface
|
|
459 |
|
460 |
public static function compassStylesheetUrl($path, $only_path = false)
|
461 |
{
|
462 |
-
|
463 |
return self::compassUrl($path, $only_path);
|
464 |
}
|
465 |
|
@@ -489,6 +503,7 @@ class Compass implements ExtensionInterface
|
|
489 |
if ($only_path) {
|
490 |
return new SassString($path);
|
491 |
}
|
|
|
492 |
return new SassString("url('$path')");
|
493 |
}
|
494 |
|
@@ -497,15 +512,16 @@ class Compass implements ExtensionInterface
|
|
497 |
$ret = '';
|
498 |
if ($from == 'top') {
|
499 |
$ret = 'bottom';
|
500 |
-
}
|
501 |
$ret = 'top';
|
502 |
-
}
|
503 |
$ret = 'right';
|
504 |
-
}
|
505 |
$ret = 'left';
|
506 |
-
}
|
507 |
$ret = 'center';
|
508 |
}
|
|
|
509 |
return $ret;
|
510 |
}
|
511 |
}
|
152 |
if ($path) {
|
153 |
return $path;
|
154 |
}
|
155 |
+
|
156 |
return false;
|
157 |
}
|
158 |
|
161 |
if ($info = self::compassImageInfo($file)) {
|
162 |
return new SassNumber($info[0] . 'px');
|
163 |
}
|
164 |
+
|
165 |
return new SassNumber('0px');
|
166 |
}
|
167 |
|
170 |
if ($info = self::compassImageInfo($file)) {
|
171 |
return new SassNumber($info[1] . 'px');
|
172 |
}
|
173 |
+
|
174 |
return new SassNumber('0px');
|
175 |
}
|
176 |
|
181 |
return $info;
|
182 |
}
|
183 |
}
|
184 |
+
|
185 |
return false;
|
186 |
}
|
187 |
|
|
|
188 |
public static function compassInlineImage($file, $mime = null)
|
189 |
{
|
190 |
if ($path = self::compassUrl($file, true, false)) {
|
192 |
$mime = $info['mime'];
|
193 |
$data = base64_encode(file_get_contents($path));
|
194 |
# todo - do not return encoded if file size > 32kb
|
195 |
+
|
196 |
return new SassString("url('data:$mime;base64,$data')");
|
197 |
}
|
198 |
+
|
199 |
return new SassString('');
|
200 |
}
|
201 |
|
257 |
if (is_object($v)) {
|
258 |
$string = (isset($v->value) ? $v->value : false);
|
259 |
} else {
|
260 |
+
$string = (string) $v;
|
261 |
}
|
262 |
if (empty($string) || $string == 'false') {
|
263 |
unset($args[$k]);
|
265 |
}
|
266 |
$list[] = $string;
|
267 |
}
|
268 |
+
|
269 |
return new SassString(implode($sep, $list));
|
270 |
}
|
271 |
|
288 |
if (isset($list[$place])) {
|
289 |
return current(SassScriptLexer::$instance->lex($list[$place], new SassContext()));
|
290 |
}
|
291 |
+
|
292 |
return new SassBoolean(false);
|
293 |
}
|
294 |
|
299 |
foreach ($args as $arg) {
|
300 |
$list = array_merge($list, self::compassList($arg));
|
301 |
}
|
302 |
+
|
303 |
return new SassString(implode(', ', $list));
|
304 |
}
|
305 |
|
307 |
{
|
308 |
$args = func_get_args();
|
309 |
$list = self::compassList($args, ',');
|
310 |
+
|
311 |
return new SassString(implode(' ', $list));
|
312 |
}
|
313 |
|
315 |
{
|
316 |
$args = func_get_args();
|
317 |
$list = self::compassList($args, ',');
|
318 |
+
|
319 |
return new SassNumber(count($list));
|
320 |
}
|
321 |
|
325 |
$end = array_pop($args);
|
326 |
$start = array_pop($args);
|
327 |
$list = self::compassList($args, ',');
|
328 |
+
|
329 |
return implode(',', array_slice($list, $start, $end));
|
330 |
}
|
331 |
|
333 |
{
|
334 |
$args = array();
|
335 |
$args[] = 'first';
|
336 |
+
|
337 |
return call_user_func_array('self::compassCompassNth', $args);
|
338 |
}
|
339 |
|
378 |
}
|
379 |
}
|
380 |
$out[] = $stack;
|
381 |
+
|
382 |
return $out;
|
383 |
}
|
384 |
|
408 |
foreach ($list as $k => $selector) {
|
409 |
$list[$k] = trim($selector) . $new;
|
410 |
}
|
411 |
+
|
412 |
return new SassString(implode(', ', $list));
|
413 |
}
|
414 |
|
428 |
$to = 6;
|
429 |
}
|
430 |
|
431 |
+
$from = (int) $from;
|
432 |
+
$to = (int) $to;
|
433 |
|
434 |
$output = array();
|
435 |
for ($i = $from; $i <= $to; $i++) {
|
436 |
$output[] = 'h' . $i;
|
437 |
}
|
438 |
+
|
439 |
return new SassString(implode(', ', $output));
|
440 |
}
|
441 |
|
474 |
|
475 |
public static function compassStylesheetUrl($path, $only_path = false)
|
476 |
{
|
|
|
477 |
return self::compassUrl($path, $only_path);
|
478 |
}
|
479 |
|
503 |
if ($only_path) {
|
504 |
return new SassString($path);
|
505 |
}
|
506 |
+
|
507 |
return new SassString("url('$path')");
|
508 |
}
|
509 |
|
512 |
$ret = '';
|
513 |
if ($from == 'top') {
|
514 |
$ret = 'bottom';
|
515 |
+
} elseif ($from == 'bottom') {
|
516 |
$ret = 'top';
|
517 |
+
} elseif ($from == 'left') {
|
518 |
$ret = 'right';
|
519 |
+
} elseif ($from == 'right') {
|
520 |
$ret = 'left';
|
521 |
+
} elseif ($from == 'center') {
|
522 |
$ret = 'center';
|
523 |
}
|
524 |
+
|
525 |
return $ret;
|
526 |
}
|
527 |
}
|
lib/phpsass/Extensions/Own/Own.php
CHANGED
@@ -84,7 +84,8 @@ class Own implements ExtensionInterface
|
|
84 |
}
|
85 |
}
|
86 |
|
87 |
-
public static function ownDemoFunction()
|
|
|
88 |
return new SassString("'This is my own Demo Function'");
|
89 |
}
|
90 |
}
|
84 |
}
|
85 |
}
|
86 |
|
87 |
+
public static function ownDemoFunction()
|
88 |
+
{
|
89 |
return new SassString("'This is my own Demo Function'");
|
90 |
}
|
91 |
}
|
lib/phpsass/Extensions/Susy/Susy.php
CHANGED
@@ -13,7 +13,6 @@ class Susy implements ExtensionInterface
|
|
13 |
|
14 |
public static function getFunctions($namespace)
|
15 |
{
|
16 |
-
|
17 |
return array();
|
18 |
}
|
19 |
|
@@ -51,6 +50,7 @@ class Susy implements ExtensionInterface
|
|
51 |
closedir($handle);
|
52 |
}
|
53 |
}
|
|
|
54 |
return $alias;
|
55 |
}
|
56 |
|
@@ -72,4 +72,4 @@ class Susy implements ExtensionInterface
|
|
72 |
return self::$filePaths[$alias];
|
73 |
}
|
74 |
}
|
75 |
-
}
|
13 |
|
14 |
public static function getFunctions($namespace)
|
15 |
{
|
|
|
16 |
return array();
|
17 |
}
|
18 |
|
50 |
closedir($handle);
|
51 |
}
|
52 |
}
|
53 |
+
|
54 |
return $alias;
|
55 |
}
|
56 |
|
72 |
return self::$filePaths[$alias];
|
73 |
}
|
74 |
}
|
75 |
+
}
|
lib/phpsass/Extensions/example.php
CHANGED
@@ -15,10 +15,10 @@ function loadCallback($file, $parser)
|
|
15 |
|
16 |
}
|
17 |
}
|
|
|
18 |
return $paths;
|
19 |
}
|
20 |
|
21 |
-
|
22 |
function getFunctions($extensions)
|
23 |
{
|
24 |
$output = array();
|
@@ -42,14 +42,12 @@ function getFunctions($extensions)
|
|
42 |
return $output;
|
43 |
}
|
44 |
|
45 |
-
|
46 |
$file = 'example.scss';
|
47 |
$path = '../';
|
48 |
$library = $path . '/SassParser.php';
|
49 |
|
50 |
if ($path && file_exists($library)) {
|
51 |
|
52 |
-
|
53 |
try {
|
54 |
require_once ($library);
|
55 |
|
@@ -82,5 +80,3 @@ if ($path && file_exists($library)) {
|
|
82 |
} else {
|
83 |
echo 'Path or library are wrong';
|
84 |
}
|
85 |
-
|
86 |
-
|
15 |
|
16 |
}
|
17 |
}
|
18 |
+
|
19 |
return $paths;
|
20 |
}
|
21 |
|
|
|
22 |
function getFunctions($extensions)
|
23 |
{
|
24 |
$output = array();
|
42 |
return $output;
|
43 |
}
|
44 |
|
|
|
45 |
$file = 'example.scss';
|
46 |
$path = '../';
|
47 |
$library = $path . '/SassParser.php';
|
48 |
|
49 |
if ($path && file_exists($library)) {
|
50 |
|
|
|
51 |
try {
|
52 |
require_once ($library);
|
53 |
|
80 |
} else {
|
81 |
echo 'Path or library are wrong';
|
82 |
}
|
|
|
|
lib/phpsass/SassException.php
CHANGED
@@ -14,14 +14,16 @@
|
|
14 |
* @package PHamlP
|
15 |
* @subpackage Sass
|
16 |
*/
|
17 |
-
class SassException extends Exception
|
|
|
18 |
/**
|
19 |
* Sass Exception.
|
20 |
* @param string Exception message
|
21 |
* @param array parameters to be applied to the message using <code>strtr</code>.
|
22 |
* @param object object with source code and meta data
|
23 |
*/
|
24 |
-
public function __construct($message, $object)
|
|
|
25 |
parent::__construct($message . (is_object($object) ? ": {$object->filename}::{$object->line}\nSource: {$object->source}" : ''));
|
26 |
}
|
27 |
-
}
|
14 |
* @package PHamlP
|
15 |
* @subpackage Sass
|
16 |
*/
|
17 |
+
class SassException extends Exception
|
18 |
+
{
|
19 |
/**
|
20 |
* Sass Exception.
|
21 |
* @param string Exception message
|
22 |
* @param array parameters to be applied to the message using <code>strtr</code>.
|
23 |
* @param object object with source code and meta data
|
24 |
*/
|
25 |
+
public function __construct($message, $object)
|
26 |
+
{
|
27 |
parent::__construct($message . (is_object($object) ? ": {$object->filename}::{$object->line}\nSource: {$object->source}" : ''));
|
28 |
}
|
29 |
+
}
|
lib/phpsass/SassFile.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass
|
17 |
*/
|
18 |
-
class SassFile
|
|
|
19 |
const CSS = 'css';
|
20 |
const SASS = 'sass';
|
21 |
const SCSS = 'scss';
|
@@ -32,7 +33,8 @@ class SassFile {
|
|
32 |
* @param SassParser Sass parser
|
33 |
* @return SassRootNode
|
34 |
*/
|
35 |
-
public static function get_tree($filename, &$parser)
|
|
|
36 |
$contents = self::get_file_contents($filename, $parser);
|
37 |
|
38 |
$options = array_merge($parser->options, array('line'=>1));
|
@@ -51,10 +53,12 @@ class SassFile {
|
|
51 |
|
52 |
$sassParser = new SassParser($options);
|
53 |
$tree = $sassParser->parse($contents, FALSE);
|
|
|
54 |
return $tree;
|
55 |
}
|
56 |
|
57 |
-
public static function get_file_contents($filename, $parser)
|
|
|
58 |
$contents = file_get_contents($filename) . "\n\n "; #add some whitespace to fix bug
|
59 |
# strip // comments at this stage, with allowances for http:// style locations.
|
60 |
$contents = preg_replace("/(^|\s)\/\/[^\n]+/", '', $contents);
|
@@ -64,12 +68,14 @@ class SassFile {
|
|
64 |
return $contents;
|
65 |
}
|
66 |
|
67 |
-
public static function resolve_paths($matches)
|
|
|
68 |
// Resolve the path into something nicer...
|
69 |
return 'url("' . self::resolve_path($matches[1]) . '")';
|
70 |
}
|
71 |
|
72 |
-
public static function resolve_path($name)
|
|
|
73 |
$path = self::$parser->basepath . self::$path;
|
74 |
$path = substr($path, 0, strrpos($path, '/')) . '/';
|
75 |
$path = $path . $name;
|
@@ -78,6 +84,7 @@ class SassFile {
|
|
78 |
$last = $path;
|
79 |
$path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
|
80 |
}
|
|
|
81 |
return $path;
|
82 |
}
|
83 |
|
@@ -90,18 +97,20 @@ class SassFile {
|
|
90 |
* @param SassParser Sass parser
|
91 |
* @return array of string path(s) to file(s) or FALSE if no such file
|
92 |
*/
|
93 |
-
public static function get_file($filename, &$parser, $sass_only = TRUE)
|
|
|
94 |
$ext = substr($filename, strrpos($filename, '.') + 1);
|
95 |
// if the last char isn't *, and it's not (.sass|.scss|.css)
|
96 |
if ($sass_only && substr($filename, -1) != '*' && $ext !== self::SASS && $ext !== self::SCSS && $ext !== self::CSS) {
|
97 |
$sass = self::get_file($filename . '.' . self::SASS, $parser);
|
|
|
98 |
return $sass ? $sass : self::get_file($filename . '.' . self::SCSS, $parser);
|
99 |
}
|
100 |
if (file_exists($filename)) {
|
101 |
return array($filename);
|
102 |
}
|
103 |
$paths = $parser->load_paths;
|
104 |
-
if(is_string($parser->filename) && $path = dirname($parser->filename)) {
|
105 |
$paths[] = $path;
|
106 |
if (!in_array($path, $parser->load_paths)) {
|
107 |
$parser->load_paths[] = $path;
|
@@ -118,6 +127,7 @@ class SassFile {
|
|
118 |
return $paths;
|
119 |
}
|
120 |
}
|
|
|
121 |
return FALSE;
|
122 |
}
|
123 |
|
@@ -128,7 +138,8 @@ class SassFile {
|
|
128 |
* @param string path to directory to look in and under
|
129 |
* @return mixed string: full path to file if found, false if not
|
130 |
*/
|
131 |
-
public static function find_file($filename, $dir)
|
|
|
132 |
$partialname = dirname($filename).DIRECTORY_SEPARATOR.'_'.basename($filename);
|
133 |
|
134 |
foreach (array($filename, $partialname) as $file) {
|
@@ -149,6 +160,7 @@ class SassFile {
|
|
149 |
}
|
150 |
}
|
151 |
}
|
|
|
152 |
return false;
|
153 |
}
|
154 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass
|
17 |
*/
|
18 |
+
class SassFile
|
19 |
+
{
|
20 |
const CSS = 'css';
|
21 |
const SASS = 'sass';
|
22 |
const SCSS = 'scss';
|
33 |
* @param SassParser Sass parser
|
34 |
* @return SassRootNode
|
35 |
*/
|
36 |
+
public static function get_tree($filename, &$parser)
|
37 |
+
{
|
38 |
$contents = self::get_file_contents($filename, $parser);
|
39 |
|
40 |
$options = array_merge($parser->options, array('line'=>1));
|
53 |
|
54 |
$sassParser = new SassParser($options);
|
55 |
$tree = $sassParser->parse($contents, FALSE);
|
56 |
+
|
57 |
return $tree;
|
58 |
}
|
59 |
|
60 |
+
public static function get_file_contents($filename, $parser)
|
61 |
+
{
|
62 |
$contents = file_get_contents($filename) . "\n\n "; #add some whitespace to fix bug
|
63 |
# strip // comments at this stage, with allowances for http:// style locations.
|
64 |
$contents = preg_replace("/(^|\s)\/\/[^\n]+/", '', $contents);
|
68 |
return $contents;
|
69 |
}
|
70 |
|
71 |
+
public static function resolve_paths($matches)
|
72 |
+
{
|
73 |
// Resolve the path into something nicer...
|
74 |
return 'url("' . self::resolve_path($matches[1]) . '")';
|
75 |
}
|
76 |
|
77 |
+
public static function resolve_path($name)
|
78 |
+
{
|
79 |
$path = self::$parser->basepath . self::$path;
|
80 |
$path = substr($path, 0, strrpos($path, '/')) . '/';
|
81 |
$path = $path . $name;
|
84 |
$last = $path;
|
85 |
$path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
|
86 |
}
|
87 |
+
|
88 |
return $path;
|
89 |
}
|
90 |
|
97 |
* @param SassParser Sass parser
|
98 |
* @return array of string path(s) to file(s) or FALSE if no such file
|
99 |
*/
|
100 |
+
public static function get_file($filename, &$parser, $sass_only = TRUE)
|
101 |
+
{
|
102 |
$ext = substr($filename, strrpos($filename, '.') + 1);
|
103 |
// if the last char isn't *, and it's not (.sass|.scss|.css)
|
104 |
if ($sass_only && substr($filename, -1) != '*' && $ext !== self::SASS && $ext !== self::SCSS && $ext !== self::CSS) {
|
105 |
$sass = self::get_file($filename . '.' . self::SASS, $parser);
|
106 |
+
|
107 |
return $sass ? $sass : self::get_file($filename . '.' . self::SCSS, $parser);
|
108 |
}
|
109 |
if (file_exists($filename)) {
|
110 |
return array($filename);
|
111 |
}
|
112 |
$paths = $parser->load_paths;
|
113 |
+
if (is_string($parser->filename) && $path = dirname($parser->filename)) {
|
114 |
$paths[] = $path;
|
115 |
if (!in_array($path, $parser->load_paths)) {
|
116 |
$parser->load_paths[] = $path;
|
127 |
return $paths;
|
128 |
}
|
129 |
}
|
130 |
+
|
131 |
return FALSE;
|
132 |
}
|
133 |
|
138 |
* @param string path to directory to look in and under
|
139 |
* @return mixed string: full path to file if found, false if not
|
140 |
*/
|
141 |
+
public static function find_file($filename, $dir)
|
142 |
+
{
|
143 |
$partialname = dirname($filename).DIRECTORY_SEPARATOR.'_'.basename($filename);
|
144 |
|
145 |
foreach (array($filename, $partialname) as $file) {
|
160 |
}
|
161 |
}
|
162 |
}
|
163 |
+
|
164 |
return false;
|
165 |
}
|
166 |
}
|
lib/phpsass/SassParser.php
CHANGED
@@ -22,9 +22,9 @@
|
|
22 |
* @subpackage Sass
|
23 |
*/
|
24 |
|
25 |
-
require_once
|
26 |
-
require_once
|
27 |
-
require_once
|
28 |
|
29 |
/**
|
30 |
* SassParser class.
|
@@ -32,7 +32,8 @@ require_once('tree/SassNode.php');
|
|
32 |
* @package PHamlP
|
33 |
* @subpackage Sass
|
34 |
*/
|
35 |
-
class SassParser
|
|
|
36 |
/**#@+
|
37 |
* Default option values
|
38 |
*/
|
@@ -51,7 +52,7 @@ class SassParser {
|
|
51 |
/**
|
52 |
* Static holder for last instance of a SassParser
|
53 |
*/
|
54 |
-
static
|
55 |
|
56 |
/**
|
57 |
* @var string the character used for indenting
|
@@ -80,7 +81,6 @@ class SassParser {
|
|
80 |
|
81 |
public $basepath;
|
82 |
|
83 |
-
|
84 |
/**
|
85 |
* debug_info:
|
86 |
* @var boolean When true the line number and file where a selector is defined
|
@@ -220,7 +220,8 @@ class SassParser {
|
|
220 |
* @param array $options
|
221 |
* @return SassParser
|
222 |
*/
|
223 |
-
public function __construct($options = array())
|
|
|
224 |
if (!is_array($options)) {
|
225 |
if (isset($options['debug']) && $options['debug']) {
|
226 |
throw new SassException('Options must be an array');
|
@@ -282,7 +283,8 @@ class SassParser {
|
|
282 |
* @param string name of property to get
|
283 |
* @return mixed return value of getter function
|
284 |
*/
|
285 |
-
public function __get($name)
|
|
|
286 |
$getter = 'get' . ucfirst($name);
|
287 |
if (method_exists($this, $getter)) {
|
288 |
return $this->$getter();
|
@@ -295,70 +297,86 @@ class SassParser {
|
|
295 |
}
|
296 |
}
|
297 |
|
298 |
-
public function getBasepath()
|
|
|
299 |
return $this->basepath;
|
300 |
}
|
301 |
|
302 |
-
public function getDebug_info()
|
|
|
303 |
return $this->debug_info;
|
304 |
}
|
305 |
|
306 |
-
public function getFilename()
|
|
|
307 |
return $this->filename;
|
308 |
}
|
309 |
|
310 |
-
public function getLine()
|
|
|
311 |
return $this->line;
|
312 |
}
|
313 |
|
314 |
-
public function getSource()
|
|
|
315 |
return $this->source;
|
316 |
}
|
317 |
|
318 |
-
public function getLine_numbers()
|
|
|
319 |
return $this->line_numbers;
|
320 |
}
|
321 |
|
322 |
-
public function getFunctions()
|
|
|
323 |
return self::$functions;
|
324 |
}
|
325 |
|
326 |
-
public function getLoad_paths()
|
|
|
327 |
return $this->load_paths;
|
328 |
}
|
329 |
|
330 |
-
public function getLoad_path_functions()
|
|
|
331 |
return $this->load_path_functions;
|
332 |
}
|
333 |
|
334 |
-
public function getProperty_syntax()
|
|
|
335 |
return $this->property_syntax;
|
336 |
}
|
337 |
|
338 |
-
public function getQuiet()
|
|
|
339 |
return $this->quiet;
|
340 |
}
|
341 |
|
342 |
-
public function getStyle()
|
|
|
343 |
return $this->style;
|
344 |
}
|
345 |
|
346 |
-
public function getSyntax()
|
|
|
347 |
return $this->syntax;
|
348 |
}
|
349 |
|
350 |
-
public function getDebug()
|
|
|
351 |
return $this->debug;
|
352 |
}
|
353 |
|
354 |
-
public function getCallbacks()
|
|
|
355 |
return $this->callbacks + array(
|
356 |
'warn' => NULL,
|
357 |
'debug' => NULL,
|
358 |
);
|
359 |
}
|
360 |
|
361 |
-
public function getOptions()
|
|
|
362 |
return array(
|
363 |
'callbacks' => $this->callbacks,
|
364 |
// 'debug' => $this->debug,
|
@@ -380,7 +398,8 @@ class SassParser {
|
|
380 |
* @param string name of source file or Sass source
|
381 |
* @return string CSS
|
382 |
*/
|
383 |
-
public function toCss($source, $isFile = true)
|
|
|
384 |
return $this->parse($source, $isFile)->render();
|
385 |
}
|
386 |
|
@@ -392,7 +411,8 @@ class SassParser {
|
|
392 |
* @param string name of source file or Sass source
|
393 |
* @return SassRootNode Root node of document tree
|
394 |
*/
|
395 |
-
public function parse($source, $isFile = true)
|
|
|
396 |
# Richard Lyon - 2011-10-25 - ignore unfound files
|
397 |
# Richard Lyon - 2011-10-25 - add multiple files to load functions
|
398 |
if (!$source) {
|
@@ -402,22 +422,23 @@ class SassParser {
|
|
402 |
if (is_array($source)) {
|
403 |
$return = null;
|
404 |
foreach ($source as $key => $value) {
|
405 |
-
if(is_numeric($key)){
|
406 |
$code = $value;
|
407 |
$type = true;
|
408 |
} else {
|
409 |
$code = $key;
|
410 |
$type = $value;
|
411 |
}
|
412 |
-
if($return===null){
|
413 |
$return = $this->parse($code, $type);
|
414 |
} else {
|
415 |
$newNode = $this->parse($code, $type);
|
416 |
-
foreach($newNode->children as $children){
|
417 |
array_push($return->children, $children);
|
418 |
}
|
419 |
}
|
420 |
}
|
|
|
421 |
return $return;
|
422 |
}
|
423 |
|
@@ -426,9 +447,9 @@ class SassParser {
|
|
426 |
foreach ($files as $file) {
|
427 |
$this->filename = $file;
|
428 |
$this->syntax = substr(strrchr($file, '.'), 1);
|
429 |
-
if($this->syntax == SassFile::CSS){
|
430 |
$this->property_syntax = "css";
|
431 |
-
}elseif (!$this->property_syntax && $this->syntax == SassFile::SCSS) {
|
432 |
$this->property_syntax = "scss";
|
433 |
}
|
434 |
|
@@ -436,13 +457,14 @@ class SassParser {
|
|
436 |
if ($this->debug) {
|
437 |
throw new SassException('Invalid {what}', array('{what}' => 'syntax option'));
|
438 |
}
|
|
|
439 |
return FALSE;
|
440 |
}
|
441 |
$files_source .= SassFile::get_file_contents($this->filename, $this);
|
442 |
}
|
|
|
443 |
return $this->toTree($files_source);
|
444 |
-
}
|
445 |
-
else {
|
446 |
return $this->toTree($source);
|
447 |
}
|
448 |
}
|
@@ -453,18 +475,19 @@ class SassParser {
|
|
453 |
* @param string Sass source
|
454 |
* @return SassRootNode the root of this document tree
|
455 |
*/
|
456 |
-
public function toTree($source)
|
|
|
457 |
if ($this->syntax === SassFile::SASS) {
|
458 |
$source = str_replace(array("\r\n", "\n\r", "\r"), "\n", $source);
|
459 |
$this->source = explode("\n", $source);
|
460 |
$this->setIndentChar();
|
461 |
-
}
|
462 |
-
else {
|
463 |
$this->source = $source;
|
464 |
}
|
465 |
unset($source);
|
466 |
$root = new SassRootNode($this);
|
467 |
$this->buildTree($root);
|
|
|
468 |
return $root;
|
469 |
}
|
470 |
|
@@ -473,12 +496,14 @@ class SassParser {
|
|
473 |
* Called recursivly until the source is parsed.
|
474 |
* @param SassNode the node
|
475 |
*/
|
476 |
-
public function buildTree($parent)
|
|
|
477 |
$node = $this->getNode($parent);
|
478 |
while (is_object($node) && $node->isChildOf($parent)) {
|
479 |
$parent->addChild($node);
|
480 |
$node = $this->buildTree($node);
|
481 |
}
|
|
|
482 |
return $node;
|
483 |
}
|
484 |
|
@@ -488,7 +513,8 @@ class SassParser {
|
|
488 |
* @return SassNode a SassNode of the appropriate type. Null when no more
|
489 |
* source to parse.
|
490 |
*/
|
491 |
-
public function getNode($node)
|
|
|
492 |
$token = $this->getToken();
|
493 |
if (empty($token)) return null;
|
494 |
switch (true) {
|
@@ -507,9 +533,9 @@ class SassParser {
|
|
507 |
if ($this->debug) {
|
508 |
throw new SassException('Mixin definition shortcut not allowed in SCSS', $this);
|
509 |
}
|
|
|
510 |
return;
|
511 |
-
}
|
512 |
-
else {
|
513 |
return new SassMixinDefinitionNode($token);
|
514 |
}
|
515 |
case SassMixinNode::isa($token):
|
@@ -517,9 +543,9 @@ class SassParser {
|
|
517 |
if ($this->debug) {
|
518 |
throw new SassException('Mixin include shortcut not allowed in SCSS', $this);
|
519 |
}
|
|
|
520 |
return;
|
521 |
-
}
|
522 |
-
else {
|
523 |
return new SassMixinNode($token);
|
524 |
}
|
525 |
default:
|
@@ -533,7 +559,8 @@ class SassParser {
|
|
533 |
* meta data about it.
|
534 |
* @return object
|
535 |
*/
|
536 |
-
public function getToken()
|
|
|
537 |
return ($this->syntax === SassFile::SASS ? $this->sass2Token() : $this->scss2Token());
|
538 |
}
|
539 |
|
@@ -544,7 +571,8 @@ class SassParser {
|
|
544 |
* CSS comments and selectors, are assembled into a single statement.
|
545 |
* @return object Statement token. Null if end of source.
|
546 |
*/
|
547 |
-
public function sass2Token()
|
|
|
548 |
$statement = ''; // source line being tokenised
|
549 |
$token = null;
|
550 |
|
@@ -566,7 +594,7 @@ class SassParser {
|
|
566 |
// Consume Sass comments
|
567 |
if (substr($statement, 0, strlen(self::BEGIN_SASS_COMMENT)) === self::BEGIN_SASS_COMMENT) {
|
568 |
unset($statement);
|
569 |
-
while($this->getLevel($this->source[0]) > $level) {
|
570 |
array_shift($this->source);
|
571 |
$this->line++;
|
572 |
}
|
@@ -575,12 +603,11 @@ class SassParser {
|
|
575 |
// Build CSS comments
|
576 |
elseif (substr($statement, 0, strlen(self::BEGIN_CSS_COMMENT))
|
577 |
=== self::BEGIN_CSS_COMMENT) {
|
578 |
-
while($this->getLevel($this->source[0]) > $level) {
|
579 |
$statement .= "\n" . ltrim(array_shift($this->source));
|
580 |
$this->line++;
|
581 |
}
|
582 |
-
}
|
583 |
-
else {
|
584 |
$this->source = $statement;
|
585 |
|
586 |
if ($this->debug) {
|
@@ -591,7 +618,7 @@ class SassParser {
|
|
591 |
// Selector statements can span multiple lines
|
592 |
elseif (substr($statement, -1) === SassRuleNode::CONTINUED) {
|
593 |
// Build the selector statement
|
594 |
-
while($this->getLevel($this->source[0]) === $level) {
|
595 |
$statement .= ltrim(array_shift($this->source));
|
596 |
$this->line++;
|
597 |
}
|
@@ -604,6 +631,7 @@ class SassParser {
|
|
604 |
'line' => $this->line - 1,
|
605 |
);
|
606 |
}
|
|
|
607 |
return $token;
|
608 |
}
|
609 |
|
@@ -614,7 +642,8 @@ class SassParser {
|
|
614 |
* @return integer the level of the source
|
615 |
* @throws Exception if the source indentation is invalid
|
616 |
*/
|
617 |
-
public function getLevel($source)
|
|
|
618 |
$indent = strlen($source) - strlen(ltrim($source));
|
619 |
$level = $indent/$this->indentSpaces;
|
620 |
if (is_float($level)) {
|
@@ -625,11 +654,11 @@ class SassParser {
|
|
625 |
|
626 |
if ($this->debug) {
|
627 |
throw new SassException('Invalid indentation', $this);
|
628 |
-
}
|
629 |
-
else {
|
630 |
return 0;
|
631 |
}
|
632 |
}
|
|
|
633 |
return $level;
|
634 |
}
|
635 |
|
@@ -638,7 +667,8 @@ class SassParser {
|
|
638 |
* about it from SCSS source.
|
639 |
* @return object Statement token. Null if end of source.
|
640 |
*/
|
641 |
-
public function scss2Token()
|
|
|
642 |
static $srcpos = 0; // current position in the source stream
|
643 |
static $srclen; // the length of the source stream
|
644 |
|
@@ -661,8 +691,7 @@ class SassParser {
|
|
661 |
));
|
662 |
}
|
663 |
$statement .= "\n";
|
664 |
-
}
|
665 |
-
elseif (substr($this->source, $srcpos-1, strlen(self::BEGIN_CSS_COMMENT)) === self::BEGIN_CSS_COMMENT) {
|
666 |
if (ltrim($statement)) {
|
667 |
if ($this->debug) {
|
668 |
throw new SassException('Invalid comment', (object) array(
|
@@ -678,8 +707,7 @@ class SassParser {
|
|
678 |
}
|
679 |
$srcpos += strlen(self::END_CSS_COMMENT);
|
680 |
$token = $this->createToken($statement.self::END_CSS_COMMENT);
|
681 |
-
}
|
682 |
-
else {
|
683 |
$statement .= $c;
|
684 |
}
|
685 |
break;
|
@@ -730,7 +758,8 @@ class SassParser {
|
|
730 |
* @param string source statement
|
731 |
* @return SassToken
|
732 |
*/
|
733 |
-
public function createToken($statement)
|
|
|
734 |
static $level = 0;
|
735 |
|
736 |
$this->line += substr_count($statement, "\n");
|
@@ -749,6 +778,7 @@ class SassParser {
|
|
749 |
'line' => $this->line,
|
750 |
) : null);
|
751 |
$level += ($last === self::BEGIN_BLOCK ? 1 : ($last === self::END_BLOCK ? -1 : 0));
|
|
|
752 |
return $token;
|
753 |
}
|
754 |
|
@@ -758,7 +788,8 @@ class SassParser {
|
|
758 |
* @param SassNode parent node
|
759 |
* @return SassNode a Sass directive node
|
760 |
*/
|
761 |
-
public function parseDirective($token, $parent)
|
|
|
762 |
switch (SassDirectiveNode::extractDirective($token)) {
|
763 |
case '@content':
|
764 |
return new SassContentNode($token);
|
@@ -794,6 +825,7 @@ class SassParser {
|
|
794 |
}
|
795 |
}
|
796 |
}
|
|
|
797 |
return new SassImportNode($token, $parent);
|
798 |
break;
|
799 |
case '@each':
|
@@ -806,6 +838,7 @@ class SassParser {
|
|
806 |
return new SassIfNode($token);
|
807 |
break;
|
808 |
case '@else': // handles else and else if directives
|
|
|
809 |
return new SassElseNode($token);
|
810 |
break;
|
811 |
case '@do':
|
@@ -833,7 +866,8 @@ class SassParser {
|
|
833 |
* @throws SassException if the indent is mixed or
|
834 |
* the indent character can not be determined
|
835 |
*/
|
836 |
-
public function setIndentChar()
|
|
|
837 |
foreach ($this->source as $l=>$source) {
|
838 |
if (!empty($source) && in_array($source[0], $this->indentChars)) {
|
839 |
$this->indentChar = $source[0];
|
@@ -846,6 +880,7 @@ class SassParser {
|
|
846 |
}
|
847 |
}
|
848 |
$this->indentSpaces = ($this->indentChar == ' ' ? $i : 1);
|
|
|
849 |
return;
|
850 |
}
|
851 |
} // foreach
|
22 |
* @subpackage Sass
|
23 |
*/
|
24 |
|
25 |
+
require_once 'SassFile.php';
|
26 |
+
require_once 'SassException.php';
|
27 |
+
require_once 'tree/SassNode.php';
|
28 |
|
29 |
/**
|
30 |
* SassParser class.
|
32 |
* @package PHamlP
|
33 |
* @subpackage Sass
|
34 |
*/
|
35 |
+
class SassParser
|
36 |
+
{
|
37 |
/**#@+
|
38 |
* Default option values
|
39 |
*/
|
52 |
/**
|
53 |
* Static holder for last instance of a SassParser
|
54 |
*/
|
55 |
+
public static $instance;
|
56 |
|
57 |
/**
|
58 |
* @var string the character used for indenting
|
81 |
|
82 |
public $basepath;
|
83 |
|
|
|
84 |
/**
|
85 |
* debug_info:
|
86 |
* @var boolean When true the line number and file where a selector is defined
|
220 |
* @param array $options
|
221 |
* @return SassParser
|
222 |
*/
|
223 |
+
public function __construct($options = array())
|
224 |
+
{
|
225 |
if (!is_array($options)) {
|
226 |
if (isset($options['debug']) && $options['debug']) {
|
227 |
throw new SassException('Options must be an array');
|
283 |
* @param string name of property to get
|
284 |
* @return mixed return value of getter function
|
285 |
*/
|
286 |
+
public function __get($name)
|
287 |
+
{
|
288 |
$getter = 'get' . ucfirst($name);
|
289 |
if (method_exists($this, $getter)) {
|
290 |
return $this->$getter();
|
297 |
}
|
298 |
}
|
299 |
|
300 |
+
public function getBasepath()
|
301 |
+
{
|
302 |
return $this->basepath;
|
303 |
}
|
304 |
|
305 |
+
public function getDebug_info()
|
306 |
+
{
|
307 |
return $this->debug_info;
|
308 |
}
|
309 |
|
310 |
+
public function getFilename()
|
311 |
+
{
|
312 |
return $this->filename;
|
313 |
}
|
314 |
|
315 |
+
public function getLine()
|
316 |
+
{
|
317 |
return $this->line;
|
318 |
}
|
319 |
|
320 |
+
public function getSource()
|
321 |
+
{
|
322 |
return $this->source;
|
323 |
}
|
324 |
|
325 |
+
public function getLine_numbers()
|
326 |
+
{
|
327 |
return $this->line_numbers;
|
328 |
}
|
329 |
|
330 |
+
public function getFunctions()
|
331 |
+
{
|
332 |
return self::$functions;
|
333 |
}
|
334 |
|
335 |
+
public function getLoad_paths()
|
336 |
+
{
|
337 |
return $this->load_paths;
|
338 |
}
|
339 |
|
340 |
+
public function getLoad_path_functions()
|
341 |
+
{
|
342 |
return $this->load_path_functions;
|
343 |
}
|
344 |
|
345 |
+
public function getProperty_syntax()
|
346 |
+
{
|
347 |
return $this->property_syntax;
|
348 |
}
|
349 |
|
350 |
+
public function getQuiet()
|
351 |
+
{
|
352 |
return $this->quiet;
|
353 |
}
|
354 |
|
355 |
+
public function getStyle()
|
356 |
+
{
|
357 |
return $this->style;
|
358 |
}
|
359 |
|
360 |
+
public function getSyntax()
|
361 |
+
{
|
362 |
return $this->syntax;
|
363 |
}
|
364 |
|
365 |
+
public function getDebug()
|
366 |
+
{
|
367 |
return $this->debug;
|
368 |
}
|
369 |
|
370 |
+
public function getCallbacks()
|
371 |
+
{
|
372 |
return $this->callbacks + array(
|
373 |
'warn' => NULL,
|
374 |
'debug' => NULL,
|
375 |
);
|
376 |
}
|
377 |
|
378 |
+
public function getOptions()
|
379 |
+
{
|
380 |
return array(
|
381 |
'callbacks' => $this->callbacks,
|
382 |
// 'debug' => $this->debug,
|
398 |
* @param string name of source file or Sass source
|
399 |
* @return string CSS
|
400 |
*/
|
401 |
+
public function toCss($source, $isFile = true)
|
402 |
+
{
|
403 |
return $this->parse($source, $isFile)->render();
|
404 |
}
|
405 |
|
411 |
* @param string name of source file or Sass source
|
412 |
* @return SassRootNode Root node of document tree
|
413 |
*/
|
414 |
+
public function parse($source, $isFile = true)
|
415 |
+
{
|
416 |
# Richard Lyon - 2011-10-25 - ignore unfound files
|
417 |
# Richard Lyon - 2011-10-25 - add multiple files to load functions
|
418 |
if (!$source) {
|
422 |
if (is_array($source)) {
|
423 |
$return = null;
|
424 |
foreach ($source as $key => $value) {
|
425 |
+
if (is_numeric($key)) {
|
426 |
$code = $value;
|
427 |
$type = true;
|
428 |
} else {
|
429 |
$code = $key;
|
430 |
$type = $value;
|
431 |
}
|
432 |
+
if ($return===null) {
|
433 |
$return = $this->parse($code, $type);
|
434 |
} else {
|
435 |
$newNode = $this->parse($code, $type);
|
436 |
+
foreach ($newNode->children as $children) {
|
437 |
array_push($return->children, $children);
|
438 |
}
|
439 |
}
|
440 |
}
|
441 |
+
|
442 |
return $return;
|
443 |
}
|
444 |
|
447 |
foreach ($files as $file) {
|
448 |
$this->filename = $file;
|
449 |
$this->syntax = substr(strrchr($file, '.'), 1);
|
450 |
+
if ($this->syntax == SassFile::CSS) {
|
451 |
$this->property_syntax = "css";
|
452 |
+
} elseif (!$this->property_syntax && $this->syntax == SassFile::SCSS) {
|
453 |
$this->property_syntax = "scss";
|
454 |
}
|
455 |
|
457 |
if ($this->debug) {
|
458 |
throw new SassException('Invalid {what}', array('{what}' => 'syntax option'));
|
459 |
}
|
460 |
+
|
461 |
return FALSE;
|
462 |
}
|
463 |
$files_source .= SassFile::get_file_contents($this->filename, $this);
|
464 |
}
|
465 |
+
|
466 |
return $this->toTree($files_source);
|
467 |
+
} else {
|
|
|
468 |
return $this->toTree($source);
|
469 |
}
|
470 |
}
|
475 |
* @param string Sass source
|
476 |
* @return SassRootNode the root of this document tree
|
477 |
*/
|
478 |
+
public function toTree($source)
|
479 |
+
{
|
480 |
if ($this->syntax === SassFile::SASS) {
|
481 |
$source = str_replace(array("\r\n", "\n\r", "\r"), "\n", $source);
|
482 |
$this->source = explode("\n", $source);
|
483 |
$this->setIndentChar();
|
484 |
+
} else {
|
|
|
485 |
$this->source = $source;
|
486 |
}
|
487 |
unset($source);
|
488 |
$root = new SassRootNode($this);
|
489 |
$this->buildTree($root);
|
490 |
+
|
491 |
return $root;
|
492 |
}
|
493 |
|
496 |
* Called recursivly until the source is parsed.
|
497 |
* @param SassNode the node
|
498 |
*/
|
499 |
+
public function buildTree($parent)
|
500 |
+
{
|
501 |
$node = $this->getNode($parent);
|
502 |
while (is_object($node) && $node->isChildOf($parent)) {
|
503 |
$parent->addChild($node);
|
504 |
$node = $this->buildTree($node);
|
505 |
}
|
506 |
+
|
507 |
return $node;
|
508 |
}
|
509 |
|
513 |
* @return SassNode a SassNode of the appropriate type. Null when no more
|
514 |
* source to parse.
|
515 |
*/
|
516 |
+
public function getNode($node)
|
517 |
+
{
|
518 |
$token = $this->getToken();
|
519 |
if (empty($token)) return null;
|
520 |
switch (true) {
|
533 |
if ($this->debug) {
|
534 |
throw new SassException('Mixin definition shortcut not allowed in SCSS', $this);
|
535 |
}
|
536 |
+
|
537 |
return;
|
538 |
+
} else {
|
|
|
539 |
return new SassMixinDefinitionNode($token);
|
540 |
}
|
541 |
case SassMixinNode::isa($token):
|
543 |
if ($this->debug) {
|
544 |
throw new SassException('Mixin include shortcut not allowed in SCSS', $this);
|
545 |
}
|
546 |
+
|
547 |
return;
|
548 |
+
} else {
|
|
|
549 |
return new SassMixinNode($token);
|
550 |
}
|
551 |
default:
|
559 |
* meta data about it.
|
560 |
* @return object
|
561 |
*/
|
562 |
+
public function getToken()
|
563 |
+
{
|
564 |
return ($this->syntax === SassFile::SASS ? $this->sass2Token() : $this->scss2Token());
|
565 |
}
|
566 |
|
571 |
* CSS comments and selectors, are assembled into a single statement.
|
572 |
* @return object Statement token. Null if end of source.
|
573 |
*/
|
574 |
+
public function sass2Token()
|
575 |
+
{
|
576 |
$statement = ''; // source line being tokenised
|
577 |
$token = null;
|
578 |
|
594 |
// Consume Sass comments
|
595 |
if (substr($statement, 0, strlen(self::BEGIN_SASS_COMMENT)) === self::BEGIN_SASS_COMMENT) {
|
596 |
unset($statement);
|
597 |
+
while ($this->getLevel($this->source[0]) > $level) {
|
598 |
array_shift($this->source);
|
599 |
$this->line++;
|
600 |
}
|
603 |
// Build CSS comments
|
604 |
elseif (substr($statement, 0, strlen(self::BEGIN_CSS_COMMENT))
|
605 |
=== self::BEGIN_CSS_COMMENT) {
|
606 |
+
while ($this->getLevel($this->source[0]) > $level) {
|
607 |
$statement .= "\n" . ltrim(array_shift($this->source));
|
608 |
$this->line++;
|
609 |
}
|
610 |
+
} else {
|
|
|
611 |
$this->source = $statement;
|
612 |
|
613 |
if ($this->debug) {
|
618 |
// Selector statements can span multiple lines
|
619 |
elseif (substr($statement, -1) === SassRuleNode::CONTINUED) {
|
620 |
// Build the selector statement
|
621 |
+
while ($this->getLevel($this->source[0]) === $level) {
|
622 |
$statement .= ltrim(array_shift($this->source));
|
623 |
$this->line++;
|
624 |
}
|
631 |
'line' => $this->line - 1,
|
632 |
);
|
633 |
}
|
634 |
+
|
635 |
return $token;
|
636 |
}
|
637 |
|
642 |
* @return integer the level of the source
|
643 |
* @throws Exception if the source indentation is invalid
|
644 |
*/
|
645 |
+
public function getLevel($source)
|
646 |
+
{
|
647 |
$indent = strlen($source) - strlen(ltrim($source));
|
648 |
$level = $indent/$this->indentSpaces;
|
649 |
if (is_float($level)) {
|
654 |
|
655 |
if ($this->debug) {
|
656 |
throw new SassException('Invalid indentation', $this);
|
657 |
+
} else {
|
|
|
658 |
return 0;
|
659 |
}
|
660 |
}
|
661 |
+
|
662 |
return $level;
|
663 |
}
|
664 |
|
667 |
* about it from SCSS source.
|
668 |
* @return object Statement token. Null if end of source.
|
669 |
*/
|
670 |
+
public function scss2Token()
|
671 |
+
{
|
672 |
static $srcpos = 0; // current position in the source stream
|
673 |
static $srclen; // the length of the source stream
|
674 |
|
691 |
));
|
692 |
}
|
693 |
$statement .= "\n";
|
694 |
+
} elseif (substr($this->source, $srcpos-1, strlen(self::BEGIN_CSS_COMMENT)) === self::BEGIN_CSS_COMMENT) {
|
|
|
695 |
if (ltrim($statement)) {
|
696 |
if ($this->debug) {
|
697 |
throw new SassException('Invalid comment', (object) array(
|
707 |
}
|
708 |
$srcpos += strlen(self::END_CSS_COMMENT);
|
709 |
$token = $this->createToken($statement.self::END_CSS_COMMENT);
|
710 |
+
} else {
|
|
|
711 |
$statement .= $c;
|
712 |
}
|
713 |
break;
|
758 |
* @param string source statement
|
759 |
* @return SassToken
|
760 |
*/
|
761 |
+
public function createToken($statement)
|
762 |
+
{
|
763 |
static $level = 0;
|
764 |
|
765 |
$this->line += substr_count($statement, "\n");
|
778 |
'line' => $this->line,
|
779 |
) : null);
|
780 |
$level += ($last === self::BEGIN_BLOCK ? 1 : ($last === self::END_BLOCK ? -1 : 0));
|
781 |
+
|
782 |
return $token;
|
783 |
}
|
784 |
|
788 |
* @param SassNode parent node
|
789 |
* @return SassNode a Sass directive node
|
790 |
*/
|
791 |
+
public function parseDirective($token, $parent)
|
792 |
+
{
|
793 |
switch (SassDirectiveNode::extractDirective($token)) {
|
794 |
case '@content':
|
795 |
return new SassContentNode($token);
|
825 |
}
|
826 |
}
|
827 |
}
|
828 |
+
|
829 |
return new SassImportNode($token, $parent);
|
830 |
break;
|
831 |
case '@each':
|
838 |
return new SassIfNode($token);
|
839 |
break;
|
840 |
case '@else': // handles else and else if directives
|
841 |
+
|
842 |
return new SassElseNode($token);
|
843 |
break;
|
844 |
case '@do':
|
866 |
* @throws SassException if the indent is mixed or
|
867 |
* the indent character can not be determined
|
868 |
*/
|
869 |
+
public function setIndentChar()
|
870 |
+
{
|
871 |
foreach ($this->source as $l=>$source) {
|
872 |
if (!empty($source) && in_array($source[0], $this->indentChars)) {
|
873 |
$this->indentChar = $source[0];
|
880 |
}
|
881 |
}
|
882 |
$this->indentSpaces = ($this->indentChar == ' ' ? $i : 1);
|
883 |
+
|
884 |
return;
|
885 |
}
|
886 |
} // foreach
|
lib/phpsass/VERSION
CHANGED
@@ -1,3 +1,5 @@
|
|
|
|
|
|
1 |
Version 201306071300 - Version bump to reflect multiple merged pull requests
|
2 |
Version 201304222300 - Version bump to reflect multiple merged pull requests
|
3 |
Version 201211282000 - Version bump to reflect multiple pull requests being merged over time.
|
1 |
+
Version 201206271500 - Verbump, merge pr #119
|
2 |
+
Version 201206181400 - Run PHP-CS-Fixer on all files to fix coding style
|
3 |
Version 201306071300 - Version bump to reflect multiple merged pull requests
|
4 |
Version 201304222300 - Version bump to reflect multiple merged pull requests
|
5 |
Version 201211282000 - Version bump to reflect multiple pull requests being merged over time.
|
lib/phpsass/renderers/SassCompactRenderer.php
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassCompactRenderer class.
|
@@ -19,7 +19,8 @@ require_once('SassCompressedRenderer.php');
|
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.renderers
|
21 |
*/
|
22 |
-
class SassCompactRenderer extends SassCompressedRenderer
|
|
|
23 |
const DEBUG_INFO_RULE = '@media -sass-debug-info';
|
24 |
const DEBUG_INFO_PROPERTY = 'font-family';
|
25 |
|
@@ -27,7 +28,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
27 |
* Renders the brace between the selectors and the properties
|
28 |
* @return string the brace between the selectors and the properties
|
29 |
*/
|
30 |
-
protected function between()
|
|
|
31 |
return ' { ';
|
32 |
}
|
33 |
|
@@ -35,7 +37,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
35 |
* Renders the brace at the end of the rule
|
36 |
* @return string the brace between the rule and its properties
|
37 |
*/
|
38 |
-
protected function end()
|
|
|
39 |
return " }\n";
|
40 |
}
|
41 |
|
@@ -46,8 +49,10 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
46 |
* @param SassNode the node being rendered
|
47 |
* @return string the rendered commnt
|
48 |
*/
|
49 |
-
public function renderComment($node)
|
|
|
50 |
$nl = ($node->parent instanceof SassRuleNode?'':"\n");
|
|
|
51 |
return "$nl/* " . join("\n * ", $node->children) . " */$nl" ;
|
52 |
}
|
53 |
|
@@ -57,7 +62,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
57 |
* @param array properties of the directive
|
58 |
* @return string the rendered directive
|
59 |
*/
|
60 |
-
public function renderDirective($node, $properties)
|
|
|
61 |
return str_replace("\n", '', parent::renderDirective($node, $properties)) .
|
62 |
"\n\n";
|
63 |
}
|
@@ -68,7 +74,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
68 |
* @param array properties to render
|
69 |
* @return string the rendered properties
|
70 |
*/
|
71 |
-
public function renderProperties($node, $properties)
|
|
|
72 |
return join(' ', $properties);
|
73 |
}
|
74 |
|
@@ -77,8 +84,10 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
77 |
* @param SassNode the node being rendered
|
78 |
* @return string the rendered property
|
79 |
*/
|
80 |
-
public function renderProperty($node)
|
|
|
81 |
$node->important = $node->important ? ' !important' : '';
|
|
|
82 |
return "{$node->name}: {$node->value}{$node->important};";
|
83 |
}
|
84 |
|
@@ -89,7 +98,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
89 |
* @param string rendered rules
|
90 |
* @return string the rendered rule
|
91 |
*/
|
92 |
-
public function renderRule($node, $properties, $rules)
|
|
|
93 |
return $this->renderDebug($node) . parent::renderRule($node, $properties,
|
94 |
str_replace("\n\n", "\n", $rules)) . "\n";
|
95 |
}
|
@@ -104,7 +114,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
104 |
* @param SassNode the node being rendered
|
105 |
* @return string the debug information
|
106 |
*/
|
107 |
-
protected function renderDebug($node)
|
|
|
108 |
$indent = $this->getIndent($node);
|
109 |
$debug = '';
|
110 |
|
@@ -114,10 +125,10 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
114 |
$debug .= 'filename{' . self::DEBUG_INFO_PROPERTY . ':' . preg_replace('/([^-\w])/', '\\\\\1', "file://{$node->filename}") . ';}';
|
115 |
$debug .= 'line{' . self::DEBUG_INFO_PROPERTY . ":'{$node->line}';}";
|
116 |
$debug .= "}\n";
|
117 |
-
}
|
118 |
-
elseif ($node->line_numbers) {
|
119 |
$debug .= "$indent/* line {$node->line} {$node->filename} */\n";
|
120 |
}
|
|
|
121 |
return $debug;
|
122 |
}
|
123 |
|
@@ -126,7 +137,8 @@ class SassCompactRenderer extends SassCompressedRenderer {
|
|
126 |
* @param SassNode the node being rendered
|
127 |
* @return string the rendered selectors
|
128 |
*/
|
129 |
-
protected function renderSelectors($node)
|
|
|
130 |
return join(', ', $node->selectors);
|
131 |
}
|
132 |
}
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassCompressedRenderer.php';
|
13 |
|
14 |
/**
|
15 |
* SassCompactRenderer class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.renderers
|
21 |
*/
|
22 |
+
class SassCompactRenderer extends SassCompressedRenderer
|
23 |
+
{
|
24 |
const DEBUG_INFO_RULE = '@media -sass-debug-info';
|
25 |
const DEBUG_INFO_PROPERTY = 'font-family';
|
26 |
|
28 |
* Renders the brace between the selectors and the properties
|
29 |
* @return string the brace between the selectors and the properties
|
30 |
*/
|
31 |
+
protected function between()
|
32 |
+
{
|
33 |
return ' { ';
|
34 |
}
|
35 |
|
37 |
* Renders the brace at the end of the rule
|
38 |
* @return string the brace between the rule and its properties
|
39 |
*/
|
40 |
+
protected function end()
|
41 |
+
{
|
42 |
return " }\n";
|
43 |
}
|
44 |
|
49 |
* @param SassNode the node being rendered
|
50 |
* @return string the rendered commnt
|
51 |
*/
|
52 |
+
public function renderComment($node)
|
53 |
+
{
|
54 |
$nl = ($node->parent instanceof SassRuleNode?'':"\n");
|
55 |
+
|
56 |
return "$nl/* " . join("\n * ", $node->children) . " */$nl" ;
|
57 |
}
|
58 |
|
62 |
* @param array properties of the directive
|
63 |
* @return string the rendered directive
|
64 |
*/
|
65 |
+
public function renderDirective($node, $properties)
|
66 |
+
{
|
67 |
return str_replace("\n", '', parent::renderDirective($node, $properties)) .
|
68 |
"\n\n";
|
69 |
}
|
74 |
* @param array properties to render
|
75 |
* @return string the rendered properties
|
76 |
*/
|
77 |
+
public function renderProperties($node, $properties)
|
78 |
+
{
|
79 |
return join(' ', $properties);
|
80 |
}
|
81 |
|
84 |
* @param SassNode the node being rendered
|
85 |
* @return string the rendered property
|
86 |
*/
|
87 |
+
public function renderProperty($node)
|
88 |
+
{
|
89 |
$node->important = $node->important ? ' !important' : '';
|
90 |
+
|
91 |
return "{$node->name}: {$node->value}{$node->important};";
|
92 |
}
|
93 |
|
98 |
* @param string rendered rules
|
99 |
* @return string the rendered rule
|
100 |
*/
|
101 |
+
public function renderRule($node, $properties, $rules)
|
102 |
+
{
|
103 |
return $this->renderDebug($node) . parent::renderRule($node, $properties,
|
104 |
str_replace("\n\n", "\n", $rules)) . "\n";
|
105 |
}
|
114 |
* @param SassNode the node being rendered
|
115 |
* @return string the debug information
|
116 |
*/
|
117 |
+
protected function renderDebug($node)
|
118 |
+
{
|
119 |
$indent = $this->getIndent($node);
|
120 |
$debug = '';
|
121 |
|
125 |
$debug .= 'filename{' . self::DEBUG_INFO_PROPERTY . ':' . preg_replace('/([^-\w])/', '\\\\\1', "file://{$node->filename}") . ';}';
|
126 |
$debug .= 'line{' . self::DEBUG_INFO_PROPERTY . ":'{$node->line}';}";
|
127 |
$debug .= "}\n";
|
128 |
+
} elseif ($node->line_numbers) {
|
|
|
129 |
$debug .= "$indent/* line {$node->line} {$node->filename} */\n";
|
130 |
}
|
131 |
+
|
132 |
return $debug;
|
133 |
}
|
134 |
|
137 |
* @param SassNode the node being rendered
|
138 |
* @return string the rendered selectors
|
139 |
*/
|
140 |
+
protected function renderSelectors($node)
|
141 |
+
{
|
142 |
return join(', ', $node->selectors);
|
143 |
}
|
144 |
}
|
lib/phpsass/renderers/SassCompressedRenderer.php
CHANGED
@@ -16,12 +16,14 @@
|
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.renderers
|
18 |
*/
|
19 |
-
class SassCompressedRenderer extends SassRenderer
|
|
|
20 |
/**
|
21 |
* Renders the brace between the selectors and the properties
|
22 |
* @return string the brace between the selectors and the properties
|
23 |
*/
|
24 |
-
protected function between()
|
|
|
25 |
return '{';
|
26 |
}
|
27 |
|
@@ -29,7 +31,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
29 |
* Renders the brace at the end of the rule
|
30 |
* @return string the brace between the rule and its properties
|
31 |
*/
|
32 |
-
protected function end()
|
|
|
33 |
return '}';
|
34 |
}
|
35 |
|
@@ -38,7 +41,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
38 |
* @param SassNode the node to return the indent string for
|
39 |
* @return string the indent string for this SassNode
|
40 |
*/
|
41 |
-
protected function getIndent($node)
|
|
|
42 |
return '';
|
43 |
}
|
44 |
|
@@ -47,7 +51,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
47 |
* @param SassNode the node being rendered
|
48 |
* @return string the rendered comment
|
49 |
*/
|
50 |
-
public function renderComment($node)
|
|
|
51 |
return '';
|
52 |
}
|
53 |
|
@@ -57,7 +62,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
57 |
* @param array properties of the directive
|
58 |
* @return string the rendered directive
|
59 |
*/
|
60 |
-
public function renderDirective($node, $properties)
|
|
|
61 |
return $node->directive . $this->between() . $this->renderProperties($node, $properties) . $this->end();
|
62 |
}
|
63 |
|
@@ -67,7 +73,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
67 |
* @param array properties to render
|
68 |
* @return string the rendered properties
|
69 |
*/
|
70 |
-
public function renderProperties($node, $properties)
|
|
|
71 |
return join('', $properties);
|
72 |
}
|
73 |
|
@@ -76,8 +83,10 @@ class SassCompressedRenderer extends SassRenderer {
|
|
76 |
* @param SassNode the node being rendered
|
77 |
* @return string the rendered property
|
78 |
*/
|
79 |
-
public function renderProperty($node)
|
|
|
80 |
$node->important = $node->important ? '!important' : '';
|
|
|
81 |
return "{$node->name}:{$node->value}{$node->important};";
|
82 |
}
|
83 |
|
@@ -88,7 +97,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
88 |
* @param string rendered rules
|
89 |
* @return string the rendered directive
|
90 |
*/
|
91 |
-
public function renderRule($node, $properties, $rules)
|
|
|
92 |
$selectors = $this->renderSelectors($node);
|
93 |
if ($selectors) {
|
94 |
return (!empty($properties) ? $selectors . $this->between() . $this->renderProperties($node, $properties) . $this->end() : '') . $rules;
|
@@ -100,7 +110,8 @@ class SassCompressedRenderer extends SassRenderer {
|
|
100 |
* @param SassNode the node being rendered
|
101 |
* @return string the rendered selectors
|
102 |
*/
|
103 |
-
protected function renderSelectors($node)
|
|
|
104 |
$selectors = array();
|
105 |
foreach ($node->selectors as $selector) {
|
106 |
if (!$node->isPlaceholder($selector)) {
|
@@ -110,4 +121,4 @@ class SassCompressedRenderer extends SassRenderer {
|
|
110 |
|
111 |
return join(',', $selectors);
|
112 |
}
|
113 |
-
}
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.renderers
|
18 |
*/
|
19 |
+
class SassCompressedRenderer extends SassRenderer
|
20 |
+
{
|
21 |
/**
|
22 |
* Renders the brace between the selectors and the properties
|
23 |
* @return string the brace between the selectors and the properties
|
24 |
*/
|
25 |
+
protected function between()
|
26 |
+
{
|
27 |
return '{';
|
28 |
}
|
29 |
|
31 |
* Renders the brace at the end of the rule
|
32 |
* @return string the brace between the rule and its properties
|
33 |
*/
|
34 |
+
protected function end()
|
35 |
+
{
|
36 |
return '}';
|
37 |
}
|
38 |
|
41 |
* @param SassNode the node to return the indent string for
|
42 |
* @return string the indent string for this SassNode
|
43 |
*/
|
44 |
+
protected function getIndent($node)
|
45 |
+
{
|
46 |
return '';
|
47 |
}
|
48 |
|
51 |
* @param SassNode the node being rendered
|
52 |
* @return string the rendered comment
|
53 |
*/
|
54 |
+
public function renderComment($node)
|
55 |
+
{
|
56 |
return '';
|
57 |
}
|
58 |
|
62 |
* @param array properties of the directive
|
63 |
* @return string the rendered directive
|
64 |
*/
|
65 |
+
public function renderDirective($node, $properties)
|
66 |
+
{
|
67 |
return $node->directive . $this->between() . $this->renderProperties($node, $properties) . $this->end();
|
68 |
}
|
69 |
|
73 |
* @param array properties to render
|
74 |
* @return string the rendered properties
|
75 |
*/
|
76 |
+
public function renderProperties($node, $properties)
|
77 |
+
{
|
78 |
return join('', $properties);
|
79 |
}
|
80 |
|
83 |
* @param SassNode the node being rendered
|
84 |
* @return string the rendered property
|
85 |
*/
|
86 |
+
public function renderProperty($node)
|
87 |
+
{
|
88 |
$node->important = $node->important ? '!important' : '';
|
89 |
+
|
90 |
return "{$node->name}:{$node->value}{$node->important};";
|
91 |
}
|
92 |
|
97 |
* @param string rendered rules
|
98 |
* @return string the rendered directive
|
99 |
*/
|
100 |
+
public function renderRule($node, $properties, $rules)
|
101 |
+
{
|
102 |
$selectors = $this->renderSelectors($node);
|
103 |
if ($selectors) {
|
104 |
return (!empty($properties) ? $selectors . $this->between() . $this->renderProperties($node, $properties) . $this->end() : '') . $rules;
|
110 |
* @param SassNode the node being rendered
|
111 |
* @return string the rendered selectors
|
112 |
*/
|
113 |
+
protected function renderSelectors($node)
|
114 |
+
{
|
115 |
$selectors = array();
|
116 |
foreach ($node->selectors as $selector) {
|
117 |
if (!$node->isPlaceholder($selector)) {
|
121 |
|
122 |
return join(',', $selectors);
|
123 |
}
|
124 |
+
}
|
lib/phpsass/renderers/SassExpandedRenderer.php
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassExpandedRenderer class.
|
@@ -19,20 +19,23 @@ require_once('SassCompactRenderer.php');
|
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.renderers
|
21 |
*/
|
22 |
-
class SassExpandedRenderer extends SassCompactRenderer
|
|
|
23 |
/**
|
24 |
* Renders the brace between the selectors and the properties
|
25 |
* @return string the brace between the selectors and the properties
|
26 |
*/
|
27 |
-
protected function between()
|
|
|
28 |
return " {\n" ;
|
29 |
}
|
30 |
-
|
31 |
/**
|
32 |
* Renders the brace at the end of the rule
|
33 |
* @return string the brace between the rule and its properties
|
34 |
*/
|
35 |
-
protected function end()
|
|
|
36 |
return "\n}\n\n";
|
37 |
}
|
38 |
|
@@ -41,12 +44,14 @@ class SassExpandedRenderer extends SassCompactRenderer {
|
|
41 |
* @param SassNode the node being rendered
|
42 |
* @return string the rendered commnt
|
43 |
*/
|
44 |
-
public function renderComment($node)
|
|
|
45 |
$indent = $this->getIndent($node);
|
46 |
$lines = explode("\n", $node->value);
|
47 |
foreach ($lines as &$line) {
|
48 |
$line = trim($line);
|
49 |
}
|
|
|
50 |
return "$indent/*\n$indent * ".join("\n$indent * ", $lines)."\n$indent */".(empty($indent)?"\n":'');
|
51 |
}
|
52 |
|
@@ -55,8 +60,10 @@ class SassExpandedRenderer extends SassCompactRenderer {
|
|
55 |
* @param array properties to render
|
56 |
* @return string the rendered properties
|
57 |
*/
|
58 |
-
public function renderProperties($node, $properties)
|
|
|
59 |
$indent = $this->getIndent($node).self::INDENT;
|
|
|
60 |
return $indent.join("\n$indent", $properties);
|
61 |
}
|
62 |
}
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassCompactRenderer.php';
|
13 |
|
14 |
/**
|
15 |
* SassExpandedRenderer class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.renderers
|
21 |
*/
|
22 |
+
class SassExpandedRenderer extends SassCompactRenderer
|
23 |
+
{
|
24 |
/**
|
25 |
* Renders the brace between the selectors and the properties
|
26 |
* @return string the brace between the selectors and the properties
|
27 |
*/
|
28 |
+
protected function between()
|
29 |
+
{
|
30 |
return " {\n" ;
|
31 |
}
|
32 |
+
|
33 |
/**
|
34 |
* Renders the brace at the end of the rule
|
35 |
* @return string the brace between the rule and its properties
|
36 |
*/
|
37 |
+
protected function end()
|
38 |
+
{
|
39 |
return "\n}\n\n";
|
40 |
}
|
41 |
|
44 |
* @param SassNode the node being rendered
|
45 |
* @return string the rendered commnt
|
46 |
*/
|
47 |
+
public function renderComment($node)
|
48 |
+
{
|
49 |
$indent = $this->getIndent($node);
|
50 |
$lines = explode("\n", $node->value);
|
51 |
foreach ($lines as &$line) {
|
52 |
$line = trim($line);
|
53 |
}
|
54 |
+
|
55 |
return "$indent/*\n$indent * ".join("\n$indent * ", $lines)."\n$indent */".(empty($indent)?"\n":'');
|
56 |
}
|
57 |
|
60 |
* @param array properties to render
|
61 |
* @return string the rendered properties
|
62 |
*/
|
63 |
+
public function renderProperties($node, $properties)
|
64 |
+
{
|
65 |
$indent = $this->getIndent($node).self::INDENT;
|
66 |
+
|
67 |
return $indent.join("\n$indent", $properties);
|
68 |
}
|
69 |
}
|
lib/phpsass/renderers/SassNestedRenderer.php
CHANGED
@@ -9,32 +9,35 @@
|
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassNestedRenderer class.
|
16 |
* Nested style is the default Sass style, because it reflects the structure of
|
17 |
* the document in much the same way Sass does. Each rule is indented based on
|
18 |
* how deeply it's nested. Each property has its own line and is indented
|
19 |
-
* within the rule.
|
20 |
* @package PHamlP
|
21 |
* @subpackage Sass.renderers
|
22 |
*/
|
23 |
-
class SassNestedRenderer extends SassExpandedRenderer
|
|
|
24 |
/**
|
25 |
* Renders the brace at the end of the rule
|
26 |
* @return string the brace between the rule and its properties
|
27 |
*/
|
28 |
-
protected function end()
|
|
|
29 |
return " }\n";
|
30 |
}
|
31 |
-
|
32 |
/**
|
33 |
* Returns the indent string for the node
|
34 |
* @param SassNode the node being rendered
|
35 |
* @return string the indent string for this SassNode
|
36 |
*/
|
37 |
-
protected function getIndent($node)
|
|
|
38 |
return str_repeat(self::INDENT, $node->level);
|
39 |
}
|
40 |
|
@@ -44,8 +47,10 @@ class SassNestedRenderer extends SassExpandedRenderer {
|
|
44 |
* @param array properties of the directive
|
45 |
* @return string the rendered directive
|
46 |
*/
|
47 |
-
public function renderDirective($node, $properties)
|
|
|
48 |
$directive = $this->getIndent($node) . $node->directive . $this->between() . $this->renderProperties($node, $properties);
|
|
|
49 |
return preg_replace('/(.*})\n$/', '\1', $directive) . $this->end();
|
50 |
}
|
51 |
|
@@ -54,15 +59,17 @@ class SassNestedRenderer extends SassExpandedRenderer {
|
|
54 |
* @param SassNode the node being rendered
|
55 |
* @return string the rendered selectors
|
56 |
*/
|
57 |
-
protected function renderSelectors($node)
|
|
|
58 |
$selectors = array();
|
59 |
foreach ($node->selectors as $selector) {
|
60 |
if (!$node->isPlaceholder($selector)) {
|
61 |
$selectors[] = $selector;
|
62 |
}
|
63 |
}
|
64 |
-
|
65 |
$indent = $this->getIndent($node);
|
|
|
66 |
return $indent.join(",\n$indent", $selectors);
|
67 |
}
|
68 |
-
}
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassExpandedRenderer.php';
|
13 |
|
14 |
/**
|
15 |
* SassNestedRenderer class.
|
16 |
* Nested style is the default Sass style, because it reflects the structure of
|
17 |
* the document in much the same way Sass does. Each rule is indented based on
|
18 |
* how deeply it's nested. Each property has its own line and is indented
|
19 |
+
* within the rule.
|
20 |
* @package PHamlP
|
21 |
* @subpackage Sass.renderers
|
22 |
*/
|
23 |
+
class SassNestedRenderer extends SassExpandedRenderer
|
24 |
+
{
|
25 |
/**
|
26 |
* Renders the brace at the end of the rule
|
27 |
* @return string the brace between the rule and its properties
|
28 |
*/
|
29 |
+
protected function end()
|
30 |
+
{
|
31 |
return " }\n";
|
32 |
}
|
33 |
+
|
34 |
/**
|
35 |
* Returns the indent string for the node
|
36 |
* @param SassNode the node being rendered
|
37 |
* @return string the indent string for this SassNode
|
38 |
*/
|
39 |
+
protected function getIndent($node)
|
40 |
+
{
|
41 |
return str_repeat(self::INDENT, $node->level);
|
42 |
}
|
43 |
|
47 |
* @param array properties of the directive
|
48 |
* @return string the rendered directive
|
49 |
*/
|
50 |
+
public function renderDirective($node, $properties)
|
51 |
+
{
|
52 |
$directive = $this->getIndent($node) . $node->directive . $this->between() . $this->renderProperties($node, $properties);
|
53 |
+
|
54 |
return preg_replace('/(.*})\n$/', '\1', $directive) . $this->end();
|
55 |
}
|
56 |
|
59 |
* @param SassNode the node being rendered
|
60 |
* @return string the rendered selectors
|
61 |
*/
|
62 |
+
protected function renderSelectors($node)
|
63 |
+
{
|
64 |
$selectors = array();
|
65 |
foreach ($node->selectors as $selector) {
|
66 |
if (!$node->isPlaceholder($selector)) {
|
67 |
$selectors[] = $selector;
|
68 |
}
|
69 |
}
|
70 |
+
|
71 |
$indent = $this->getIndent($node);
|
72 |
+
|
73 |
return $indent.join(",\n$indent", $selectors);
|
74 |
}
|
75 |
+
}
|
lib/phpsass/renderers/SassRenderer.php
CHANGED
@@ -9,17 +9,18 @@
|
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
-
require_once
|
14 |
-
require_once
|
15 |
-
require_once
|
16 |
|
17 |
/**
|
18 |
* SassRenderer class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.renderers
|
21 |
*/
|
22 |
-
class SassRenderer
|
|
|
23 |
/**#@+
|
24 |
* Output Styles
|
25 |
*/
|
@@ -36,7 +37,8 @@ class SassRenderer {
|
|
36 |
* @param string render style
|
37 |
* @return SassRenderer
|
38 |
*/
|
39 |
-
public static function getRenderer($style)
|
|
|
40 |
switch ($style) {
|
41 |
case self::STYLE_COMPACT:
|
42 |
return new SassCompactRenderer();
|
@@ -48,4 +50,4 @@ class SassRenderer {
|
|
48 |
return new SassNestedRenderer();
|
49 |
} // switch
|
50 |
}
|
51 |
-
}
|
9 |
* @subpackage Sass.renderers
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassCompactRenderer.php';
|
13 |
+
require_once 'SassCompressedRenderer.php';
|
14 |
+
require_once 'SassExpandedRenderer.php';
|
15 |
+
require_once 'SassNestedRenderer.php';
|
16 |
|
17 |
/**
|
18 |
* SassRenderer class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.renderers
|
21 |
*/
|
22 |
+
class SassRenderer
|
23 |
+
{
|
24 |
/**#@+
|
25 |
* Output Styles
|
26 |
*/
|
37 |
* @param string render style
|
38 |
* @return SassRenderer
|
39 |
*/
|
40 |
+
public static function getRenderer($style)
|
41 |
+
{
|
42 |
switch ($style) {
|
43 |
case self::STYLE_COMPACT:
|
44 |
return new SassCompactRenderer();
|
50 |
return new SassNestedRenderer();
|
51 |
} // switch
|
52 |
}
|
53 |
+
}
|
lib/phpsass/script/SassScriptFunction.php
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
* @subpackage Sass.script
|
9 |
*/
|
10 |
|
11 |
-
require_once
|
12 |
|
13 |
/**
|
14 |
* SassScriptFunction class.
|
@@ -16,7 +16,8 @@ require_once('SassScriptFunctions.php');
|
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.script
|
18 |
*/
|
19 |
-
class SassScriptFunction
|
|
|
20 |
/**@#+
|
21 |
* Regexes for matching and extracting functions and arguments
|
22 |
*/
|
@@ -37,17 +38,20 @@ class SassScriptFunction {
|
|
37 |
* @param array arguments for the function
|
38 |
* @return SassScriptFunction
|
39 |
*/
|
40 |
-
public function __construct($name, $args)
|
|
|
41 |
$this->name = $name;
|
42 |
$this->args = $args;
|
43 |
}
|
44 |
|
45 |
-
private function process_arguments($input)
|
|
|
46 |
if (is_array($input)) {
|
47 |
$output = array();
|
48 |
foreach ($input as $k => $token) {
|
49 |
$output[$k] = trim($this->process_arguments($token), '\'"');
|
50 |
}
|
|
|
51 |
return $output;
|
52 |
}
|
53 |
|
@@ -76,7 +80,8 @@ class SassScriptFunction {
|
|
76 |
* pre-defined functions, then try the pre-defined functions.
|
77 |
* @return Function the value of this Function
|
78 |
*/
|
79 |
-
public function perform()
|
|
|
80 |
self::$context = new SassContext(SassScriptParser::$context);
|
81 |
|
82 |
$name = preg_replace('/[^a-z0-9_]/', '_', strtolower($this->name));
|
@@ -91,10 +96,11 @@ class SassScriptFunction {
|
|
91 |
try {
|
92 |
if (SassScriptParser::$context->hasFunction($this->name)) {
|
93 |
$return = SassScriptParser::$context->getFunction($this->name)->execute(SassScriptParser::$context, $this->args);
|
|
|
94 |
return $return;
|
95 |
-
}
|
96 |
-
else if (SassScriptParser::$context->hasFunction($name)) {
|
97 |
$return = SassScriptParser::$context->getFunction($name)->execute(SassScriptParser::$context, $this->args);
|
|
|
98 |
return $return;
|
99 |
}
|
100 |
} catch (Exception $e) {
|
@@ -110,8 +116,10 @@ class SassScriptFunction {
|
|
110 |
if (count($lexed) === 1) {
|
111 |
return $lexed[0];
|
112 |
}
|
|
|
113 |
return new SassString(implode('', $this->process_arguments($lexed)));
|
114 |
}
|
|
|
115 |
return $result;
|
116 |
}
|
117 |
}
|
@@ -120,6 +128,7 @@ class SassScriptFunction {
|
|
120 |
if (method_exists('SassScriptFunctions', $name) || method_exists('SassScriptFunctions', $name = '_' . $name)) {
|
121 |
$sig = self::get_reflection(array('SassScriptFunctions', $name));
|
122 |
list($args) = self::fill_parameters($sig, $this->args, SassScriptParser::$context, $this);
|
|
|
123 |
return call_user_func_array(array('SassScriptFunctions', $name), $args);
|
124 |
}
|
125 |
|
@@ -132,7 +141,6 @@ class SassScriptFunction {
|
|
132 |
}
|
133 |
}
|
134 |
|
135 |
-
|
136 |
// CSS function: create a SassString that will emit the function into the CSS
|
137 |
return new SassString($this->name . '(' . join(', ', $args) . ')');
|
138 |
}
|
@@ -142,7 +150,8 @@ class SassScriptFunction {
|
|
142 |
* @param string path to directory to import
|
143 |
* @return array filenames imported
|
144 |
*/
|
145 |
-
private function import($dir)
|
|
|
146 |
$files = array();
|
147 |
|
148 |
foreach (array_slice(scandir($dir), 2) as $file) {
|
@@ -151,6 +160,7 @@ class SassScriptFunction {
|
|
151 |
require_once($dir . DIRECTORY_SEPARATOR . $file);
|
152 |
}
|
153 |
} // foreach
|
|
|
154 |
return $files;
|
155 |
}
|
156 |
|
@@ -160,7 +170,8 @@ class SassScriptFunction {
|
|
160 |
* @param string the subject string
|
161 |
* @return mixed match at the start of the string or false if no match
|
162 |
*/
|
163 |
-
public static function isa($subject)
|
|
|
164 |
if (!preg_match(self::MATCH, $subject, $matches))
|
165 |
return false;
|
166 |
|
@@ -170,21 +181,22 @@ class SassScriptFunction {
|
|
170 |
$strlen = strlen($subject);
|
171 |
$subject_str = (string) $subject;
|
172 |
|
173 |
-
while($paren && $strpos < $strlen) {
|
174 |
$c = $subject_str[$strpos++];
|
175 |
|
176 |
$match .= $c;
|
177 |
if ($c === '(') {
|
178 |
$paren += 1;
|
179 |
-
}
|
180 |
-
elseif ($c === ')') {
|
181 |
$paren -= 1;
|
182 |
}
|
183 |
}
|
|
|
184 |
return $match;
|
185 |
}
|
186 |
|
187 |
-
public static function extractArgs($string, $include_null = TRUE, $context)
|
|
|
188 |
$args = array();
|
189 |
$arg = '';
|
190 |
$paren = 0;
|
@@ -205,7 +217,7 @@ class SassScriptFunction {
|
|
205 |
|
206 |
if (strpos($value, ':') !== false && preg_match(SassVariableNode::MATCH, $value, $match)) {
|
207 |
$return[$match[SassVariableNode::NAME]] = $match[SassVariableNode::VALUE];
|
208 |
-
}
|
209 |
$return[str_replace('$', '', $value)] = NULL;
|
210 |
} elseif ($include_null || $value !== NULL) {
|
211 |
$return[] = $value;
|
@@ -215,12 +227,12 @@ class SassScriptFunction {
|
|
215 |
return $return;
|
216 |
}
|
217 |
|
218 |
-
public static function get_reflection($method)
|
|
|
219 |
if (is_array($method)) {
|
220 |
$class = new ReflectionClass($method[0]);
|
221 |
$function = $class->getMethod($method[1]);
|
222 |
-
}
|
223 |
-
else {
|
224 |
$function = new ReflectionFunction($method);
|
225 |
}
|
226 |
|
@@ -235,15 +247,16 @@ class SassScriptFunction {
|
|
235 |
}
|
236 |
$return[$parameter->getName()] = $parsed; # we evaluate the defaults to get Sass objects.
|
237 |
}
|
|
|
238 |
return $return;
|
239 |
}
|
240 |
|
241 |
-
public static function fill_parameters($required, $provided, $context, $source)
|
|
|
242 |
$context = new SassContext($context);
|
243 |
$_required = array_merge(array(), $required); // need to array_merge?
|
244 |
$fill = $_required;
|
245 |
|
246 |
-
|
247 |
foreach ($required as $name=>$default) {
|
248 |
// we require that named variables provide a default.
|
249 |
if (isset($provided[$name]) && $default !== NULL) {
|
@@ -264,8 +277,7 @@ class SassScriptFunction {
|
|
264 |
}
|
265 |
if (count($provided)) {
|
266 |
$arg = array_shift($provided);
|
267 |
-
}
|
268 |
-
elseif ($default !== NULL) {
|
269 |
$arg = $default;
|
270 |
|
271 |
// for mixins with default values that refer to other arguments
|
@@ -277,8 +289,7 @@ class SassScriptFunction {
|
|
277 |
$arg = $provided_copy[$pos];
|
278 |
}
|
279 |
}
|
280 |
-
}
|
281 |
-
else {
|
282 |
throw new SassMixinNodeException("Function::$name: Required variable ($name) not given.\nFunction defined: " . $source->token->filename . '::' . $source->token->line . "\nFunction used", $source);
|
283 |
}
|
284 |
// splats
|
8 |
* @subpackage Sass.script
|
9 |
*/
|
10 |
|
11 |
+
require_once 'SassScriptFunctions.php';
|
12 |
|
13 |
/**
|
14 |
* SassScriptFunction class.
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.script
|
18 |
*/
|
19 |
+
class SassScriptFunction
|
20 |
+
{
|
21 |
/**@#+
|
22 |
* Regexes for matching and extracting functions and arguments
|
23 |
*/
|
38 |
* @param array arguments for the function
|
39 |
* @return SassScriptFunction
|
40 |
*/
|
41 |
+
public function __construct($name, $args)
|
42 |
+
{
|
43 |
$this->name = $name;
|
44 |
$this->args = $args;
|
45 |
}
|
46 |
|
47 |
+
private function process_arguments($input)
|
48 |
+
{
|
49 |
if (is_array($input)) {
|
50 |
$output = array();
|
51 |
foreach ($input as $k => $token) {
|
52 |
$output[$k] = trim($this->process_arguments($token), '\'"');
|
53 |
}
|
54 |
+
|
55 |
return $output;
|
56 |
}
|
57 |
|
80 |
* pre-defined functions, then try the pre-defined functions.
|
81 |
* @return Function the value of this Function
|
82 |
*/
|
83 |
+
public function perform()
|
84 |
+
{
|
85 |
self::$context = new SassContext(SassScriptParser::$context);
|
86 |
|
87 |
$name = preg_replace('/[^a-z0-9_]/', '_', strtolower($this->name));
|
96 |
try {
|
97 |
if (SassScriptParser::$context->hasFunction($this->name)) {
|
98 |
$return = SassScriptParser::$context->getFunction($this->name)->execute(SassScriptParser::$context, $this->args);
|
99 |
+
|
100 |
return $return;
|
101 |
+
} elseif (SassScriptParser::$context->hasFunction($name)) {
|
|
|
102 |
$return = SassScriptParser::$context->getFunction($name)->execute(SassScriptParser::$context, $this->args);
|
103 |
+
|
104 |
return $return;
|
105 |
}
|
106 |
} catch (Exception $e) {
|
116 |
if (count($lexed) === 1) {
|
117 |
return $lexed[0];
|
118 |
}
|
119 |
+
|
120 |
return new SassString(implode('', $this->process_arguments($lexed)));
|
121 |
}
|
122 |
+
|
123 |
return $result;
|
124 |
}
|
125 |
}
|
128 |
if (method_exists('SassScriptFunctions', $name) || method_exists('SassScriptFunctions', $name = '_' . $name)) {
|
129 |
$sig = self::get_reflection(array('SassScriptFunctions', $name));
|
130 |
list($args) = self::fill_parameters($sig, $this->args, SassScriptParser::$context, $this);
|
131 |
+
|
132 |
return call_user_func_array(array('SassScriptFunctions', $name), $args);
|
133 |
}
|
134 |
|
141 |
}
|
142 |
}
|
143 |
|
|
|
144 |
// CSS function: create a SassString that will emit the function into the CSS
|
145 |
return new SassString($this->name . '(' . join(', ', $args) . ')');
|
146 |
}
|
150 |
* @param string path to directory to import
|
151 |
* @return array filenames imported
|
152 |
*/
|
153 |
+
private function import($dir)
|
154 |
+
{
|
155 |
$files = array();
|
156 |
|
157 |
foreach (array_slice(scandir($dir), 2) as $file) {
|
160 |
require_once($dir . DIRECTORY_SEPARATOR . $file);
|
161 |
}
|
162 |
} // foreach
|
163 |
+
|
164 |
return $files;
|
165 |
}
|
166 |
|
170 |
* @param string the subject string
|
171 |
* @return mixed match at the start of the string or false if no match
|
172 |
*/
|
173 |
+
public static function isa($subject)
|
174 |
+
{
|
175 |
if (!preg_match(self::MATCH, $subject, $matches))
|
176 |
return false;
|
177 |
|
181 |
$strlen = strlen($subject);
|
182 |
$subject_str = (string) $subject;
|
183 |
|
184 |
+
while ($paren && $strpos < $strlen) {
|
185 |
$c = $subject_str[$strpos++];
|
186 |
|
187 |
$match .= $c;
|
188 |
if ($c === '(') {
|
189 |
$paren += 1;
|
190 |
+
} elseif ($c === ')') {
|
|
|
191 |
$paren -= 1;
|
192 |
}
|
193 |
}
|
194 |
+
|
195 |
return $match;
|
196 |
}
|
197 |
|
198 |
+
public static function extractArgs($string, $include_null = TRUE, $context)
|
199 |
+
{
|
200 |
$args = array();
|
201 |
$arg = '';
|
202 |
$paren = 0;
|
217 |
|
218 |
if (strpos($value, ':') !== false && preg_match(SassVariableNode::MATCH, $value, $match)) {
|
219 |
$return[$match[SassVariableNode::NAME]] = $match[SassVariableNode::VALUE];
|
220 |
+
} elseif (substr($value, 0, 1) == '$' && $include_null) {
|
221 |
$return[str_replace('$', '', $value)] = NULL;
|
222 |
} elseif ($include_null || $value !== NULL) {
|
223 |
$return[] = $value;
|
227 |
return $return;
|
228 |
}
|
229 |
|
230 |
+
public static function get_reflection($method)
|
231 |
+
{
|
232 |
if (is_array($method)) {
|
233 |
$class = new ReflectionClass($method[0]);
|
234 |
$function = $class->getMethod($method[1]);
|
235 |
+
} else {
|
|
|
236 |
$function = new ReflectionFunction($method);
|
237 |
}
|
238 |
|
247 |
}
|
248 |
$return[$parameter->getName()] = $parsed; # we evaluate the defaults to get Sass objects.
|
249 |
}
|
250 |
+
|
251 |
return $return;
|
252 |
}
|
253 |
|
254 |
+
public static function fill_parameters($required, $provided, $context, $source)
|
255 |
+
{
|
256 |
$context = new SassContext($context);
|
257 |
$_required = array_merge(array(), $required); // need to array_merge?
|
258 |
$fill = $_required;
|
259 |
|
|
|
260 |
foreach ($required as $name=>$default) {
|
261 |
// we require that named variables provide a default.
|
262 |
if (isset($provided[$name]) && $default !== NULL) {
|
277 |
}
|
278 |
if (count($provided)) {
|
279 |
$arg = array_shift($provided);
|
280 |
+
} elseif ($default !== NULL) {
|
|
|
281 |
$arg = $default;
|
282 |
|
283 |
// for mixins with default values that refer to other arguments
|
289 |
$arg = $provided_copy[$pos];
|
290 |
}
|
291 |
}
|
292 |
+
} else {
|
|
|
293 |
throw new SassMixinNodeException("Function::$name: Required variable ($name) not given.\nFunction defined: " . $source->token->filename . '::' . $source->token->line . "\nFunction used", $source);
|
294 |
}
|
295 |
// splats
|
lib/phpsass/script/SassScriptFunctions.php
CHANGED
@@ -36,16 +36,19 @@
|
|
36 |
* @package PHamlP
|
37 |
* @subpackage Sass.script
|
38 |
*/
|
39 |
-
class SassScriptFunctions
|
|
|
40 |
const DECREASE = false;
|
41 |
const INCREASE = true;
|
42 |
|
43 |
public static $parser = FALSE;
|
44 |
-
public static function option($name)
|
|
|
45 |
$options = SassParser::$instance->getOptions();
|
46 |
if (isset($options[$name->value])) {
|
47 |
return new SassString($options[$name->value]);
|
48 |
}
|
|
|
49 |
return new SassBoolean(false);
|
50 |
}
|
51 |
|
@@ -64,7 +67,8 @@ class SassScriptFunctions {
|
|
64 |
* @return new SassColour SassColour object
|
65 |
* @throws SassScriptFunctionException if red, green, or blue are out of bounds
|
66 |
*/
|
67 |
-
public static function rgb($red, $green, $blue)
|
|
|
68 |
return self::rgba($red, $green, $blue, new SassNumber(1));
|
69 |
}
|
70 |
|
@@ -90,7 +94,8 @@ class SassScriptFunctions {
|
|
90 |
* colour components are out of bounds, or or the colour is not a colour, or
|
91 |
* alpha is out of bounds
|
92 |
*/
|
93 |
-
public static function rgba()
|
|
|
94 |
switch (func_num_args()) {
|
95 |
case 2:
|
96 |
$colour = func_get_arg(0);
|
@@ -98,19 +103,19 @@ class SassScriptFunctions {
|
|
98 |
SassLiteral::assertType($colour, 'SassColour');
|
99 |
SassLiteral::assertType($alpha, 'SassNumber');
|
100 |
SassLiteral::assertInRange($alpha, 0, 1);
|
|
|
101 |
return $colour->with(array('alpha' => $alpha->value));
|
102 |
break;
|
103 |
case 4:
|
104 |
$rgba = array();
|
105 |
$components = func_get_args();
|
106 |
$alpha = array_pop($components);
|
107 |
-
foreach($components as $component) {
|
108 |
SassLiteral::assertType($component, 'SassNumber');
|
109 |
if ($component->units == '%') {
|
110 |
SassLiteral::assertInRange($component, 0, 100, '%');
|
111 |
$rgba[] = $component->value * 2.55;
|
112 |
-
}
|
113 |
-
else {
|
114 |
SassLiteral::assertInRange($component, 0, 255);
|
115 |
$rgba[] = $component->value;
|
116 |
}
|
@@ -118,6 +123,7 @@ class SassScriptFunctions {
|
|
118 |
SassLiteral::assertType($alpha, 'SassNumber');
|
119 |
SassLiteral::assertInRange($alpha, 0, 1);
|
120 |
$rgba[] = $alpha->value;
|
|
|
121 |
return new SassColour($rgba);
|
122 |
break;
|
123 |
default:
|
@@ -138,9 +144,11 @@ class SassScriptFunctions {
|
|
138 |
* @return new SassColour The resulting colour
|
139 |
* @throws SassScriptFunctionException if saturation or lightness are out of bounds
|
140 |
*/
|
141 |
-
public static function hsl($h, $s, $l)
|
|
|
142 |
SassLiteral::assertInRange($s, 0, 100, '%');
|
143 |
SassLiteral::assertInRange($l, 0, 100, '%');
|
|
|
144 |
return self::hsla($h, $s, $l, new SassNumber(1));
|
145 |
}
|
146 |
|
@@ -158,7 +166,8 @@ class SassScriptFunctions {
|
|
158 |
* @throws SassScriptFunctionException if saturation, lightness or alpha are
|
159 |
* out of bounds
|
160 |
*/
|
161 |
-
public static function hsla($h, $s, $l, $a)
|
|
|
162 |
SassLiteral::assertType($h, 'SassNumber');
|
163 |
SassLiteral::assertType($s, 'SassNumber');
|
164 |
SassLiteral::assertType($l, 'SassNumber');
|
@@ -166,6 +175,7 @@ class SassScriptFunctions {
|
|
166 |
SassLiteral::assertInRange($s, 0, 100, '%');
|
167 |
SassLiteral::assertInRange($l, 0, 100, '%');
|
168 |
SassLiteral::assertInRange($a, 0, 1);
|
|
|
169 |
return new SassColour(array('hue' => $h, 'saturation' => $s, 'lightness' => $l, 'alpha' => $a));
|
170 |
}
|
171 |
|
@@ -179,8 +189,10 @@ class SassScriptFunctions {
|
|
179 |
* @return new SassNumber The red component of colour
|
180 |
* @throws SassScriptFunctionException If $colour is not a colour
|
181 |
*/
|
182 |
-
public static function red($colour)
|
|
|
183 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
184 |
return new SassNumber($colour->red);
|
185 |
}
|
186 |
|
@@ -190,8 +202,10 @@ class SassScriptFunctions {
|
|
190 |
* @return new SassNumber The green component of colour
|
191 |
* @throws SassScriptFunctionException If $colour is not a colour
|
192 |
*/
|
193 |
-
public static function green($colour)
|
|
|
194 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
195 |
return new SassNumber($colour->green);
|
196 |
}
|
197 |
|
@@ -201,8 +215,10 @@ class SassScriptFunctions {
|
|
201 |
* @return new SassNumber The blue component of colour
|
202 |
* @throws SassScriptFunctionException If $colour is not a colour
|
203 |
*/
|
204 |
-
public static function blue($colour)
|
|
|
205 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
206 |
return new SassNumber($colour->blue);
|
207 |
}
|
208 |
|
@@ -212,8 +228,10 @@ class SassScriptFunctions {
|
|
212 |
* @return new SassNumber The hue component of colour
|
213 |
* @throws SassScriptFunctionException If $colour is not a colour
|
214 |
*/
|
215 |
-
public static function hue($colour)
|
|
|
216 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
217 |
return new SassNumber($colour->getHue() . 'deg');
|
218 |
}
|
219 |
|
@@ -223,8 +241,10 @@ class SassScriptFunctions {
|
|
223 |
* @return new SassNumber The saturation component of colour
|
224 |
* @throws SassScriptFunctionException If $colour is not a colour
|
225 |
*/
|
226 |
-
public static function saturation($colour)
|
|
|
227 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
228 |
return new SassNumber($colour->getSaturation() . '%');
|
229 |
}
|
230 |
|
@@ -234,8 +254,10 @@ class SassScriptFunctions {
|
|
234 |
* @return new SassNumber The lightness component of colour
|
235 |
* @throws SassScriptFunctionException If $colour is not a colour
|
236 |
*/
|
237 |
-
public static function lightness($colour)
|
|
|
238 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
239 |
return new SassNumber($colour->getLightness() . '%');
|
240 |
}
|
241 |
|
@@ -247,13 +269,14 @@ class SassScriptFunctions {
|
|
247 |
*
|
248 |
* RL modified so that the filter: alpha function doesn't bork
|
249 |
*/
|
250 |
-
public static function alpha($colour)
|
|
|
251 |
try {
|
252 |
SassLiteral::assertType($colour, 'SassColour');
|
253 |
-
}
|
254 |
-
catch (Exception $e) {
|
255 |
return new SassString('alpha(100)');
|
256 |
}
|
|
|
257 |
return new SassNumber($colour->alpha);
|
258 |
}
|
259 |
|
@@ -263,8 +286,10 @@ class SassScriptFunctions {
|
|
263 |
* @return new SassNumber The alpha component (opacity) of colour
|
264 |
* @throws SassScriptFunctionException If $colour is not a colour
|
265 |
*/
|
266 |
-
public static function opacity($colour)
|
|
|
267 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
268 |
return new SassNumber($colour->alpha);
|
269 |
}
|
270 |
|
@@ -280,9 +305,11 @@ class SassScriptFunctions {
|
|
280 |
* @throws SassScriptFunctionException If $colour is not a colour or
|
281 |
* $degrees is not a number
|
282 |
*/
|
283 |
-
public static function adjust_hue($colour, $degrees)
|
|
|
284 |
SassLiteral::assertType($colour, 'SassColour');
|
285 |
SassLiteral::assertType($degrees, 'SassNumber');
|
|
|
286 |
return $colour->with(array('hue' => $colour->getHue(true) + $degrees->value));
|
287 |
}
|
288 |
|
@@ -302,7 +329,8 @@ class SassScriptFunctions {
|
|
302 |
* $amount is not a number
|
303 |
* @see lighten_rel
|
304 |
*/
|
305 |
-
public static function lighten($colour, $amount, $ofCurrent = false)
|
|
|
306 |
return self::adjust($colour, $amount, $ofCurrent, 'lightness', self::INCREASE, 0, 100, '%');
|
307 |
}
|
308 |
|
@@ -322,7 +350,8 @@ class SassScriptFunctions {
|
|
322 |
* $amount is not a number
|
323 |
* @see adjust
|
324 |
*/
|
325 |
-
public static function darken($colour, $amount, $ofCurrent = false)
|
|
|
326 |
return self::adjust($colour, $amount, $ofCurrent, 'lightness', self::DECREASE, 0, 100, '%');
|
327 |
}
|
328 |
|
@@ -342,7 +371,8 @@ class SassScriptFunctions {
|
|
342 |
* $amount is not a number
|
343 |
* @see adjust
|
344 |
*/
|
345 |
-
public static function saturate($colour, $amount, $ofCurrent = false)
|
|
|
346 |
return self::adjust($colour, $amount, $ofCurrent, 'saturation', self::INCREASE, 0, 100, '%');
|
347 |
}
|
348 |
|
@@ -362,7 +392,8 @@ class SassScriptFunctions {
|
|
362 |
* $amount is not a number
|
363 |
* @see adjust
|
364 |
*/
|
365 |
-
public static function desaturate($colour, $amount, $ofCurrent = false)
|
|
|
366 |
return self::adjust($colour, $amount, $ofCurrent, 'saturation', self::DECREASE, 0, 100, '%');
|
367 |
}
|
368 |
|
@@ -380,8 +411,10 @@ class SassScriptFunctions {
|
|
380 |
* $amount is not a number
|
381 |
* @see opacify_rel
|
382 |
*/
|
383 |
-
public static function opacify($colour, $amount, $ofCurrent = false)
|
|
|
384 |
$units = self::units($amount);
|
|
|
385 |
return self::adjust($colour, $amount, $ofCurrent, 'alpha', self::INCREASE, 0, ($units === '%' ? 100 : 1), $units);
|
386 |
}
|
387 |
|
@@ -398,8 +431,10 @@ class SassScriptFunctions {
|
|
398 |
* @throws SassScriptFunctionException If $colour is not a colour or
|
399 |
* $amount is not a number
|
400 |
*/
|
401 |
-
public static function transparentize($colour, $amount, $ofCurrent = false)
|
|
|
402 |
$units = self::units($amount);
|
|
|
403 |
return self::adjust($colour, $amount, $ofCurrent, 'alpha', self::DECREASE, 0, ($units === '%' ? 100 : 1), $units);
|
404 |
}
|
405 |
|
@@ -415,7 +450,8 @@ class SassScriptFunctions {
|
|
415 |
* $amount is not a number
|
416 |
* @see opacify
|
417 |
*/
|
418 |
-
public static function fade_in($colour, $amount, $ofCurrent = false)
|
|
|
419 |
return self::opacify($colour, $amount, $ofCurrent);
|
420 |
}
|
421 |
|
@@ -431,7 +467,8 @@ class SassScriptFunctions {
|
|
431 |
* $amount is not a number
|
432 |
* @see transparentize
|
433 |
*/
|
434 |
-
public static function fade_out($colour, $amount, $ofCurrent = false)
|
|
|
435 |
return self::transparentize($colour, $amount, $ofCurrent);
|
436 |
}
|
437 |
|
@@ -442,7 +479,8 @@ class SassScriptFunctions {
|
|
442 |
* @return new SassColour The comlemented colour
|
443 |
* @uses adjust_hue()
|
444 |
*/
|
445 |
-
public static function complement($colour)
|
|
|
446 |
// return self::adjust($colour, new SassNumber('180deg'), true, 'hue', self::INCREASE, 0, 360, '');
|
447 |
return self::adjust_hue($colour, new SassNumber('180deg'));
|
448 |
}
|
@@ -453,7 +491,8 @@ class SassScriptFunctions {
|
|
453 |
* @return new SassColour The greyscale colour
|
454 |
* @see desaturate
|
455 |
*/
|
456 |
-
public static function grayscale($colour)
|
|
|
457 |
return self::desaturate($colour, new SassNumber(100));
|
458 |
}
|
459 |
|
@@ -464,7 +503,8 @@ class SassScriptFunctions {
|
|
464 |
* @return new SassColour The greyscale colour
|
465 |
* @see desaturate
|
466 |
*/
|
467 |
-
public static function greyscale($colour)
|
|
|
468 |
return self::desaturate($colour, new SassNumber(100));
|
469 |
}
|
470 |
|
@@ -474,8 +514,10 @@ class SassScriptFunctions {
|
|
474 |
* @param SassColour: the colour
|
475 |
* @return new SassColour: the inverted colour
|
476 |
*/
|
477 |
-
public static function invert($colour)
|
|
|
478 |
SassLiteral::assertType($colour, 'SassColour');
|
|
|
479 |
return $colour->with(array(
|
480 |
'red' => 255 - $colour->getRed(true),
|
481 |
'blue' => 255 - $colour->getBlue(true),
|
@@ -504,7 +546,8 @@ class SassScriptFunctions {
|
|
504 |
* @throws SassScriptFunctionException If $colour1 or $colour2 is
|
505 |
* not a colour
|
506 |
*/
|
507 |
-
public static function mix($colour1, $colour2, $weight = '50%')
|
|
|
508 |
if (is_object($weight)) {
|
509 |
$weight = new SassNumber($weight);
|
510 |
}
|
@@ -560,7 +603,8 @@ class SassScriptFunctions {
|
|
560 |
* @param SassNumber (red, green, blue, hue, saturation, lightness, alpha) - the amount(s) to adjust by
|
561 |
* @return SassColour
|
562 |
*/
|
563 |
-
public static function adjust_color($color, $red = 0, $green = 0, $blue = 0, $hue = 0, $saturation = 0, $lightness = 0, $alpha = 0)
|
|
|
564 |
foreach (array('red', 'green', 'blue', 'hue', 'saturation', 'lightness', 'alpha') as $property) {
|
565 |
$obj = $$property;
|
566 |
$color = self::adjust($color, $$property, FALSE, $property, self::INCREASE, 0, 255);
|
@@ -575,7 +619,8 @@ class SassScriptFunctions {
|
|
575 |
* @param SassNumber (red, green, blue, saturation, lightness, alpha) - the amount(s) to scale by
|
576 |
* @return SassColour
|
577 |
*/
|
578 |
-
public static function scale_color($color, $red = 0, $green = 0, $blue = 0, $saturation = 0, $lightness = 0, $alpha = 0)
|
|
|
579 |
$maxes = array(
|
580 |
'red' => 255,
|
581 |
'green' => 255,
|
@@ -592,6 +637,7 @@ class SassScriptFunctions {
|
|
592 |
$color->$property = $color->$property + $diff * $scale;
|
593 |
}
|
594 |
$color->hsl2rgb();
|
|
|
595 |
return $color;
|
596 |
}
|
597 |
|
@@ -601,7 +647,8 @@ class SassScriptFunctions {
|
|
601 |
* @param SassNumber (red, green, blue, hue, saturation, lightness, alpha) - the amounts to scale by
|
602 |
* @return SassColour
|
603 |
*/
|
604 |
-
public static function change_color($color, $red = false, $green = false, $blue = false, $hue = false, $saturation = false, $lightness = false, $alpha = false)
|
|
|
605 |
$attrs = array();
|
606 |
foreach (array('red', 'green', 'blue', 'hue', 'saturation', 'lightness', 'alpha') as $i => $property) {
|
607 |
$obj = $$property;
|
@@ -609,6 +656,7 @@ class SassScriptFunctions {
|
|
609 |
$attrs[$property] = $obj->value;
|
610 |
}
|
611 |
}
|
|
|
612 |
return $color->with($attrs);
|
613 |
}
|
614 |
|
@@ -624,7 +672,8 @@ class SassScriptFunctions {
|
|
624 |
* @param float maximum value the amount can bemixed
|
625 |
* @param string amount units
|
626 |
*/
|
627 |
-
public static function adjust($colour, $amount, $ofCurrent, $att, $op, $min, $max, $units='')
|
|
|
628 |
SassLiteral::assertType($colour, 'SassColour');
|
629 |
SassLiteral::assertType($amount, 'SassNumber');
|
630 |
// SassLiteral::assertInRange($amount, $min, $max, $units);
|
@@ -640,13 +689,13 @@ class SassScriptFunctions {
|
|
640 |
$colour->hsl2rgb();
|
641 |
$colour->$att = $ofCurrent ? $colour->$att * (1 + ($amount * ($op === self::INCREASE ? 1 : -1))/100) : $colour->$att + ($amount * ($op === self::INCREASE ? 1 : -1));
|
642 |
$colour->rgb2hsl();
|
643 |
-
}
|
644 |
-
else {
|
645 |
$colour->rgb2hsl();
|
646 |
$colour->$att = $ofCurrent ? $colour->$att * (1 + ($amount * ($op === self::INCREASE ? 1 : -1))/100) : $colour->$att + ($amount * ($op === self::INCREASE ? 1 : -1));
|
647 |
$colour->$att = max($min, min($max, $colour->$att));
|
648 |
$colour->hsl2rgb();
|
649 |
}
|
|
|
650 |
return $colour;
|
651 |
}
|
652 |
|
@@ -654,13 +703,15 @@ class SassScriptFunctions {
|
|
654 |
* returns an IE hex string for a color with an alpha channel
|
655 |
* suitable for passing to IE filters.
|
656 |
*/
|
657 |
-
public static function ie_hex_str($color)
|
|
|
658 |
if (!($color instanceof SassColour)) {
|
659 |
$color = new SassColour($color);
|
660 |
}
|
661 |
$alpha = str_replace(',','.',round($color->alpha * 255));
|
662 |
$alpha_str = str_pad(dechex($alpha), 2, '0', STR_PAD_LEFT);
|
663 |
$col = $color->asHex(FALSE);
|
|
|
664 |
return new SassString(strtoupper('#' . $alpha_str . $col));
|
665 |
}
|
666 |
|
@@ -679,8 +730,10 @@ class SassScriptFunctions {
|
|
679 |
* @return SassNumber The absolute value of the number
|
680 |
* @throws SassScriptFunctionException If $number is not a number
|
681 |
*/
|
682 |
-
public static function abs($number)
|
|
|
683 |
SassLiteral::assertType($number, 'SassNumber');
|
|
|
684 |
return new SassNumber(abs($number->value).$number->units);
|
685 |
}
|
686 |
|
@@ -694,8 +747,10 @@ class SassScriptFunctions {
|
|
694 |
* @return new SassNumber The rounded number
|
695 |
* @throws SassScriptFunctionException If $number is not a number
|
696 |
*/
|
697 |
-
public static function ceil($number)
|
|
|
698 |
SassLiteral::assertType($number, 'SassNumber');
|
|
|
699 |
return new SassNumber(ceil($number->value).$number->units);
|
700 |
}
|
701 |
|
@@ -709,8 +764,10 @@ class SassScriptFunctions {
|
|
709 |
* @return new SassNumber The rounded number
|
710 |
* @throws SassScriptFunctionException If $value is not a number
|
711 |
*/
|
712 |
-
public static function floor($number)
|
|
|
713 |
SassLiteral::assertType($number, 'SassNumber');
|
|
|
714 |
return new SassNumber(floor($number->value).$number->units);
|
715 |
}
|
716 |
|
@@ -724,8 +781,10 @@ class SassScriptFunctions {
|
|
724 |
* @return new SassNumber The rounded number
|
725 |
* @throws SassScriptFunctionException If $number is not a number
|
726 |
*/
|
727 |
-
public static function round($number)
|
|
|
728 |
SassLiteral::assertType($number, 'SassNumber');
|
|
|
729 |
return new SassNumber(str_replace(',','.',round($number->value)).$number->units);
|
730 |
}
|
731 |
|
@@ -738,9 +797,11 @@ class SassScriptFunctions {
|
|
738 |
* @throws SassScriptFunctionException If $number1 or $number2 is not
|
739 |
* a number
|
740 |
*/
|
741 |
-
public static function comparable($number1, $number2)
|
|
|
742 |
SassLiteral::assertType($number1, 'SassNumber');
|
743 |
SassLiteral::assertType($number2, 'SassNumber');
|
|
|
744 |
return new SassBoolean($number1->isComparableTo($number2));
|
745 |
}
|
746 |
|
@@ -753,33 +814,38 @@ class SassScriptFunctions {
|
|
753 |
* @return new SassNumber The number as a percentage
|
754 |
* @throws SassScriptFunctionException If $number isn't a unitless number
|
755 |
*/
|
756 |
-
public static function percentage($number)
|
|
|
757 |
$number->value *= 100;
|
758 |
$number->units = '%';
|
|
|
759 |
return $number;
|
760 |
}
|
761 |
|
762 |
-
public static function max()
|
|
|
763 |
$max = func_get_arg(0);
|
764 |
foreach (func_get_args() as $var) {
|
765 |
if ($var instanceOf SassNumber && $var->op_gt($max)->value) {
|
766 |
$max = $var;
|
767 |
}
|
768 |
}
|
|
|
769 |
return $max;
|
770 |
}
|
771 |
|
772 |
-
public static function min()
|
|
|
773 |
$min = func_get_arg(0);
|
774 |
foreach (func_get_args() as $var) {
|
775 |
if ($var instanceOf SassNumber && $var->op_lt($min)->value) {
|
776 |
$min = $var;
|
777 |
}
|
778 |
}
|
|
|
779 |
return $min;
|
780 |
}
|
781 |
|
782 |
-
|
783 |
/**
|
784 |
* Inspects the unit of the number, returning it as a quoted string.
|
785 |
* Alias for units.
|
@@ -788,7 +854,8 @@ class SassScriptFunctions {
|
|
788 |
* @throws SassScriptFunctionException If $number is not a number
|
789 |
* @see units
|
790 |
*/
|
791 |
-
public static function unit($number)
|
|
|
792 |
return self::units($number);
|
793 |
}
|
794 |
|
@@ -798,8 +865,10 @@ class SassScriptFunctions {
|
|
798 |
* @return new SassString The units of the number
|
799 |
* @throws SassScriptFunctionException If $number is not a number
|
800 |
*/
|
801 |
-
public static function units($number)
|
|
|
802 |
SassLiteral::assertType($number, 'SassNumber');
|
|
|
803 |
return new SassString($number->units);
|
804 |
}
|
805 |
|
@@ -810,8 +879,10 @@ class SassScriptFunctions {
|
|
810 |
* @return new SassBoolean True if the number is unitless, false if it has units.
|
811 |
* @throws SassScriptFunctionException If $number is not a number
|
812 |
*/
|
813 |
-
public static function unitless($number)
|
|
|
814 |
SassLiteral::assertType($number, 'SassNumber');
|
|
|
815 |
return new SassBoolean($number->isUnitless());
|
816 |
}
|
817 |
|
@@ -827,8 +898,10 @@ class SassScriptFunctions {
|
|
827 |
* @throws SassScriptFunctionException If $string is not a string
|
828 |
* @see unquote
|
829 |
*/
|
830 |
-
public static function quote($string)
|
|
|
831 |
SassLiteral::assertType($string, 'SassString');
|
|
|
832 |
return new SassString('"'.$string->value.'"');
|
833 |
}
|
834 |
|
@@ -840,10 +913,12 @@ class SassScriptFunctions {
|
|
840 |
* @throws SassScriptFunctionException If $string is not a string
|
841 |
* @see quote
|
842 |
*/
|
843 |
-
public static function unquote($string)
|
|
|
844 |
if ($string instanceof SassString) {
|
845 |
return new SassString($string->value);
|
846 |
}
|
|
|
847 |
return $string;
|
848 |
}
|
849 |
|
@@ -853,8 +928,10 @@ class SassScriptFunctions {
|
|
853 |
* @return
|
854 |
* @throws SassScriptFunctionException If $string is not a string
|
855 |
*/
|
856 |
-
public static function get_var($string)
|
|
|
857 |
SassLiteral::assertType($string, 'SassString');
|
|
|
858 |
return new SassString($string->toVar());
|
859 |
}
|
860 |
|
@@ -867,10 +944,12 @@ class SassScriptFunctions {
|
|
867 |
* @param SassList - the list to count
|
868 |
* @return SassNumber
|
869 |
*/
|
870 |
-
public static function length($list)
|
|
|
871 |
if ($list instanceOf SassString) {
|
872 |
$list = new SassList($list->toString());
|
873 |
}
|
|
|
874 |
return new SassNumber($list->length());
|
875 |
}
|
876 |
|
@@ -880,7 +959,8 @@ class SassScriptFunctions {
|
|
880 |
* @param SassNumber - the value to get
|
881 |
* @return anything
|
882 |
*/
|
883 |
-
public static function nth($list, $n)
|
|
|
884 |
SassLiteral::assertType($n, 'SassNumber');
|
885 |
|
886 |
if ($list instanceof SassString) {
|
@@ -890,28 +970,33 @@ class SassScriptFunctions {
|
|
890 |
return $list->nth($n->value);
|
891 |
}
|
892 |
|
893 |
-
public static function join($one, $two, $sep = ', ')
|
|
|
894 |
return self::append($one, $two, $sep);
|
895 |
}
|
896 |
|
897 |
-
public static function append($list, $val, $sep = ', ')
|
|
|
898 |
if ($list instanceOf SassString) {
|
899 |
$list = new SassList($list->toString());
|
900 |
}
|
901 |
$list->append($val, $sep);
|
|
|
902 |
return $list;
|
903 |
}
|
904 |
|
905 |
-
public static function index($list, $value)
|
|
|
906 |
if (!($list instanceOf SassList)) {
|
907 |
$list = new SassList($list->toString());
|
908 |
}
|
|
|
909 |
return $list->index($value);
|
910 |
}
|
911 |
|
912 |
-
|
913 |
// New function zip allows several lists to be combined into one list of lists. For example: zip(1px 1px 3px, solid dashed solid, red green blue) becomes 1px solid red, 1px dashed green, 3px solid blue
|
914 |
-
function zip()
|
|
|
915 |
$result = new SassList('', ',');
|
916 |
foreach (func_get_args() as $i => $arg) {
|
917 |
$list = new SassList($arg);
|
@@ -920,6 +1005,7 @@ class SassScriptFunctions {
|
|
920 |
$result->value[$j]->value[] = (string) $val;
|
921 |
}
|
922 |
}
|
|
|
923 |
return $result;
|
924 |
}
|
925 |
|
@@ -934,7 +1020,8 @@ class SassScriptFunctions {
|
|
934 |
* @param anything - returns if Condition is true
|
935 |
* @param anything - returns if Condition is false
|
936 |
*/
|
937 |
-
public static function _if($condition, $if_true, $if_false)
|
|
|
938 |
return ($condition->value ? $if_true : $if_false);
|
939 |
}
|
940 |
|
@@ -945,8 +1032,10 @@ class SassScriptFunctions {
|
|
945 |
* @throws SassScriptFunctionException If $obj is not an instance of a
|
946 |
* SassLiteral
|
947 |
*/
|
948 |
-
public static function type_of($obj)
|
|
|
949 |
SassLiteral::assertType($obj, 'SassLiteral');
|
|
|
950 |
return new SassString($obj->typeOf);
|
951 |
}
|
952 |
|
@@ -957,7 +1046,8 @@ class SassScriptFunctions {
|
|
957 |
* @param float the maximum value
|
958 |
* @return the value clipped to the range
|
959 |
*/
|
960 |
-
public static function inRange($value, $min, $max)
|
|
|
961 |
return ($value < $min ? $min : ($value > $max ? $max : $value));
|
962 |
}
|
963 |
}
|
36 |
* @package PHamlP
|
37 |
* @subpackage Sass.script
|
38 |
*/
|
39 |
+
class SassScriptFunctions
|
40 |
+
{
|
41 |
const DECREASE = false;
|
42 |
const INCREASE = true;
|
43 |
|
44 |
public static $parser = FALSE;
|
45 |
+
public static function option($name)
|
46 |
+
{
|
47 |
$options = SassParser::$instance->getOptions();
|
48 |
if (isset($options[$name->value])) {
|
49 |
return new SassString($options[$name->value]);
|
50 |
}
|
51 |
+
|
52 |
return new SassBoolean(false);
|
53 |
}
|
54 |
|
67 |
* @return new SassColour SassColour object
|
68 |
* @throws SassScriptFunctionException if red, green, or blue are out of bounds
|
69 |
*/
|
70 |
+
public static function rgb($red, $green, $blue)
|
71 |
+
{
|
72 |
return self::rgba($red, $green, $blue, new SassNumber(1));
|
73 |
}
|
74 |
|
94 |
* colour components are out of bounds, or or the colour is not a colour, or
|
95 |
* alpha is out of bounds
|
96 |
*/
|
97 |
+
public static function rgba()
|
98 |
+
{
|
99 |
switch (func_num_args()) {
|
100 |
case 2:
|
101 |
$colour = func_get_arg(0);
|
103 |
SassLiteral::assertType($colour, 'SassColour');
|
104 |
SassLiteral::assertType($alpha, 'SassNumber');
|
105 |
SassLiteral::assertInRange($alpha, 0, 1);
|
106 |
+
|
107 |
return $colour->with(array('alpha' => $alpha->value));
|
108 |
break;
|
109 |
case 4:
|
110 |
$rgba = array();
|
111 |
$components = func_get_args();
|
112 |
$alpha = array_pop($components);
|
113 |
+
foreach ($components as $component) {
|
114 |
SassLiteral::assertType($component, 'SassNumber');
|
115 |
if ($component->units == '%') {
|
116 |
SassLiteral::assertInRange($component, 0, 100, '%');
|
117 |
$rgba[] = $component->value * 2.55;
|
118 |
+
} else {
|
|
|
119 |
SassLiteral::assertInRange($component, 0, 255);
|
120 |
$rgba[] = $component->value;
|
121 |
}
|
123 |
SassLiteral::assertType($alpha, 'SassNumber');
|
124 |
SassLiteral::assertInRange($alpha, 0, 1);
|
125 |
$rgba[] = $alpha->value;
|
126 |
+
|
127 |
return new SassColour($rgba);
|
128 |
break;
|
129 |
default:
|
144 |
* @return new SassColour The resulting colour
|
145 |
* @throws SassScriptFunctionException if saturation or lightness are out of bounds
|
146 |
*/
|
147 |
+
public static function hsl($h, $s, $l)
|
148 |
+
{
|
149 |
SassLiteral::assertInRange($s, 0, 100, '%');
|
150 |
SassLiteral::assertInRange($l, 0, 100, '%');
|
151 |
+
|
152 |
return self::hsla($h, $s, $l, new SassNumber(1));
|
153 |
}
|
154 |
|
166 |
* @throws SassScriptFunctionException if saturation, lightness or alpha are
|
167 |
* out of bounds
|
168 |
*/
|
169 |
+
public static function hsla($h, $s, $l, $a)
|
170 |
+
{
|
171 |
SassLiteral::assertType($h, 'SassNumber');
|
172 |
SassLiteral::assertType($s, 'SassNumber');
|
173 |
SassLiteral::assertType($l, 'SassNumber');
|
175 |
SassLiteral::assertInRange($s, 0, 100, '%');
|
176 |
SassLiteral::assertInRange($l, 0, 100, '%');
|
177 |
SassLiteral::assertInRange($a, 0, 1);
|
178 |
+
|
179 |
return new SassColour(array('hue' => $h, 'saturation' => $s, 'lightness' => $l, 'alpha' => $a));
|
180 |
}
|
181 |
|
189 |
* @return new SassNumber The red component of colour
|
190 |
* @throws SassScriptFunctionException If $colour is not a colour
|
191 |
*/
|
192 |
+
public static function red($colour)
|
193 |
+
{
|
194 |
SassLiteral::assertType($colour, 'SassColour');
|
195 |
+
|
196 |
return new SassNumber($colour->red);
|
197 |
}
|
198 |
|
202 |
* @return new SassNumber The green component of colour
|
203 |
* @throws SassScriptFunctionException If $colour is not a colour
|
204 |
*/
|
205 |
+
public static function green($colour)
|
206 |
+
{
|
207 |
SassLiteral::assertType($colour, 'SassColour');
|
208 |
+
|
209 |
return new SassNumber($colour->green);
|
210 |
}
|
211 |
|
215 |
* @return new SassNumber The blue component of colour
|
216 |
* @throws SassScriptFunctionException If $colour is not a colour
|
217 |
*/
|
218 |
+
public static function blue($colour)
|
219 |
+
{
|
220 |
SassLiteral::assertType($colour, 'SassColour');
|
221 |
+
|
222 |
return new SassNumber($colour->blue);
|
223 |
}
|
224 |
|
228 |
* @return new SassNumber The hue component of colour
|
229 |
* @throws SassScriptFunctionException If $colour is not a colour
|
230 |
*/
|
231 |
+
public static function hue($colour)
|
232 |
+
{
|
233 |
SassLiteral::assertType($colour, 'SassColour');
|
234 |
+
|
235 |
return new SassNumber($colour->getHue() . 'deg');
|
236 |
}
|
237 |
|
241 |
* @return new SassNumber The saturation component of colour
|
242 |
* @throws SassScriptFunctionException If $colour is not a colour
|
243 |
*/
|
244 |
+
public static function saturation($colour)
|
245 |
+
{
|
246 |
SassLiteral::assertType($colour, 'SassColour');
|
247 |
+
|
248 |
return new SassNumber($colour->getSaturation() . '%');
|
249 |
}
|
250 |
|
254 |
* @return new SassNumber The lightness component of colour
|
255 |
* @throws SassScriptFunctionException If $colour is not a colour
|
256 |
*/
|
257 |
+
public static function lightness($colour)
|
258 |
+
{
|
259 |
SassLiteral::assertType($colour, 'SassColour');
|
260 |
+
|
261 |
return new SassNumber($colour->getLightness() . '%');
|
262 |
}
|
263 |
|
269 |
*
|
270 |
* RL modified so that the filter: alpha function doesn't bork
|
271 |
*/
|
272 |
+
public static function alpha($colour)
|
273 |
+
{
|
274 |
try {
|
275 |
SassLiteral::assertType($colour, 'SassColour');
|
276 |
+
} catch (Exception $e) {
|
|
|
277 |
return new SassString('alpha(100)');
|
278 |
}
|
279 |
+
|
280 |
return new SassNumber($colour->alpha);
|
281 |
}
|
282 |
|
286 |
* @return new SassNumber The alpha component (opacity) of colour
|
287 |
* @throws SassScriptFunctionException If $colour is not a colour
|
288 |
*/
|
289 |
+
public static function opacity($colour)
|
290 |
+
{
|
291 |
SassLiteral::assertType($colour, 'SassColour');
|
292 |
+
|
293 |
return new SassNumber($colour->alpha);
|
294 |
}
|
295 |
|
305 |
* @throws SassScriptFunctionException If $colour is not a colour or
|
306 |
* $degrees is not a number
|
307 |
*/
|
308 |
+
public static function adjust_hue($colour, $degrees)
|
309 |
+
{
|
310 |
SassLiteral::assertType($colour, 'SassColour');
|
311 |
SassLiteral::assertType($degrees, 'SassNumber');
|
312 |
+
|
313 |
return $colour->with(array('hue' => $colour->getHue(true) + $degrees->value));
|
314 |
}
|
315 |
|
329 |
* $amount is not a number
|
330 |
* @see lighten_rel
|
331 |
*/
|
332 |
+
public static function lighten($colour, $amount, $ofCurrent = false)
|
333 |
+
{
|
334 |
return self::adjust($colour, $amount, $ofCurrent, 'lightness', self::INCREASE, 0, 100, '%');
|
335 |
}
|
336 |
|
350 |
* $amount is not a number
|
351 |
* @see adjust
|
352 |
*/
|
353 |
+
public static function darken($colour, $amount, $ofCurrent = false)
|
354 |
+
{
|
355 |
return self::adjust($colour, $amount, $ofCurrent, 'lightness', self::DECREASE, 0, 100, '%');
|
356 |
}
|
357 |
|
371 |
* $amount is not a number
|
372 |
* @see adjust
|
373 |
*/
|
374 |
+
public static function saturate($colour, $amount, $ofCurrent = false)
|
375 |
+
{
|
376 |
return self::adjust($colour, $amount, $ofCurrent, 'saturation', self::INCREASE, 0, 100, '%');
|
377 |
}
|
378 |
|
392 |
* $amount is not a number
|
393 |
* @see adjust
|
394 |
*/
|
395 |
+
public static function desaturate($colour, $amount, $ofCurrent = false)
|
396 |
+
{
|
397 |
return self::adjust($colour, $amount, $ofCurrent, 'saturation', self::DECREASE, 0, 100, '%');
|
398 |
}
|
399 |
|
411 |
* $amount is not a number
|
412 |
* @see opacify_rel
|
413 |
*/
|
414 |
+
public static function opacify($colour, $amount, $ofCurrent = false)
|
415 |
+
{
|
416 |
$units = self::units($amount);
|
417 |
+
|
418 |
return self::adjust($colour, $amount, $ofCurrent, 'alpha', self::INCREASE, 0, ($units === '%' ? 100 : 1), $units);
|
419 |
}
|
420 |
|
431 |
* @throws SassScriptFunctionException If $colour is not a colour or
|
432 |
* $amount is not a number
|
433 |
*/
|
434 |
+
public static function transparentize($colour, $amount, $ofCurrent = false)
|
435 |
+
{
|
436 |
$units = self::units($amount);
|
437 |
+
|
438 |
return self::adjust($colour, $amount, $ofCurrent, 'alpha', self::DECREASE, 0, ($units === '%' ? 100 : 1), $units);
|
439 |
}
|
440 |
|
450 |
* $amount is not a number
|
451 |
* @see opacify
|
452 |
*/
|
453 |
+
public static function fade_in($colour, $amount, $ofCurrent = false)
|
454 |
+
{
|
455 |
return self::opacify($colour, $amount, $ofCurrent);
|
456 |
}
|
457 |
|
467 |
* $amount is not a number
|
468 |
* @see transparentize
|
469 |
*/
|
470 |
+
public static function fade_out($colour, $amount, $ofCurrent = false)
|
471 |
+
{
|
472 |
return self::transparentize($colour, $amount, $ofCurrent);
|
473 |
}
|
474 |
|
479 |
* @return new SassColour The comlemented colour
|
480 |
* @uses adjust_hue()
|
481 |
*/
|
482 |
+
public static function complement($colour)
|
483 |
+
{
|
484 |
// return self::adjust($colour, new SassNumber('180deg'), true, 'hue', self::INCREASE, 0, 360, '');
|
485 |
return self::adjust_hue($colour, new SassNumber('180deg'));
|
486 |
}
|
491 |
* @return new SassColour The greyscale colour
|
492 |
* @see desaturate
|
493 |
*/
|
494 |
+
public static function grayscale($colour)
|
495 |
+
{
|
496 |
return self::desaturate($colour, new SassNumber(100));
|
497 |
}
|
498 |
|
503 |
* @return new SassColour The greyscale colour
|
504 |
* @see desaturate
|
505 |
*/
|
506 |
+
public static function greyscale($colour)
|
507 |
+
{
|
508 |
return self::desaturate($colour, new SassNumber(100));
|
509 |
}
|
510 |
|
514 |
* @param SassColour: the colour
|
515 |
* @return new SassColour: the inverted colour
|
516 |
*/
|
517 |
+
public static function invert($colour)
|
518 |
+
{
|
519 |
SassLiteral::assertType($colour, 'SassColour');
|
520 |
+
|
521 |
return $colour->with(array(
|
522 |
'red' => 255 - $colour->getRed(true),
|
523 |
'blue' => 255 - $colour->getBlue(true),
|
546 |
* @throws SassScriptFunctionException If $colour1 or $colour2 is
|
547 |
* not a colour
|
548 |
*/
|
549 |
+
public static function mix($colour1, $colour2, $weight = '50%')
|
550 |
+
{
|
551 |
if (is_object($weight)) {
|
552 |
$weight = new SassNumber($weight);
|
553 |
}
|
603 |
* @param SassNumber (red, green, blue, hue, saturation, lightness, alpha) - the amount(s) to adjust by
|
604 |
* @return SassColour
|
605 |
*/
|
606 |
+
public static function adjust_color($color, $red = 0, $green = 0, $blue = 0, $hue = 0, $saturation = 0, $lightness = 0, $alpha = 0)
|
607 |
+
{
|
608 |
foreach (array('red', 'green', 'blue', 'hue', 'saturation', 'lightness', 'alpha') as $property) {
|
609 |
$obj = $$property;
|
610 |
$color = self::adjust($color, $$property, FALSE, $property, self::INCREASE, 0, 255);
|
619 |
* @param SassNumber (red, green, blue, saturation, lightness, alpha) - the amount(s) to scale by
|
620 |
* @return SassColour
|
621 |
*/
|
622 |
+
public static function scale_color($color, $red = 0, $green = 0, $blue = 0, $saturation = 0, $lightness = 0, $alpha = 0)
|
623 |
+
{
|
624 |
$maxes = array(
|
625 |
'red' => 255,
|
626 |
'green' => 255,
|
637 |
$color->$property = $color->$property + $diff * $scale;
|
638 |
}
|
639 |
$color->hsl2rgb();
|
640 |
+
|
641 |
return $color;
|
642 |
}
|
643 |
|
647 |
* @param SassNumber (red, green, blue, hue, saturation, lightness, alpha) - the amounts to scale by
|
648 |
* @return SassColour
|
649 |
*/
|
650 |
+
public static function change_color($color, $red = false, $green = false, $blue = false, $hue = false, $saturation = false, $lightness = false, $alpha = false)
|
651 |
+
{
|
652 |
$attrs = array();
|
653 |
foreach (array('red', 'green', 'blue', 'hue', 'saturation', 'lightness', 'alpha') as $i => $property) {
|
654 |
$obj = $$property;
|
656 |
$attrs[$property] = $obj->value;
|
657 |
}
|
658 |
}
|
659 |
+
|
660 |
return $color->with($attrs);
|
661 |
}
|
662 |
|
672 |
* @param float maximum value the amount can bemixed
|
673 |
* @param string amount units
|
674 |
*/
|
675 |
+
public static function adjust($colour, $amount, $ofCurrent, $att, $op, $min, $max, $units='')
|
676 |
+
{
|
677 |
SassLiteral::assertType($colour, 'SassColour');
|
678 |
SassLiteral::assertType($amount, 'SassNumber');
|
679 |
// SassLiteral::assertInRange($amount, $min, $max, $units);
|
689 |
$colour->hsl2rgb();
|
690 |
$colour->$att = $ofCurrent ? $colour->$att * (1 + ($amount * ($op === self::INCREASE ? 1 : -1))/100) : $colour->$att + ($amount * ($op === self::INCREASE ? 1 : -1));
|
691 |
$colour->rgb2hsl();
|
692 |
+
} else {
|
|
|
693 |
$colour->rgb2hsl();
|
694 |
$colour->$att = $ofCurrent ? $colour->$att * (1 + ($amount * ($op === self::INCREASE ? 1 : -1))/100) : $colour->$att + ($amount * ($op === self::INCREASE ? 1 : -1));
|
695 |
$colour->$att = max($min, min($max, $colour->$att));
|
696 |
$colour->hsl2rgb();
|
697 |
}
|
698 |
+
|
699 |
return $colour;
|
700 |
}
|
701 |
|
703 |
* returns an IE hex string for a color with an alpha channel
|
704 |
* suitable for passing to IE filters.
|
705 |
*/
|
706 |
+
public static function ie_hex_str($color)
|
707 |
+
{
|
708 |
if (!($color instanceof SassColour)) {
|
709 |
$color = new SassColour($color);
|
710 |
}
|
711 |
$alpha = str_replace(',','.',round($color->alpha * 255));
|
712 |
$alpha_str = str_pad(dechex($alpha), 2, '0', STR_PAD_LEFT);
|
713 |
$col = $color->asHex(FALSE);
|
714 |
+
|
715 |
return new SassString(strtoupper('#' . $alpha_str . $col));
|
716 |
}
|
717 |
|
730 |
* @return SassNumber The absolute value of the number
|
731 |
* @throws SassScriptFunctionException If $number is not a number
|
732 |
*/
|
733 |
+
public static function abs($number)
|
734 |
+
{
|
735 |
SassLiteral::assertType($number, 'SassNumber');
|
736 |
+
|
737 |
return new SassNumber(abs($number->value).$number->units);
|
738 |
}
|
739 |
|
747 |
* @return new SassNumber The rounded number
|
748 |
* @throws SassScriptFunctionException If $number is not a number
|
749 |
*/
|
750 |
+
public static function ceil($number)
|
751 |
+
{
|
752 |
SassLiteral::assertType($number, 'SassNumber');
|
753 |
+
|
754 |
return new SassNumber(ceil($number->value).$number->units);
|
755 |
}
|
756 |
|
764 |
* @return new SassNumber The rounded number
|
765 |
* @throws SassScriptFunctionException If $value is not a number
|
766 |
*/
|
767 |
+
public static function floor($number)
|
768 |
+
{
|
769 |
SassLiteral::assertType($number, 'SassNumber');
|
770 |
+
|
771 |
return new SassNumber(floor($number->value).$number->units);
|
772 |
}
|
773 |
|
781 |
* @return new SassNumber The rounded number
|
782 |
* @throws SassScriptFunctionException If $number is not a number
|
783 |
*/
|
784 |
+
public static function round($number)
|
785 |
+
{
|
786 |
SassLiteral::assertType($number, 'SassNumber');
|
787 |
+
|
788 |
return new SassNumber(str_replace(',','.',round($number->value)).$number->units);
|
789 |
}
|
790 |
|
797 |
* @throws SassScriptFunctionException If $number1 or $number2 is not
|
798 |
* a number
|
799 |
*/
|
800 |
+
public static function comparable($number1, $number2)
|
801 |
+
{
|
802 |
SassLiteral::assertType($number1, 'SassNumber');
|
803 |
SassLiteral::assertType($number2, 'SassNumber');
|
804 |
+
|
805 |
return new SassBoolean($number1->isComparableTo($number2));
|
806 |
}
|
807 |
|
814 |
* @return new SassNumber The number as a percentage
|
815 |
* @throws SassScriptFunctionException If $number isn't a unitless number
|
816 |
*/
|
817 |
+
public static function percentage($number)
|
818 |
+
{
|
819 |
$number->value *= 100;
|
820 |
$number->units = '%';
|
821 |
+
|
822 |
return $number;
|
823 |
}
|
824 |
|
825 |
+
public static function max()
|
826 |
+
{
|
827 |
$max = func_get_arg(0);
|
828 |
foreach (func_get_args() as $var) {
|
829 |
if ($var instanceOf SassNumber && $var->op_gt($max)->value) {
|
830 |
$max = $var;
|
831 |
}
|
832 |
}
|
833 |
+
|
834 |
return $max;
|
835 |
}
|
836 |
|
837 |
+
public static function min()
|
838 |
+
{
|
839 |
$min = func_get_arg(0);
|
840 |
foreach (func_get_args() as $var) {
|
841 |
if ($var instanceOf SassNumber && $var->op_lt($min)->value) {
|
842 |
$min = $var;
|
843 |
}
|
844 |
}
|
845 |
+
|
846 |
return $min;
|
847 |
}
|
848 |
|
|
|
849 |
/**
|
850 |
* Inspects the unit of the number, returning it as a quoted string.
|
851 |
* Alias for units.
|
854 |
* @throws SassScriptFunctionException If $number is not a number
|
855 |
* @see units
|
856 |
*/
|
857 |
+
public static function unit($number)
|
858 |
+
{
|
859 |
return self::units($number);
|
860 |
}
|
861 |
|
865 |
* @return new SassString The units of the number
|
866 |
* @throws SassScriptFunctionException If $number is not a number
|
867 |
*/
|
868 |
+
public static function units($number)
|
869 |
+
{
|
870 |
SassLiteral::assertType($number, 'SassNumber');
|
871 |
+
|
872 |
return new SassString($number->units);
|
873 |
}
|
874 |
|
879 |
* @return new SassBoolean True if the number is unitless, false if it has units.
|
880 |
* @throws SassScriptFunctionException If $number is not a number
|
881 |
*/
|
882 |
+
public static function unitless($number)
|
883 |
+
{
|
884 |
SassLiteral::assertType($number, 'SassNumber');
|
885 |
+
|
886 |
return new SassBoolean($number->isUnitless());
|
887 |
}
|
888 |
|
898 |
* @throws SassScriptFunctionException If $string is not a string
|
899 |
* @see unquote
|
900 |
*/
|
901 |
+
public static function quote($string)
|
902 |
+
{
|
903 |
SassLiteral::assertType($string, 'SassString');
|
904 |
+
|
905 |
return new SassString('"'.$string->value.'"');
|
906 |
}
|
907 |
|
913 |
* @throws SassScriptFunctionException If $string is not a string
|
914 |
* @see quote
|
915 |
*/
|
916 |
+
public static function unquote($string)
|
917 |
+
{
|
918 |
if ($string instanceof SassString) {
|
919 |
return new SassString($string->value);
|
920 |
}
|
921 |
+
|
922 |
return $string;
|
923 |
}
|
924 |
|
928 |
* @return
|
929 |
* @throws SassScriptFunctionException If $string is not a string
|
930 |
*/
|
931 |
+
public static function get_var($string)
|
932 |
+
{
|
933 |
SassLiteral::assertType($string, 'SassString');
|
934 |
+
|
935 |
return new SassString($string->toVar());
|
936 |
}
|
937 |
|
944 |
* @param SassList - the list to count
|
945 |
* @return SassNumber
|
946 |
*/
|
947 |
+
public static function length($list)
|
948 |
+
{
|
949 |
if ($list instanceOf SassString) {
|
950 |
$list = new SassList($list->toString());
|
951 |
}
|
952 |
+
|
953 |
return new SassNumber($list->length());
|
954 |
}
|
955 |
|
959 |
* @param SassNumber - the value to get
|
960 |
* @return anything
|
961 |
*/
|
962 |
+
public static function nth($list, $n)
|
963 |
+
{
|
964 |
SassLiteral::assertType($n, 'SassNumber');
|
965 |
|
966 |
if ($list instanceof SassString) {
|
970 |
return $list->nth($n->value);
|
971 |
}
|
972 |
|
973 |
+
public static function join($one, $two, $sep = ', ')
|
974 |
+
{
|
975 |
return self::append($one, $two, $sep);
|
976 |
}
|
977 |
|
978 |
+
public static function append($list, $val, $sep = ', ')
|
979 |
+
{
|
980 |
if ($list instanceOf SassString) {
|
981 |
$list = new SassList($list->toString());
|
982 |
}
|
983 |
$list->append($val, $sep);
|
984 |
+
|
985 |
return $list;
|
986 |
}
|
987 |
|
988 |
+
public static function index($list, $value)
|
989 |
+
{
|
990 |
if (!($list instanceOf SassList)) {
|
991 |
$list = new SassList($list->toString());
|
992 |
}
|
993 |
+
|
994 |
return $list->index($value);
|
995 |
}
|
996 |
|
|
|
997 |
// New function zip allows several lists to be combined into one list of lists. For example: zip(1px 1px 3px, solid dashed solid, red green blue) becomes 1px solid red, 1px dashed green, 3px solid blue
|
998 |
+
public function zip()
|
999 |
+
{
|
1000 |
$result = new SassList('', ',');
|
1001 |
foreach (func_get_args() as $i => $arg) {
|
1002 |
$list = new SassList($arg);
|
1005 |
$result->value[$j]->value[] = (string) $val;
|
1006 |
}
|
1007 |
}
|
1008 |
+
|
1009 |
return $result;
|
1010 |
}
|
1011 |
|
1020 |
* @param anything - returns if Condition is true
|
1021 |
* @param anything - returns if Condition is false
|
1022 |
*/
|
1023 |
+
public static function _if($condition, $if_true, $if_false)
|
1024 |
+
{
|
1025 |
return ($condition->value ? $if_true : $if_false);
|
1026 |
}
|
1027 |
|
1032 |
* @throws SassScriptFunctionException If $obj is not an instance of a
|
1033 |
* SassLiteral
|
1034 |
*/
|
1035 |
+
public static function type_of($obj)
|
1036 |
+
{
|
1037 |
SassLiteral::assertType($obj, 'SassLiteral');
|
1038 |
+
|
1039 |
return new SassString($obj->typeOf);
|
1040 |
}
|
1041 |
|
1046 |
* @param float the maximum value
|
1047 |
* @return the value clipped to the range
|
1048 |
*/
|
1049 |
+
public static function inRange($value, $min, $max)
|
1050 |
+
{
|
1051 |
return ($value < $min ? $min : ($value > $max ? $max : $value));
|
1052 |
}
|
1053 |
}
|
lib/phpsass/script/SassScriptLexer.php
CHANGED
@@ -9,14 +9,14 @@
|
|
9 |
* @subpackage Sass.script
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
-
require_once
|
14 |
-
require_once
|
15 |
-
require_once
|
16 |
-
require_once
|
17 |
-
require_once
|
18 |
-
require_once
|
19 |
-
require_once
|
20 |
|
21 |
/**
|
22 |
* SassScriptLexer class.
|
@@ -26,13 +26,14 @@ require_once('SassScriptVariable.php');
|
|
26 |
* @package PHamlP
|
27 |
* @subpackage Sass.script
|
28 |
*/
|
29 |
-
class SassScriptLexer
|
|
|
30 |
const MATCH_WHITESPACE = '/^\s+/';
|
31 |
|
32 |
/**
|
33 |
* Static holder for last instance of SassScriptLexer
|
34 |
*/
|
35 |
-
static
|
36 |
|
37 |
/**
|
38 |
* @var SassScriptParser the parser object
|
@@ -43,7 +44,8 @@ class SassScriptLexer {
|
|
43 |
* SassScriptLexer constructor.
|
44 |
* @return SassScriptLexer
|
45 |
*/
|
46 |
-
public function __construct($parser)
|
|
|
47 |
$this->parser = $parser;
|
48 |
self::$instance = $this;
|
49 |
}
|
@@ -54,7 +56,8 @@ class SassScriptLexer {
|
|
54 |
* @param SassContext the context in which the expression is lexed
|
55 |
* @return array tokens
|
56 |
*/
|
57 |
-
public function lex($string, $context)
|
|
|
58 |
// if it's already lexed, just return it as-is
|
59 |
if (is_object($string)) {
|
60 |
return array($string);
|
@@ -66,43 +69,34 @@ class SassScriptLexer {
|
|
66 |
while ($string !== false) {
|
67 |
if (($match = $this->isWhitespace($string)) !== false) {
|
68 |
$tokens[] = null;
|
69 |
-
}
|
70 |
-
elseif (($match = SassScriptFunction::isa($string)) !== false) {
|
71 |
preg_match(SassScriptFunction::MATCH_FUNC, $match, $matches);
|
72 |
$args = array();
|
73 |
foreach (SassScriptFunction::extractArgs($matches[SassScriptFunction::ARGS], false, $context) as $key => $expression) {
|
74 |
$args[$key] = $this->parser->evaluate($expression, $context);
|
75 |
}
|
76 |
$tokens[] = new SassScriptFunction($matches[SassScriptFunction::NAME], $args);
|
77 |
-
}
|
78 |
-
elseif (($match = SassBoolean::isa($string)) !== false) {
|
79 |
$tokens[] = new SassBoolean($match);
|
80 |
-
}
|
81 |
-
elseif (($match = SassColour::isa($string)) !== false) {
|
82 |
$tokens[] = new SassColour($match);
|
83 |
-
}
|
84 |
-
elseif (($match = SassNumber::isa($string)) !== false) {
|
85 |
$tokens[] = new SassNumber($match);
|
86 |
-
}
|
87 |
-
elseif (($match = SassString::isa($string)) !== false) {
|
88 |
$stringed = new SassString($match);
|
89 |
if (strlen($stringed->quote) == 0 && SassList::isa($string) !== false) {
|
90 |
$tokens[] = new SassList($string);
|
91 |
} else {
|
92 |
$tokens[] = $stringed;
|
93 |
}
|
94 |
-
}
|
95 |
-
elseif ($string == '()') {
|
96 |
$match = $string;
|
97 |
$tokens[] = new SassList($match);
|
98 |
-
}
|
99 |
-
elseif (($match = SassScriptOperation::isa($string)) !== false) {
|
100 |
$tokens[] = new SassScriptOperation($match);
|
101 |
-
}
|
102 |
-
elseif (($match = SassScriptVariable::isa($string)) !== false) {
|
103 |
$tokens[] = new SassScriptVariable($match);
|
104 |
-
}
|
105 |
-
else {
|
106 |
$_string = $string;
|
107 |
$match = '';
|
108 |
while (strlen($_string) && !$this->isWhitespace($_string)) {
|
@@ -118,6 +112,7 @@ class SassScriptLexer {
|
|
118 |
}
|
119 |
$string = substr($string, strlen($match));
|
120 |
}
|
|
|
121 |
return $tokens;
|
122 |
}
|
123 |
|
@@ -127,7 +122,8 @@ class SassScriptLexer {
|
|
127 |
* @param string the subject string
|
128 |
* @return mixed match at the start of the string or false if no match
|
129 |
*/
|
130 |
-
public function isWhitespace($subject)
|
|
|
131 |
return (preg_match(self::MATCH_WHITESPACE, $subject, $matches) ? $matches[0] : false);
|
132 |
}
|
133 |
}
|
9 |
* @subpackage Sass.script
|
10 |
*/
|
11 |
|
12 |
+
require_once 'literals/SassBoolean.php';
|
13 |
+
require_once 'literals/SassColour.php';
|
14 |
+
require_once 'literals/SassNumber.php';
|
15 |
+
require_once 'literals/SassString.php';
|
16 |
+
require_once 'literals/SassList.php';
|
17 |
+
require_once 'SassScriptFunction.php';
|
18 |
+
require_once 'SassScriptOperation.php';
|
19 |
+
require_once 'SassScriptVariable.php';
|
20 |
|
21 |
/**
|
22 |
* SassScriptLexer class.
|
26 |
* @package PHamlP
|
27 |
* @subpackage Sass.script
|
28 |
*/
|
29 |
+
class SassScriptLexer
|
30 |
+
{
|
31 |
const MATCH_WHITESPACE = '/^\s+/';
|
32 |
|
33 |
/**
|
34 |
* Static holder for last instance of SassScriptLexer
|
35 |
*/
|
36 |
+
public static $instance;
|
37 |
|
38 |
/**
|
39 |
* @var SassScriptParser the parser object
|
44 |
* SassScriptLexer constructor.
|
45 |
* @return SassScriptLexer
|
46 |
*/
|
47 |
+
public function __construct($parser)
|
48 |
+
{
|
49 |
$this->parser = $parser;
|
50 |
self::$instance = $this;
|
51 |
}
|
56 |
* @param SassContext the context in which the expression is lexed
|
57 |
* @return array tokens
|
58 |
*/
|
59 |
+
public function lex($string, $context)
|
60 |
+
{
|
61 |
// if it's already lexed, just return it as-is
|
62 |
if (is_object($string)) {
|
63 |
return array($string);
|
69 |
while ($string !== false) {
|
70 |
if (($match = $this->isWhitespace($string)) !== false) {
|
71 |
$tokens[] = null;
|
72 |
+
} elseif (($match = SassScriptFunction::isa($string)) !== false) {
|
|
|
73 |
preg_match(SassScriptFunction::MATCH_FUNC, $match, $matches);
|
74 |
$args = array();
|
75 |
foreach (SassScriptFunction::extractArgs($matches[SassScriptFunction::ARGS], false, $context) as $key => $expression) {
|
76 |
$args[$key] = $this->parser->evaluate($expression, $context);
|
77 |
}
|
78 |
$tokens[] = new SassScriptFunction($matches[SassScriptFunction::NAME], $args);
|
79 |
+
} elseif (($match = SassBoolean::isa($string)) !== false) {
|
|
|
80 |
$tokens[] = new SassBoolean($match);
|
81 |
+
} elseif (($match = SassColour::isa($string)) !== false) {
|
|
|
82 |
$tokens[] = new SassColour($match);
|
83 |
+
} elseif (($match = SassNumber::isa($string)) !== false) {
|
|
|
84 |
$tokens[] = new SassNumber($match);
|
85 |
+
} elseif (($match = SassString::isa($string)) !== false) {
|
|
|
86 |
$stringed = new SassString($match);
|
87 |
if (strlen($stringed->quote) == 0 && SassList::isa($string) !== false) {
|
88 |
$tokens[] = new SassList($string);
|
89 |
} else {
|
90 |
$tokens[] = $stringed;
|
91 |
}
|
92 |
+
} elseif ($string == '()') {
|
|
|
93 |
$match = $string;
|
94 |
$tokens[] = new SassList($match);
|
95 |
+
} elseif (($match = SassScriptOperation::isa($string)) !== false) {
|
|
|
96 |
$tokens[] = new SassScriptOperation($match);
|
97 |
+
} elseif (($match = SassScriptVariable::isa($string)) !== false) {
|
|
|
98 |
$tokens[] = new SassScriptVariable($match);
|
99 |
+
} else {
|
|
|
100 |
$_string = $string;
|
101 |
$match = '';
|
102 |
while (strlen($_string) && !$this->isWhitespace($_string)) {
|
112 |
}
|
113 |
$string = substr($string, strlen($match));
|
114 |
}
|
115 |
+
|
116 |
return $tokens;
|
117 |
}
|
118 |
|
122 |
* @param string the subject string
|
123 |
* @return mixed match at the start of the string or false if no match
|
124 |
*/
|
125 |
+
public function isWhitespace($subject)
|
126 |
+
{
|
127 |
return (preg_match(self::MATCH_WHITESPACE, $subject, $matches) ? $matches[0] : false);
|
128 |
}
|
129 |
}
|
lib/phpsass/script/SassScriptOperation.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.script
|
17 |
*/
|
18 |
-
class SassScriptOperation
|
|
|
19 |
const MATCH = '/^(\(|\)|\+|-|\*|\/|%|<=|>=|<|>|==|!=|=|#{|}|,|and\b|or\b|xor\b|not\b)/';
|
20 |
|
21 |
/**
|
@@ -82,7 +83,8 @@ class SassScriptOperation {
|
|
82 |
* @param mixed string: operator symbol; array: operator token
|
83 |
* @return SassScriptOperation
|
84 |
*/
|
85 |
-
public function __construct($operation)
|
|
|
86 |
if (is_string($operation)) {
|
87 |
$operation = self::$operators[$operation];
|
88 |
}
|
@@ -100,11 +102,11 @@ class SassScriptOperation {
|
|
100 |
* @return mixed value of the property
|
101 |
* @throws SassScriptOperationException if the property does not exist
|
102 |
*/
|
103 |
-
public function __get($name)
|
|
|
104 |
if (property_exists($this, $name)) {
|
105 |
return $this->$name;
|
106 |
-
}
|
107 |
-
else {
|
108 |
throw new SassScriptOperationException('Unknown property: ' . $name, SassScriptParser::$context->node);
|
109 |
}
|
110 |
}
|
@@ -116,7 +118,8 @@ class SassScriptOperation {
|
|
116 |
* @throws SassScriptOperationException if the oprand count is incorrect or
|
117 |
* the operation is undefined
|
118 |
*/
|
119 |
-
public function perform($operands)
|
|
|
120 |
if (count($operands) !== $this->operandCount) {
|
121 |
throw new SassScriptOperationException('Incorrect operand count for ' . get_class($operands[0]) . '; expected ' . $this->operandCount . ', received ' . count($operands), SassScriptParser::$context->node);
|
122 |
}
|
@@ -136,8 +139,7 @@ class SassScriptOperation {
|
|
136 |
|
137 |
if (count($operands) > 1 && is_null($operands[1])) {
|
138 |
$operation = 'op_unary_' . $this->operator;
|
139 |
-
}
|
140 |
-
else {
|
141 |
$operation = 'op_' . $this->operator;
|
142 |
if ($this->associativity == 'l') {
|
143 |
$operands = array_reverse($operands);
|
@@ -146,6 +148,7 @@ class SassScriptOperation {
|
|
146 |
|
147 |
if (method_exists($operands[0], $operation)) {
|
148 |
$op = clone $operands[0];
|
|
|
149 |
return $op->$operation(!empty($operands[1]) ? $operands[1] : null);
|
150 |
}
|
151 |
|
@@ -168,19 +171,22 @@ class SassScriptOperation {
|
|
168 |
* @param string the subject string
|
169 |
* @return mixed match at the start of the string or false if no match
|
170 |
*/
|
171 |
-
public static function isa($subject)
|
|
|
172 |
# begins with a "/x", almost always a path without quotes.
|
173 |
if (preg_match('/^\/[^0-9\.\-\s]+/', $subject)) {
|
174 |
return FALSE;
|
175 |
}
|
|
|
176 |
return (preg_match(self::MATCH, $subject, $matches) ? trim($matches[1]) : false);
|
177 |
}
|
178 |
|
179 |
/**
|
180 |
* Converts the operation back into it's SASS representation
|
181 |
*/
|
182 |
-
public function __toString()
|
183 |
-
|
|
|
184 |
if ($operator[0] == trim($this->operator)) {
|
185 |
return $char;
|
186 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.script
|
17 |
*/
|
18 |
+
class SassScriptOperation
|
19 |
+
{
|
20 |
const MATCH = '/^(\(|\)|\+|-|\*|\/|%|<=|>=|<|>|==|!=|=|#{|}|,|and\b|or\b|xor\b|not\b)/';
|
21 |
|
22 |
/**
|
83 |
* @param mixed string: operator symbol; array: operator token
|
84 |
* @return SassScriptOperation
|
85 |
*/
|
86 |
+
public function __construct($operation)
|
87 |
+
{
|
88 |
if (is_string($operation)) {
|
89 |
$operation = self::$operators[$operation];
|
90 |
}
|
102 |
* @return mixed value of the property
|
103 |
* @throws SassScriptOperationException if the property does not exist
|
104 |
*/
|
105 |
+
public function __get($name)
|
106 |
+
{
|
107 |
if (property_exists($this, $name)) {
|
108 |
return $this->$name;
|
109 |
+
} else {
|
|
|
110 |
throw new SassScriptOperationException('Unknown property: ' . $name, SassScriptParser::$context->node);
|
111 |
}
|
112 |
}
|
118 |
* @throws SassScriptOperationException if the oprand count is incorrect or
|
119 |
* the operation is undefined
|
120 |
*/
|
121 |
+
public function perform($operands)
|
122 |
+
{
|
123 |
if (count($operands) !== $this->operandCount) {
|
124 |
throw new SassScriptOperationException('Incorrect operand count for ' . get_class($operands[0]) . '; expected ' . $this->operandCount . ', received ' . count($operands), SassScriptParser::$context->node);
|
125 |
}
|
139 |
|
140 |
if (count($operands) > 1 && is_null($operands[1])) {
|
141 |
$operation = 'op_unary_' . $this->operator;
|
142 |
+
} else {
|
|
|
143 |
$operation = 'op_' . $this->operator;
|
144 |
if ($this->associativity == 'l') {
|
145 |
$operands = array_reverse($operands);
|
148 |
|
149 |
if (method_exists($operands[0], $operation)) {
|
150 |
$op = clone $operands[0];
|
151 |
+
|
152 |
return $op->$operation(!empty($operands[1]) ? $operands[1] : null);
|
153 |
}
|
154 |
|
171 |
* @param string the subject string
|
172 |
* @return mixed match at the start of the string or false if no match
|
173 |
*/
|
174 |
+
public static function isa($subject)
|
175 |
+
{
|
176 |
# begins with a "/x", almost always a path without quotes.
|
177 |
if (preg_match('/^\/[^0-9\.\-\s]+/', $subject)) {
|
178 |
return FALSE;
|
179 |
}
|
180 |
+
|
181 |
return (preg_match(self::MATCH, $subject, $matches) ? trim($matches[1]) : false);
|
182 |
}
|
183 |
|
184 |
/**
|
185 |
* Converts the operation back into it's SASS representation
|
186 |
*/
|
187 |
+
public function __toString()
|
188 |
+
{
|
189 |
+
foreach (SassScriptOperation::$operators as $char => $operator) {
|
190 |
if ($operator[0] == trim($this->operator)) {
|
191 |
return $char;
|
192 |
}
|
lib/phpsass/script/SassScriptParser.php
CHANGED
@@ -9,8 +9,8 @@
|
|
9 |
* @subpackage Sass.script
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
-
require_once
|
14 |
|
15 |
/**
|
16 |
* SassScriptParser class.
|
@@ -19,7 +19,8 @@ require_once('SassScriptParserExceptions.php');
|
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.script
|
21 |
*/
|
22 |
-
class SassScriptParser
|
|
|
23 |
const MATCH_INTERPOLATION = '/(?<!\\\\)#\{(.*?)\}/';
|
24 |
const DEFAULT_ENV = 0;
|
25 |
const CSS_RULE = 1;
|
@@ -44,7 +45,8 @@ class SassScriptParser {
|
|
44 |
* SassScriptParser constructor.
|
45 |
* @return SassScriptParser
|
46 |
*/
|
47 |
-
public function __construct()
|
|
|
48 |
$this->lexer = new SassScriptLexer($this);
|
49 |
self::$instance = $this;
|
50 |
}
|
@@ -55,7 +57,8 @@ class SassScriptParser {
|
|
55 |
* @param SassContext the context in which the string is interpolated
|
56 |
* @return string the interpolated text
|
57 |
*/
|
58 |
-
public function interpolate($string, $context)
|
|
|
59 |
for ($i = 0, $n = preg_match_all(self::MATCH_INTERPOLATION, $string, $matches); $i < $n; $i++) {
|
60 |
$var = $this->evaluate($matches[1][$i], $context);
|
61 |
|
@@ -65,20 +68,18 @@ class SassScriptParser {
|
|
65 |
$var = $var->toString();
|
66 |
}
|
67 |
|
68 |
-
if(preg_match('/^unquote\((["\'])(.*)\1\)$/', $var, $match)){
|
69 |
$val = $match[2];
|
70 |
-
}
|
71 |
-
else if($var == '""'){
|
72 |
$val = "";
|
73 |
-
}
|
74 |
-
else if(preg_match('/^(["\'])(.*)\1$/', $var, $match)){
|
75 |
$val = $match[2];
|
76 |
-
}
|
77 |
-
else {
|
78 |
$val = $var;
|
79 |
}
|
80 |
$matches[1][$i] = $val;
|
81 |
}
|
|
|
82 |
return str_replace($matches[0], $matches[1], $string);
|
83 |
}
|
84 |
|
@@ -89,7 +90,8 @@ class SassScriptParser {
|
|
89 |
* @param integer the environment in which the expression is evaluated
|
90 |
* @return SassLiteral parsed value
|
91 |
*/
|
92 |
-
public function evaluate($expression, $context, $environment = self::DEFAULT_ENV)
|
|
|
93 |
self::$context = $context;
|
94 |
$operands = array();
|
95 |
|
@@ -100,14 +102,12 @@ class SassScriptParser {
|
|
100 |
if ($token instanceof SassScriptFunction) {
|
101 |
$perform = $token->perform();
|
102 |
array_push($operands, $perform);
|
103 |
-
}
|
104 |
-
elseif ($token instanceof SassLiteral) {
|
105 |
if ($token instanceof SassString) {
|
106 |
$token = new SassString($this->interpolate($token->toString(), self::$context));
|
107 |
}
|
108 |
array_push($operands, $token);
|
109 |
-
}
|
110 |
-
else {
|
111 |
$args = array();
|
112 |
for ($i = 0, $c = $token->operandCount; $i < $c; $i++) {
|
113 |
$args[] = array_pop($operands);
|
@@ -127,27 +127,26 @@ class SassScriptParser {
|
|
127 |
* @param integer the environment in which the expression is parsed
|
128 |
* @return array tokens in RPN
|
129 |
*/
|
130 |
-
public function parse($expression, $context, $environment=self::DEFAULT_ENV)
|
|
|
131 |
$outputQueue = array();
|
132 |
$operatorStack = array();
|
133 |
$parenthesis = 0;
|
134 |
|
135 |
$tokens = $this->lexer->lex($expression, $context);
|
136 |
|
137 |
-
foreach($tokens as $i=>$token) {
|
138 |
// If two literals/expessions are seperated by whitespace use the concat operator
|
139 |
if (empty($token)) {
|
140 |
if (isset($tokens[$i+1])) {
|
141 |
if ($i > 0 && (!$tokens[$i-1] instanceof SassScriptOperation || $tokens[$i-1]->operator === SassScriptOperation::$operators[')'][0]) &&
|
142 |
(!$tokens[$i+1] instanceof SassScriptOperation || $tokens[$i+1]->operator === SassScriptOperation::$operators['('][0])) {
|
143 |
$token = new SassScriptOperation(SassScriptOperation::$defaultOperator, $context);
|
144 |
-
}
|
145 |
-
else {
|
146 |
continue;
|
147 |
}
|
148 |
}
|
149 |
-
}
|
150 |
-
elseif ($token instanceof SassScriptVariable) {
|
151 |
$token = $token->evaluate($context);
|
152 |
$environment = self::DEFAULT_ENV;
|
153 |
}
|
@@ -213,8 +212,7 @@ class SassScriptParser {
|
|
213 |
while ($c = count($operatorStack)) { // While there are operators on the stack:
|
214 |
if ($operatorStack[$c - 1]->operator !== SassScriptOperation::$operators['('][0]) {
|
215 |
array_push($outputQueue, array_pop($operatorStack));
|
216 |
-
}
|
217 |
-
else {
|
218 |
throw new SassScriptParserException('Unmatched parentheses', $context->node);
|
219 |
}
|
220 |
}
|
@@ -225,7 +223,8 @@ class SassScriptParser {
|
|
225 |
/**
|
226 |
* Reduces a set down to a singular form
|
227 |
*/
|
228 |
-
public static function makeSingular($operands)
|
|
|
229 |
if (count($operands) == 1) {
|
230 |
return $operands[0];
|
231 |
}
|
@@ -239,12 +238,10 @@ class SassScriptParser {
|
|
239 |
}
|
240 |
if ($result instanceOf SassString) {
|
241 |
$result = $result->op_concat($operand);
|
242 |
-
}
|
243 |
-
else {
|
244 |
$result = $result->op_plus($operand);
|
245 |
}
|
246 |
-
}
|
247 |
-
else {
|
248 |
$string = new SassString(' ');
|
249 |
if (!$result) {
|
250 |
$result = $string;
|
9 |
* @subpackage Sass.script
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassScriptLexer.php';
|
13 |
+
require_once 'SassScriptParserExceptions.php';
|
14 |
|
15 |
/**
|
16 |
* SassScriptParser class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.script
|
21 |
*/
|
22 |
+
class SassScriptParser
|
23 |
+
{
|
24 |
const MATCH_INTERPOLATION = '/(?<!\\\\)#\{(.*?)\}/';
|
25 |
const DEFAULT_ENV = 0;
|
26 |
const CSS_RULE = 1;
|
45 |
* SassScriptParser constructor.
|
46 |
* @return SassScriptParser
|
47 |
*/
|
48 |
+
public function __construct()
|
49 |
+
{
|
50 |
$this->lexer = new SassScriptLexer($this);
|
51 |
self::$instance = $this;
|
52 |
}
|
57 |
* @param SassContext the context in which the string is interpolated
|
58 |
* @return string the interpolated text
|
59 |
*/
|
60 |
+
public function interpolate($string, $context)
|
61 |
+
{
|
62 |
for ($i = 0, $n = preg_match_all(self::MATCH_INTERPOLATION, $string, $matches); $i < $n; $i++) {
|
63 |
$var = $this->evaluate($matches[1][$i], $context);
|
64 |
|
68 |
$var = $var->toString();
|
69 |
}
|
70 |
|
71 |
+
if (preg_match('/^unquote\((["\'])(.*)\1\)$/', $var, $match)) {
|
72 |
$val = $match[2];
|
73 |
+
} elseif ($var == '""') {
|
|
|
74 |
$val = "";
|
75 |
+
} elseif (preg_match('/^(["\'])(.*)\1$/', $var, $match)) {
|
|
|
76 |
$val = $match[2];
|
77 |
+
} else {
|
|
|
78 |
$val = $var;
|
79 |
}
|
80 |
$matches[1][$i] = $val;
|
81 |
}
|
82 |
+
|
83 |
return str_replace($matches[0], $matches[1], $string);
|
84 |
}
|
85 |
|
90 |
* @param integer the environment in which the expression is evaluated
|
91 |
* @return SassLiteral parsed value
|
92 |
*/
|
93 |
+
public function evaluate($expression, $context, $environment = self::DEFAULT_ENV)
|
94 |
+
{
|
95 |
self::$context = $context;
|
96 |
$operands = array();
|
97 |
|
102 |
if ($token instanceof SassScriptFunction) {
|
103 |
$perform = $token->perform();
|
104 |
array_push($operands, $perform);
|
105 |
+
} elseif ($token instanceof SassLiteral) {
|
|
|
106 |
if ($token instanceof SassString) {
|
107 |
$token = new SassString($this->interpolate($token->toString(), self::$context));
|
108 |
}
|
109 |
array_push($operands, $token);
|
110 |
+
} else {
|
|
|
111 |
$args = array();
|
112 |
for ($i = 0, $c = $token->operandCount; $i < $c; $i++) {
|
113 |
$args[] = array_pop($operands);
|
127 |
* @param integer the environment in which the expression is parsed
|
128 |
* @return array tokens in RPN
|
129 |
*/
|
130 |
+
public function parse($expression, $context, $environment=self::DEFAULT_ENV)
|
131 |
+
{
|
132 |
$outputQueue = array();
|
133 |
$operatorStack = array();
|
134 |
$parenthesis = 0;
|
135 |
|
136 |
$tokens = $this->lexer->lex($expression, $context);
|
137 |
|
138 |
+
foreach ($tokens as $i=>$token) {
|
139 |
// If two literals/expessions are seperated by whitespace use the concat operator
|
140 |
if (empty($token)) {
|
141 |
if (isset($tokens[$i+1])) {
|
142 |
if ($i > 0 && (!$tokens[$i-1] instanceof SassScriptOperation || $tokens[$i-1]->operator === SassScriptOperation::$operators[')'][0]) &&
|
143 |
(!$tokens[$i+1] instanceof SassScriptOperation || $tokens[$i+1]->operator === SassScriptOperation::$operators['('][0])) {
|
144 |
$token = new SassScriptOperation(SassScriptOperation::$defaultOperator, $context);
|
145 |
+
} else {
|
|
|
146 |
continue;
|
147 |
}
|
148 |
}
|
149 |
+
} elseif ($token instanceof SassScriptVariable) {
|
|
|
150 |
$token = $token->evaluate($context);
|
151 |
$environment = self::DEFAULT_ENV;
|
152 |
}
|
212 |
while ($c = count($operatorStack)) { // While there are operators on the stack:
|
213 |
if ($operatorStack[$c - 1]->operator !== SassScriptOperation::$operators['('][0]) {
|
214 |
array_push($outputQueue, array_pop($operatorStack));
|
215 |
+
} else {
|
|
|
216 |
throw new SassScriptParserException('Unmatched parentheses', $context->node);
|
217 |
}
|
218 |
}
|
223 |
/**
|
224 |
* Reduces a set down to a singular form
|
225 |
*/
|
226 |
+
public static function makeSingular($operands)
|
227 |
+
{
|
228 |
if (count($operands) == 1) {
|
229 |
return $operands[0];
|
230 |
}
|
238 |
}
|
239 |
if ($result instanceOf SassString) {
|
240 |
$result = $result->op_concat($operand);
|
241 |
+
} else {
|
|
|
242 |
$result = $result->op_plus($operand);
|
243 |
}
|
244 |
+
} else {
|
|
|
245 |
$string = new SassString(' ');
|
246 |
if (!$result) {
|
247 |
$result = $string;
|
lib/phpsass/script/SassScriptParserExceptions.php
CHANGED
@@ -37,4 +37,4 @@ class SassScriptOperationException extends SassScriptParserException {}
|
|
37 |
* @package PHamlP
|
38 |
* @subpackage Sass.script
|
39 |
*/
|
40 |
-
class SassScriptFunctionException extends SassScriptParserException {}
|
37 |
* @package PHamlP
|
38 |
* @subpackage Sass.script
|
39 |
*/
|
40 |
+
class SassScriptFunctionException extends SassScriptParserException {}
|
lib/phpsass/script/SassScriptVariable.php
CHANGED
@@ -8,18 +8,19 @@
|
|
8 |
* @package PHamlP
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
-
|
12 |
/**
|
13 |
* SassVariable class.
|
14 |
* @package PHamlP
|
15 |
* @subpackage Sass.script.literals
|
16 |
*/
|
17 |
-
class SassScriptVariable
|
|
|
18 |
/**
|
19 |
* Regex for matching and extracting Variables
|
20 |
*/
|
21 |
const MATCH = '/^(?<!\\\\)(?(?!!important\b)[!\$]([\w-]+))/';
|
22 |
-
|
23 |
/**
|
24 |
* @var string name of variable
|
25 |
*/
|
@@ -30,7 +31,8 @@ class SassScriptVariable {
|
|
30 |
* @param string value of the Variable type
|
31 |
* @return SassVariable
|
32 |
*/
|
33 |
-
public function __construct($value)
|
|
|
34 |
$this->name = substr($value, 1);
|
35 |
}
|
36 |
|
@@ -39,7 +41,8 @@ class SassScriptVariable {
|
|
39 |
* @param SassContext context of the variable
|
40 |
* @return SassLiteral the SassScript object for this variable
|
41 |
*/
|
42 |
-
public function evaluate($context)
|
|
|
43 |
return $context->getVariable($this->name);
|
44 |
}
|
45 |
|
@@ -49,9 +52,10 @@ class SassScriptVariable {
|
|
49 |
* @param string the subject string
|
50 |
* @return mixed match at the start of the string or false if no match
|
51 |
*/
|
52 |
-
public static function isa($subject)
|
|
|
53 |
// we need to do the check as preg_match returns a count of 1 if
|
54 |
// subject == '!important'; the match being an empty match
|
55 |
return (preg_match(self::MATCH, $subject, $matches) ? (empty($matches[0]) ? false : $matches[0]) : false);
|
56 |
}
|
57 |
-
}
|
8 |
* @package PHamlP
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
+
|
12 |
/**
|
13 |
* SassVariable class.
|
14 |
* @package PHamlP
|
15 |
* @subpackage Sass.script.literals
|
16 |
*/
|
17 |
+
class SassScriptVariable
|
18 |
+
{
|
19 |
/**
|
20 |
* Regex for matching and extracting Variables
|
21 |
*/
|
22 |
const MATCH = '/^(?<!\\\\)(?(?!!important\b)[!\$]([\w-]+))/';
|
23 |
+
|
24 |
/**
|
25 |
* @var string name of variable
|
26 |
*/
|
31 |
* @param string value of the Variable type
|
32 |
* @return SassVariable
|
33 |
*/
|
34 |
+
public function __construct($value)
|
35 |
+
{
|
36 |
$this->name = substr($value, 1);
|
37 |
}
|
38 |
|
41 |
* @param SassContext context of the variable
|
42 |
* @return SassLiteral the SassScript object for this variable
|
43 |
*/
|
44 |
+
public function evaluate($context)
|
45 |
+
{
|
46 |
return $context->getVariable($this->name);
|
47 |
}
|
48 |
|
52 |
* @param string the subject string
|
53 |
* @return mixed match at the start of the string or false if no match
|
54 |
*/
|
55 |
+
public static function isa($subject)
|
56 |
+
{
|
57 |
// we need to do the check as preg_match returns a count of 1 if
|
58 |
// subject == '!important'; the match being an empty match
|
59 |
return (preg_match(self::MATCH, $subject, $matches) ? (empty($matches[0]) ? false : $matches[0]) : false);
|
60 |
}
|
61 |
+
}
|
lib/phpsass/script/literals/SassBoolean.php
CHANGED
@@ -9,14 +9,15 @@
|
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassBoolean class.
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.script.literals
|
18 |
*/
|
19 |
-
class SassBoolean extends SassLiteral
|
|
|
20 |
/**@#+
|
21 |
* Regex for matching and extracting booleans
|
22 |
*/
|
@@ -27,14 +28,13 @@ class SassBoolean extends SassLiteral {
|
|
27 |
* @param string value of the boolean type
|
28 |
* @return SassBoolean
|
29 |
*/
|
30 |
-
public function __construct($value)
|
|
|
31 |
if (is_bool($value)) {
|
32 |
$this->value = $value;
|
33 |
-
}
|
34 |
-
elseif ($value === 'true' || $value === 'false') {
|
35 |
$this->value = ($value === 'true' ? true : false);
|
36 |
-
}
|
37 |
-
else {
|
38 |
throw new SassBooleanException('Invalid SassBoolean', SassScriptParser::$context->node);
|
39 |
}
|
40 |
}
|
@@ -43,7 +43,8 @@ class SassBoolean extends SassLiteral {
|
|
43 |
* Returns the value of this boolean.
|
44 |
* @return boolean the value of this boolean
|
45 |
*/
|
46 |
-
public function getValue()
|
|
|
47 |
return $this->value;
|
48 |
}
|
49 |
|
@@ -51,18 +52,22 @@ class SassBoolean extends SassLiteral {
|
|
51 |
* Returns a string representation of the value.
|
52 |
* @return string string representation of the value.
|
53 |
*/
|
54 |
-
public function toString()
|
|
|
55 |
return $this->getValue() ? 'true' : 'false';
|
56 |
}
|
57 |
|
58 |
-
public function length()
|
|
|
59 |
return 1;
|
60 |
}
|
61 |
|
62 |
-
public function nth($i)
|
|
|
63 |
if ($i == 1 && isset($this->value)) {
|
64 |
return new SassBoolean($this->value);
|
65 |
}
|
|
|
66 |
return new SassBoolean(false);
|
67 |
}
|
68 |
|
@@ -72,7 +77,8 @@ class SassBoolean extends SassLiteral {
|
|
72 |
* @param string the subject string
|
73 |
* @return mixed match at the start of the string or false if no match
|
74 |
*/
|
75 |
-
public static function isa($subject)
|
|
|
76 |
return (preg_match(self::MATCH, $subject, $matches) ? $matches[0] : false);
|
77 |
}
|
78 |
}
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassLiteral.php';
|
13 |
|
14 |
/**
|
15 |
* SassBoolean class.
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.script.literals
|
18 |
*/
|
19 |
+
class SassBoolean extends SassLiteral
|
20 |
+
{
|
21 |
/**@#+
|
22 |
* Regex for matching and extracting booleans
|
23 |
*/
|
28 |
* @param string value of the boolean type
|
29 |
* @return SassBoolean
|
30 |
*/
|
31 |
+
public function __construct($value)
|
32 |
+
{
|
33 |
if (is_bool($value)) {
|
34 |
$this->value = $value;
|
35 |
+
} elseif ($value === 'true' || $value === 'false') {
|
|
|
36 |
$this->value = ($value === 'true' ? true : false);
|
37 |
+
} else {
|
|
|
38 |
throw new SassBooleanException('Invalid SassBoolean', SassScriptParser::$context->node);
|
39 |
}
|
40 |
}
|
43 |
* Returns the value of this boolean.
|
44 |
* @return boolean the value of this boolean
|
45 |
*/
|
46 |
+
public function getValue()
|
47 |
+
{
|
48 |
return $this->value;
|
49 |
}
|
50 |
|
52 |
* Returns a string representation of the value.
|
53 |
* @return string string representation of the value.
|
54 |
*/
|
55 |
+
public function toString()
|
56 |
+
{
|
57 |
return $this->getValue() ? 'true' : 'false';
|
58 |
}
|
59 |
|
60 |
+
public function length()
|
61 |
+
{
|
62 |
return 1;
|
63 |
}
|
64 |
|
65 |
+
public function nth($i)
|
66 |
+
{
|
67 |
if ($i == 1 && isset($this->value)) {
|
68 |
return new SassBoolean($this->value);
|
69 |
}
|
70 |
+
|
71 |
return new SassBoolean(false);
|
72 |
}
|
73 |
|
77 |
* @param string the subject string
|
78 |
* @return mixed match at the start of the string or false if no match
|
79 |
*/
|
80 |
+
public static function isa($subject)
|
81 |
+
{
|
82 |
return (preg_match(self::MATCH, $subject, $matches) ? $matches[0] : false);
|
83 |
}
|
84 |
}
|
lib/phpsass/script/literals/SassColour.php
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassColour class.
|
@@ -35,7 +35,8 @@ require_once('SassLiteral.php');
|
|
35 |
* @package PHamlP
|
36 |
* @subpackage Sass.script.literals
|
37 |
*/
|
38 |
-
class SassColour extends SassLiteral
|
|
|
39 |
/**@#+
|
40 |
* Regexes for matching and extracting colours
|
41 |
*/
|
@@ -46,7 +47,7 @@ class SassColour extends SassLiteral {
|
|
46 |
/**@#-*/
|
47 |
|
48 |
/**@#-*/
|
49 |
-
static
|
50 |
'aliceblue' => '#f0f8ff',
|
51 |
'antiquewhite' => '#faebd7',
|
52 |
'aqua' => '#00ffff',
|
@@ -197,12 +198,12 @@ class SassColour extends SassLiteral {
|
|
197 |
/**
|
198 |
* @var array reverse array (value => name) of named SVG1.0 colours
|
199 |
*/
|
200 |
-
static
|
201 |
|
202 |
/**
|
203 |
* @var array reverse array (value => name) of named HTML4 colours
|
204 |
*/
|
205 |
-
static
|
206 |
'#000000' => 'black',
|
207 |
'#000080' => 'navy',
|
208 |
'#0000ff' => 'blue',
|
@@ -221,7 +222,7 @@ class SassColour extends SassLiteral {
|
|
221 |
'#ffffff' => 'white',
|
222 |
);
|
223 |
|
224 |
-
static
|
225 |
|
226 |
/**@#+
|
227 |
* RGB colour components
|
@@ -229,7 +230,7 @@ class SassColour extends SassLiteral {
|
|
229 |
/**
|
230 |
* @var array RGB colour components. Used to check for RGB attributes.
|
231 |
*/
|
232 |
-
static
|
233 |
/**
|
234 |
* @var integer red component. 0 - 255
|
235 |
*/
|
@@ -249,7 +250,7 @@ class SassColour extends SassLiteral {
|
|
249 |
/**
|
250 |
* @var array HSL colour components. Used to check for HSL attributes.
|
251 |
*/
|
252 |
-
static
|
253 |
/**
|
254 |
* @var float hue component. 0 - 360
|
255 |
*/
|
@@ -282,7 +283,8 @@ class SassColour extends SassLiteral {
|
|
282 |
* @param mixed the colour
|
283 |
* @return SassColour
|
284 |
*/
|
285 |
-
public function __construct($colour)
|
|
|
286 |
if (is_string($colour)) {
|
287 |
$colour = strtolower($colour);
|
288 |
if ($colour === self::TRANSPARENT) {
|
@@ -290,8 +292,7 @@ class SassColour extends SassLiteral {
|
|
290 |
$this->green = 0;
|
291 |
$this->blue = 0;
|
292 |
$this->alpha = 0;
|
293 |
-
}
|
294 |
-
else {
|
295 |
if (array_key_exists($colour, self::$svgColours)) {
|
296 |
$colour = self::$svgColours[$colour];
|
297 |
}
|
@@ -299,8 +300,7 @@ class SassColour extends SassLiteral {
|
|
299 |
for ($i = 1; $i < 4; $i++) {
|
300 |
$matches[$i] = str_repeat($matches[$i], 2);
|
301 |
}
|
302 |
-
}
|
303 |
-
else {
|
304 |
preg_match(self::EXTRACT_6, $colour, $matches);
|
305 |
}
|
306 |
|
@@ -312,29 +312,25 @@ class SassColour extends SassLiteral {
|
|
312 |
$this->blue = intval($matches[3], 16);
|
313 |
$this->alpha = 1;
|
314 |
}
|
315 |
-
}
|
316 |
-
elseif (is_array($colour)) {
|
317 |
$scheme = $this->assertValid($colour);
|
318 |
if ($scheme == 'rgb') {
|
319 |
$this->red = $colour['red'];
|
320 |
$this->green = $colour['green'];
|
321 |
$this->blue = $colour['blue'];
|
322 |
$this->alpha = (isset($colour['alpha']) ? $colour['alpha'] : 1);
|
323 |
-
}
|
324 |
-
elseif ($scheme == 'hsl') {
|
325 |
$this->hue = $colour['hue'];
|
326 |
$this->saturation = $colour['saturation'];
|
327 |
$this->lightness = $colour['lightness'];
|
328 |
$this->alpha = (isset($colour['alpha']) ? $colour['alpha'] : 1);
|
329 |
-
}
|
330 |
-
else {
|
331 |
$this->red = $colour[0];
|
332 |
$this->green = $colour[1];
|
333 |
$this->blue = $colour[2];
|
334 |
$this->alpha = (isset($colour[3]) ? $colour[3] : 1);
|
335 |
}
|
336 |
-
}
|
337 |
-
else {
|
338 |
throw new SassColourException('Colour must be a array', SassScriptParser::$context->node);
|
339 |
}
|
340 |
}
|
@@ -344,7 +340,8 @@ class SassColour extends SassLiteral {
|
|
344 |
* @param mixed SassColour|SassNumber value to add
|
345 |
* @return sassColour the colour result
|
346 |
*/
|
347 |
-
public function op_plus($other)
|
|
|
348 |
if ($other instanceof SassNumber) {
|
349 |
if (!$other->isUnitless()) {
|
350 |
return new SassString($this->toString() . $other->value);
|
@@ -353,16 +350,15 @@ class SassColour extends SassLiteral {
|
|
353 |
$this->red = $this->getRed() + $other->value;
|
354 |
$this->green = $this->getGreen() + $other->value;
|
355 |
$this->blue = $this->getBlue() + $other->value;
|
356 |
-
}
|
357 |
-
elseif (!$other instanceof SassColour) {
|
358 |
return new SassString($this->toString() . $other->value);
|
359 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
360 |
-
}
|
361 |
-
else {
|
362 |
$this->red = $this->getRed() + $other->getRed();
|
363 |
$this->green = $this->getGreen() + $other->getGreen();
|
364 |
$this->blue = $this->getBlue() + $other->getBlue();
|
365 |
}
|
|
|
366 |
return $this;
|
367 |
}
|
368 |
|
@@ -371,7 +367,8 @@ class SassColour extends SassLiteral {
|
|
371 |
* @param mixed value (SassColour or SassNumber) to subtract
|
372 |
* @return sassColour the colour result
|
373 |
*/
|
374 |
-
public function op_minus($other)
|
|
|
375 |
if ($other instanceof SassNumber) {
|
376 |
if (!$other->isUnitless()) {
|
377 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -379,15 +376,14 @@ class SassColour extends SassLiteral {
|
|
379 |
$this->red = $this->getRed() - $other->value;
|
380 |
$this->green = $this->getGreen() - $other->value;
|
381 |
$this->blue = $this->getBlue() - $other->value;
|
382 |
-
}
|
383 |
-
elseif (!$other instanceof SassColour) {
|
384 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
385 |
-
}
|
386 |
-
else {
|
387 |
$this->red = $this->getRed() - $other->getRed();
|
388 |
$this->green = $this->getGreen() - $other->getGreen();
|
389 |
$this->blue = $this->getBlue() - $other->getBlue();
|
390 |
}
|
|
|
391 |
return $this;
|
392 |
}
|
393 |
|
@@ -396,7 +392,8 @@ class SassColour extends SassLiteral {
|
|
396 |
* @param mixed SassColour|SassNumber value to multiply by
|
397 |
* @return sassColour the colour result
|
398 |
*/
|
399 |
-
public function op_times($other)
|
|
|
400 |
if ($other instanceof SassNumber) {
|
401 |
if (!$other->isUnitless()) {
|
402 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -404,15 +401,14 @@ class SassColour extends SassLiteral {
|
|
404 |
$this->red = $this->getRed() * $other->value;
|
405 |
$this->green = $this->getGreen() * $other->value;
|
406 |
$this->blue = $this->getBlue() * $other->value;
|
407 |
-
}
|
408 |
-
elseif (!$other instanceof SassColour) {
|
409 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
410 |
-
}
|
411 |
-
else {
|
412 |
$this->red = $this->getRed() * $other->getRed();
|
413 |
$this->green = $this->getGreen() * $other->getGreen();
|
414 |
$this->blue = $this->getBlue() * $other->getBlue();
|
415 |
}
|
|
|
416 |
return $this;
|
417 |
}
|
418 |
|
@@ -421,7 +417,8 @@ class SassColour extends SassLiteral {
|
|
421 |
* @param mixed value (SassColour or SassNumber) to divide by
|
422 |
* @return sassColour the colour result
|
423 |
*/
|
424 |
-
public function op_div($other)
|
|
|
425 |
if ($other instanceof SassNumber) {
|
426 |
if (!$other->isUnitless()) {
|
427 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -429,15 +426,14 @@ class SassColour extends SassLiteral {
|
|
429 |
$this->red = $this->getRed() / $other->value;
|
430 |
$this->green = $this->getGreen() / $other->value;
|
431 |
$this->blue = $this->getBlue() / $other->value;
|
432 |
-
}
|
433 |
-
elseif (!$other instanceof SassColour) {
|
434 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
435 |
-
}
|
436 |
-
else {
|
437 |
$this->red = $this->getRed() / $other->getRed();
|
438 |
$this->green = $this->getGreen() / $other->getGreen();
|
439 |
$this->blue = $this->getBlue() / $other->getBlue();
|
440 |
}
|
|
|
441 |
return $this;
|
442 |
}
|
443 |
|
@@ -446,7 +442,8 @@ class SassColour extends SassLiteral {
|
|
446 |
* @param mixed value (SassColour or SassNumber) to divide by
|
447 |
* @return sassColour the colour result
|
448 |
*/
|
449 |
-
public function op_modulo($other)
|
|
|
450 |
if ($other instanceof SassNumber) {
|
451 |
if (!$other->isUnitless()) {
|
452 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -454,15 +451,14 @@ class SassColour extends SassLiteral {
|
|
454 |
$this->red = fmod($this->getRed(), $other->value);
|
455 |
$this->green = fmod($this->getGreen(), $other->value);
|
456 |
$this->blue = fmod($this->getBlue(), $other->value);
|
457 |
-
}
|
458 |
-
elseif (!$other instanceof SassColour) {
|
459 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
460 |
-
}
|
461 |
-
else {
|
462 |
$this->red = fmod($this->getRed(), $other->getRed());
|
463 |
$this->green = fmod($this->getGreen(), $other->getGreen());
|
464 |
$this->blue = fmod($this->getBlue(), $other->getBlue());
|
465 |
}
|
|
|
466 |
return $this;
|
467 |
}
|
468 |
|
@@ -471,7 +467,8 @@ class SassColour extends SassLiteral {
|
|
471 |
* @param mixed value (SassColour or SassNumber) to bitwise AND with
|
472 |
* @return sassColour the colour result
|
473 |
*/
|
474 |
-
public function op_bw_and($other)
|
|
|
475 |
if ($other instanceof SassNumber) {
|
476 |
if (!$other->isUnitless()) {
|
477 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -479,15 +476,14 @@ class SassColour extends SassLiteral {
|
|
479 |
$this->red = $this->getRed() & $other->value;
|
480 |
$this->green = $this->getGreen() & $other->value;
|
481 |
$this->blue = $this->getBlue() & $other->value;
|
482 |
-
}
|
483 |
-
elseif (!$other instanceof SassColour) {
|
484 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
485 |
-
}
|
486 |
-
else {
|
487 |
$this->red = $this->getRed() & $other->getRed();
|
488 |
$this->green = $this->getGreen() & $other->getGreen();
|
489 |
$this->blue = $this->getBlue() & $other->getBlue();
|
490 |
}
|
|
|
491 |
return $this;
|
492 |
}
|
493 |
|
@@ -496,7 +492,8 @@ class SassColour extends SassLiteral {
|
|
496 |
* @param mixed value (SassColour or SassNumber) to bitwise OR with
|
497 |
* @return sassColour the colour result
|
498 |
*/
|
499 |
-
public function op_bw_or($other)
|
|
|
500 |
if ($other instanceof SassNumber) {
|
501 |
if (!$other->isUnitless()) {
|
502 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -504,15 +501,14 @@ class SassColour extends SassLiteral {
|
|
504 |
$this->red = $this->getRed() | $other->value;
|
505 |
$this->green = $this->getGreen() | $other->value;
|
506 |
$this->blue = $this->getBlue() | $other->value;
|
507 |
-
}
|
508 |
-
elseif (!$other instanceof SassColour) {
|
509 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
510 |
-
}
|
511 |
-
else {
|
512 |
$this->red = $this->getRed() | $other->getRed();
|
513 |
$this->green = $this->getGreen() | $other->getGreen();
|
514 |
$this->blue = $this->getBlue() | $other->getBlue();
|
515 |
}
|
|
|
516 |
return $this;
|
517 |
}
|
518 |
|
@@ -521,7 +517,8 @@ class SassColour extends SassLiteral {
|
|
521 |
* @param mixed value (SassColour or SassNumber) to bitwise XOR with
|
522 |
* @return sassColour the colour result
|
523 |
*/
|
524 |
-
public function op_bw_xor($other)
|
|
|
525 |
if ($other instanceof SassNumber) {
|
526 |
if (!$other->isUnitless()) {
|
527 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
@@ -529,15 +526,14 @@ class SassColour extends SassLiteral {
|
|
529 |
$this->red = $this->getRed() ^ $other->value;
|
530 |
$this->green = $this->getGreen() ^ $other->value;
|
531 |
$this->blue = $this->getBlue() ^ $other->value;
|
532 |
-
}
|
533 |
-
elseif (!$other instanceof SassColour) {
|
534 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
535 |
-
}
|
536 |
-
else {
|
537 |
$this->red = $this->getRed() ^ $other->getRed();
|
538 |
$this->green = $this->getGreen() ^ $other->getGreen();
|
539 |
$this->blue = $this->getBlue() ^ $other->getBlue();
|
540 |
}
|
|
|
541 |
return $this;
|
542 |
}
|
543 |
|
@@ -545,10 +541,12 @@ class SassColour extends SassLiteral {
|
|
545 |
* Colour bitwise NOT
|
546 |
* @return sassColour the colour result
|
547 |
*/
|
548 |
-
public function op_not()
|
|
|
549 |
$this->red = ~$this->getRed();
|
550 |
$this->green = ~$this->getGreen();
|
551 |
$this->blue = ~$this->getBlue();
|
|
|
552 |
return $this;
|
553 |
}
|
554 |
|
@@ -557,13 +555,15 @@ class SassColour extends SassLiteral {
|
|
557 |
* @param sassNumber amount to shift left by
|
558 |
* @return sassColour the colour result
|
559 |
*/
|
560 |
-
public function op_shiftl($other)
|
|
|
561 |
if (!$other instanceof SassNumber ||!$other->isUnitless()) {
|
562 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
563 |
}
|
564 |
$this->red = $this->getRed() << $other->value;
|
565 |
$this->green = $this->getGreen() << $other->value;
|
566 |
$this->blue = $this->getBlue() << $other->value;
|
|
|
567 |
return $this;
|
568 |
}
|
569 |
|
@@ -572,13 +572,15 @@ class SassColour extends SassLiteral {
|
|
572 |
* @param sassNumber amount to shift right by
|
573 |
* @return sassColour the colour result
|
574 |
*/
|
575 |
-
public function op_shiftr($other)
|
|
|
576 |
if (!$other instanceof SassNumber || !$other->isUnitless()) {
|
577 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
578 |
}
|
579 |
$this->red = $this->getRed() >> $other->value;
|
580 |
$this->green = $this->getGreen() >> $other->value;
|
581 |
$this->blue = $this->getBlue() >> $other->value;
|
|
|
582 |
return $this;
|
583 |
}
|
584 |
|
@@ -587,7 +589,8 @@ class SassColour extends SassLiteral {
|
|
587 |
* RGB or HSL attributes may be changed, but not both at once.
|
588 |
* @param array attributes to change
|
589 |
*/
|
590 |
-
public function with($attributes)
|
|
|
591 |
if ($this->assertValid($attributes, false) === 'hsl') {
|
592 |
$colour = array_merge(array(
|
593 |
'hue' => $this->getHue(),
|
@@ -595,8 +598,7 @@ class SassColour extends SassLiteral {
|
|
595 |
'lightness' => $this->getLightness(),
|
596 |
'alpha' => $this->alpha
|
597 |
), $attributes);
|
598 |
-
}
|
599 |
-
else {
|
600 |
$colour = array_merge(array(
|
601 |
'red' => $this->getRed(),
|
602 |
'green' => $this->getGreen(),
|
@@ -605,9 +607,9 @@ class SassColour extends SassLiteral {
|
|
605 |
), $attributes);
|
606 |
}
|
607 |
|
608 |
-
|
609 |
$colour = new SassColour($colour);
|
610 |
$colour->getRed(); # will get RGB and HSL
|
|
|
611 |
return $colour;
|
612 |
}
|
613 |
|
@@ -615,10 +617,12 @@ class SassColour extends SassLiteral {
|
|
615 |
* Returns the alpha component (opacity) of this colour.
|
616 |
* @return float the alpha component (opacity) of this colour.
|
617 |
*/
|
618 |
-
public function getAlpha($value = false)
|
|
|
619 |
if ($value && isset($this->alpha->$value)) {
|
620 |
return $this->alpha->value;
|
621 |
}
|
|
|
622 |
return $this->alpha;
|
623 |
}
|
624 |
|
@@ -626,13 +630,15 @@ class SassColour extends SassLiteral {
|
|
626 |
* Returns the hue of this colour.
|
627 |
* @return float the hue of this colour.
|
628 |
*/
|
629 |
-
public function getHue($value = false)
|
|
|
630 |
if (is_null($this->hue)) {
|
631 |
$this->rgb2hsl();
|
632 |
}
|
633 |
if ($value && isset($this->hue->value)) {
|
634 |
return $this->hue->value;
|
635 |
}
|
|
|
636 |
return $this->hue;
|
637 |
}
|
638 |
|
@@ -640,13 +646,15 @@ class SassColour extends SassLiteral {
|
|
640 |
* Returns the saturation of this colour.
|
641 |
* @return float the saturation of this colour.
|
642 |
*/
|
643 |
-
public function getSaturation($value = false)
|
|
|
644 |
if (is_null($this->saturation)) {
|
645 |
$this->rgb2hsl();
|
646 |
}
|
647 |
if ($value && isset($this->saturation->value)) {
|
648 |
return $this->saturation->value;
|
649 |
}
|
|
|
650 |
return $this->saturation;
|
651 |
}
|
652 |
|
@@ -654,13 +662,15 @@ class SassColour extends SassLiteral {
|
|
654 |
* Returns the lightness of this colour.
|
655 |
* @return float the lightness of this colour.
|
656 |
*/
|
657 |
-
public function getLightness($value = false)
|
|
|
658 |
if (is_null($this->lightness)) {
|
659 |
$this->rgb2hsl();
|
660 |
}
|
661 |
if ($value && isset($this->lightness->value)) {
|
662 |
return $this->lightness->value;
|
663 |
}
|
|
|
664 |
return $this->lightness;
|
665 |
}
|
666 |
|
@@ -668,13 +678,15 @@ class SassColour extends SassLiteral {
|
|
668 |
* Returns the blue component of this colour.
|
669 |
* @return integer the blue component of this colour.
|
670 |
*/
|
671 |
-
public function getBlue($value = false)
|
|
|
672 |
if (is_null($this->blue)) {
|
673 |
$this->hsl2rgb();
|
674 |
}
|
675 |
if ($value && isset($this->blue->value)) {
|
676 |
return $this->blue->value;
|
677 |
}
|
|
|
678 |
return max(0, min(255, str_replace(',','.',round($this->blue))));
|
679 |
}
|
680 |
|
@@ -682,13 +694,15 @@ class SassColour extends SassLiteral {
|
|
682 |
* Returns the green component of this colour.
|
683 |
* @return integer the green component of this colour.
|
684 |
*/
|
685 |
-
public function getGreen($value = false)
|
|
|
686 |
if (is_null($this->green)) {
|
687 |
$this->hsl2rgb();
|
688 |
}
|
689 |
if ($value && isset($this->green->value)) {
|
690 |
return $this->green->value;
|
691 |
}
|
|
|
692 |
return max(0, min(255, str_replace(',','.',round($this->green))));
|
693 |
}
|
694 |
|
@@ -696,13 +710,15 @@ class SassColour extends SassLiteral {
|
|
696 |
* Returns the red component of this colour.
|
697 |
* @return integer the red component of this colour.
|
698 |
*/
|
699 |
-
public function getRed($value = false)
|
|
|
700 |
if (is_null($this->red)) {
|
701 |
$this->hsl2rgb();
|
702 |
}
|
703 |
if ($value && isset($this->red->value)) {
|
704 |
return $this->red->value;
|
705 |
}
|
|
|
706 |
return max(0, min(255, str_replace(',','.',round($this->red))));
|
707 |
}
|
708 |
|
@@ -710,7 +726,8 @@ class SassColour extends SassLiteral {
|
|
710 |
* Returns an array with the RGB components of this colour.
|
711 |
* @return array the RGB components of this colour
|
712 |
*/
|
713 |
-
public function getRgb()
|
|
|
714 |
return array($this->red, $this->green, $this->blue);
|
715 |
}
|
716 |
|
@@ -718,7 +735,8 @@ class SassColour extends SassLiteral {
|
|
718 |
* Returns an array with the RGB and alpha components of this colour.
|
719 |
* @return array the RGB and alpha components of this colour
|
720 |
*/
|
721 |
-
public function getRgba()
|
|
|
722 |
return array($this->getRed(), $this->getGreen(), $this->getBlue(), $this->alpha);
|
723 |
}
|
724 |
|
@@ -726,7 +744,8 @@ class SassColour extends SassLiteral {
|
|
726 |
* Returns an array with the HSL components of this colour.
|
727 |
* @return array the HSL components of this colour
|
728 |
*/
|
729 |
-
public function getHsl()
|
|
|
730 |
return array($this->getHue(), $this->getSaturation(), $this->getLightness());
|
731 |
}
|
732 |
|
@@ -734,7 +753,8 @@ class SassColour extends SassLiteral {
|
|
734 |
* Returns an array with the HSL and alpha components of this colour.
|
735 |
* @return array the HSL and alpha components of this colour
|
736 |
*/
|
737 |
-
public function getHsla()
|
|
|
738 |
return array($this->getHue(), $this->getSaturation(), $this->getLightness(), $this->alpha);
|
739 |
}
|
740 |
|
@@ -743,7 +763,8 @@ class SassColour extends SassLiteral {
|
|
743 |
* @return array the colour
|
744 |
* @deprecated
|
745 |
*/
|
746 |
-
public function getValue()
|
|
|
747 |
return $this->rgb;
|
748 |
}
|
749 |
|
@@ -751,7 +772,8 @@ class SassColour extends SassLiteral {
|
|
751 |
* Returns whether this colour object is translucent; that is, whether the alpha channel is non-1.
|
752 |
* @return boolean true if this colour is translucent, false if not
|
753 |
*/
|
754 |
-
public function isTranslucent()
|
|
|
755 |
return $this->alpha < 1;
|
756 |
}
|
757 |
|
@@ -760,7 +782,8 @@ class SassColour extends SassLiteral {
|
|
760 |
* @param boolean whether to use CSS3 SVG1.0 colour names
|
761 |
* @return string the colour as a named colour, rgba(r,g,g,a) or #rrggbb
|
762 |
*/
|
763 |
-
public function toString($css3 = true)
|
|
|
764 |
$rgba = $this->getRgba();
|
765 |
|
766 |
foreach ($rgba as $k => $v) {
|
@@ -771,12 +794,11 @@ class SassColour extends SassLiteral {
|
|
771 |
|
772 |
if ($rgba[3] == 0) {
|
773 |
return 'transparent';
|
774 |
-
}
|
775 |
-
elseif ($rgba[3] < 1) {
|
776 |
$rgba[3] = str_replace(',','.',round($rgba[3], 2));
|
|
|
777 |
return sprintf('rgba(%d, %d, %d, %s)', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
|
778 |
-
}
|
779 |
-
else {
|
780 |
$colour = sprintf('#%02x%02x%02x', str_replace(',','.',round($rgba[0])), str_replace(',','.',round($rgba[1])), str_replace(',','.',round($rgba[2])));
|
781 |
}
|
782 |
|
@@ -784,15 +806,15 @@ class SassColour extends SassLiteral {
|
|
784 |
if (empty(self::$_svgColours)) {
|
785 |
self::$_svgColours = array_flip(self::$svgColours);
|
786 |
}
|
|
|
787 |
return (array_key_exists($colour, self::$_svgColours) ? self::$_svgColours[$colour] : $colour);
|
788 |
-
}
|
789 |
-
else {
|
790 |
return (array_key_exists($colour, self::$_html4Colours) ? self::$_html4Colours[$colour] : $colour);
|
791 |
}
|
792 |
}
|
793 |
|
794 |
-
|
795 |
-
|
796 |
return sprintf(($inc_hash ? '#' : '') . '%02x%02x%02x', str_replace(',','.',round($this->red)), str_replace(',','.',round($this->green)), str_replace(',','.',round($this->blue)));
|
797 |
}
|
798 |
|
@@ -801,7 +823,8 @@ class SassColour extends SassLiteral {
|
|
801 |
* Algorithm from the CSS3 spec: {@link http://www.w3.org/TR/css3-color/#hsl-color}
|
802 |
* @uses hue2rgb()
|
803 |
*/
|
804 |
-
public function hsl2rgb()
|
|
|
805 |
$h = $this->getHue(true) / 360;
|
806 |
$s = $this->getSaturation(true) / 100;
|
807 |
$l = $this->getLightness(true) / 100;
|
@@ -818,7 +841,8 @@ class SassColour extends SassLiteral {
|
|
818 |
/**
|
819 |
* Converts from hue to RGB colourspace
|
820 |
*/
|
821 |
-
public function hue2rgb($p, $q, $t)
|
|
|
822 |
if ($t < 0)
|
823 |
$t += 1;
|
824 |
if ($t > 1)
|
@@ -838,7 +862,8 @@ class SassColour extends SassLiteral {
|
|
838 |
* Converts from RGB to HSL colourspace
|
839 |
* Algorithm adapted from {@link http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript}
|
840 |
*/
|
841 |
-
public function rgb2hsl()
|
|
|
842 |
list($r, $g, $b) = array($this->red / 255, $this->green / 255, $this->blue / 255);
|
843 |
|
844 |
$max = max($r, $g, $b);
|
@@ -848,8 +873,7 @@ class SassColour extends SassLiteral {
|
|
848 |
if ($max == $min) {
|
849 |
$h = 0;
|
850 |
$s = 0;
|
851 |
-
}
|
852 |
-
else if ($max == $r)
|
853 |
$h = 60 * ($g - $b) / $d;
|
854 |
else if ($max == $g)
|
855 |
$h = 60 * ($b - $r) / $d + 120;
|
@@ -881,7 +905,8 @@ class SassColour extends SassLiteral {
|
|
881 |
* @throws SassColourException if mixed colour space keys given or not all
|
882 |
* keys for a colour space are required but not given (contructor)
|
883 |
*/
|
884 |
-
public function assertValid($colour, $all = true)
|
|
|
885 |
if (array_key_exists('red', $colour) || array_key_exists('green', $colour) || array_key_exists('blue', $colour)) {
|
886 |
if (array_key_exists('hue', $colour) || array_key_exists('saturation', $colour) || array_key_exists('lightness', $colour)) {
|
887 |
throw new SassColourException('SassColour can not have HSL and RGB keys specified', SassScriptParser::$context->node);
|
@@ -889,15 +914,15 @@ class SassColour extends SassLiteral {
|
|
889 |
if ($all && (!array_key_exists('red', $colour) || !array_key_exists('green', $colour) || !array_key_exists('blue', $colour))) {
|
890 |
throw new SassColourException('SassColour must have all RGB keys specified', SassScriptParser::$context->node);
|
891 |
}
|
|
|
892 |
return 'rgb';
|
893 |
-
}
|
894 |
-
elseif (array_key_exists('hue', $colour) || array_key_exists('saturation', $colour) || array_key_exists('lightness', $colour)) {
|
895 |
if ($all && (!array_key_exists('hue', $colour) || !array_key_exists('saturation', $colour) || !array_key_exists('lightness', $colour))) {
|
896 |
throw new SassColourException('SassColour must have all HSL keys specified', SassScriptParser::$context->node);
|
897 |
}
|
|
|
898 |
return 'hsl';
|
899 |
-
}
|
900 |
-
elseif ($all && sizeof($colour) < 3) {
|
901 |
throw new SassColourException('SassColour array must have at least 3 elements', SassScriptParser::$context->node);
|
902 |
}
|
903 |
}
|
@@ -908,20 +933,24 @@ class SassColour extends SassLiteral {
|
|
908 |
* @param string the subject string
|
909 |
* @return mixed match at the start of the string or false if no match
|
910 |
*/
|
911 |
-
static
|
|
|
912 |
if (empty(self::$regex)) {
|
913 |
self::$regex = str_replace('{CSS_COLOURS}', join('|', array_reverse(array_keys(self::$svgColours))), self::MATCH);
|
914 |
}
|
|
|
915 |
return (preg_match(self::$regex, strtolower($subject), $matches) ?
|
916 |
$matches[0] : false);
|
917 |
}
|
918 |
|
919 |
-
public function nth($i)
|
|
|
920 |
if ($i == 1) return clone $this;
|
921 |
return new SassBoolean(false);
|
922 |
}
|
923 |
|
924 |
-
public function length()
|
|
|
925 |
return 1;
|
926 |
}
|
927 |
}
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassLiteral.php';
|
13 |
|
14 |
/**
|
15 |
* SassColour class.
|
35 |
* @package PHamlP
|
36 |
* @subpackage Sass.script.literals
|
37 |
*/
|
38 |
+
class SassColour extends SassLiteral
|
39 |
+
{
|
40 |
/**@#+
|
41 |
* Regexes for matching and extracting colours
|
42 |
*/
|
47 |
/**@#-*/
|
48 |
|
49 |
/**@#-*/
|
50 |
+
public static $svgColours = array(
|
51 |
'aliceblue' => '#f0f8ff',
|
52 |
'antiquewhite' => '#faebd7',
|
53 |
'aqua' => '#00ffff',
|
198 |
/**
|
199 |
* @var array reverse array (value => name) of named SVG1.0 colours
|
200 |
*/
|
201 |
+
public static $_svgColours;
|
202 |
|
203 |
/**
|
204 |
* @var array reverse array (value => name) of named HTML4 colours
|
205 |
*/
|
206 |
+
public static $_html4Colours = array(
|
207 |
'#000000' => 'black',
|
208 |
'#000080' => 'navy',
|
209 |
'#0000ff' => 'blue',
|
222 |
'#ffffff' => 'white',
|
223 |
);
|
224 |
|
225 |
+
public static $regex;
|
226 |
|
227 |
/**@#+
|
228 |
* RGB colour components
|
230 |
/**
|
231 |
* @var array RGB colour components. Used to check for RGB attributes.
|
232 |
*/
|
233 |
+
public static $rgb = array('red', 'green', 'blue');
|
234 |
/**
|
235 |
* @var integer red component. 0 - 255
|
236 |
*/
|
250 |
/**
|
251 |
* @var array HSL colour components. Used to check for HSL attributes.
|
252 |
*/
|
253 |
+
public static $hsl = array('hue', 'saturation', 'lightness');
|
254 |
/**
|
255 |
* @var float hue component. 0 - 360
|
256 |
*/
|
283 |
* @param mixed the colour
|
284 |
* @return SassColour
|
285 |
*/
|
286 |
+
public function __construct($colour)
|
287 |
+
{
|
288 |
if (is_string($colour)) {
|
289 |
$colour = strtolower($colour);
|
290 |
if ($colour === self::TRANSPARENT) {
|
292 |
$this->green = 0;
|
293 |
$this->blue = 0;
|
294 |
$this->alpha = 0;
|
295 |
+
} else {
|
|
|
296 |
if (array_key_exists($colour, self::$svgColours)) {
|
297 |
$colour = self::$svgColours[$colour];
|
298 |
}
|
300 |
for ($i = 1; $i < 4; $i++) {
|
301 |
$matches[$i] = str_repeat($matches[$i], 2);
|
302 |
}
|
303 |
+
} else {
|
|
|
304 |
preg_match(self::EXTRACT_6, $colour, $matches);
|
305 |
}
|
306 |
|
312 |
$this->blue = intval($matches[3], 16);
|
313 |
$this->alpha = 1;
|
314 |
}
|
315 |
+
} elseif (is_array($colour)) {
|
|
|
316 |
$scheme = $this->assertValid($colour);
|
317 |
if ($scheme == 'rgb') {
|
318 |
$this->red = $colour['red'];
|
319 |
$this->green = $colour['green'];
|
320 |
$this->blue = $colour['blue'];
|
321 |
$this->alpha = (isset($colour['alpha']) ? $colour['alpha'] : 1);
|
322 |
+
} elseif ($scheme == 'hsl') {
|
|
|
323 |
$this->hue = $colour['hue'];
|
324 |
$this->saturation = $colour['saturation'];
|
325 |
$this->lightness = $colour['lightness'];
|
326 |
$this->alpha = (isset($colour['alpha']) ? $colour['alpha'] : 1);
|
327 |
+
} else {
|
|
|
328 |
$this->red = $colour[0];
|
329 |
$this->green = $colour[1];
|
330 |
$this->blue = $colour[2];
|
331 |
$this->alpha = (isset($colour[3]) ? $colour[3] : 1);
|
332 |
}
|
333 |
+
} else {
|
|
|
334 |
throw new SassColourException('Colour must be a array', SassScriptParser::$context->node);
|
335 |
}
|
336 |
}
|
340 |
* @param mixed SassColour|SassNumber value to add
|
341 |
* @return sassColour the colour result
|
342 |
*/
|
343 |
+
public function op_plus($other)
|
344 |
+
{
|
345 |
if ($other instanceof SassNumber) {
|
346 |
if (!$other->isUnitless()) {
|
347 |
return new SassString($this->toString() . $other->value);
|
350 |
$this->red = $this->getRed() + $other->value;
|
351 |
$this->green = $this->getGreen() + $other->value;
|
352 |
$this->blue = $this->getBlue() + $other->value;
|
353 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
354 |
return new SassString($this->toString() . $other->value);
|
355 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
356 |
+
} else {
|
|
|
357 |
$this->red = $this->getRed() + $other->getRed();
|
358 |
$this->green = $this->getGreen() + $other->getGreen();
|
359 |
$this->blue = $this->getBlue() + $other->getBlue();
|
360 |
}
|
361 |
+
|
362 |
return $this;
|
363 |
}
|
364 |
|
367 |
* @param mixed value (SassColour or SassNumber) to subtract
|
368 |
* @return sassColour the colour result
|
369 |
*/
|
370 |
+
public function op_minus($other)
|
371 |
+
{
|
372 |
if ($other instanceof SassNumber) {
|
373 |
if (!$other->isUnitless()) {
|
374 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
376 |
$this->red = $this->getRed() - $other->value;
|
377 |
$this->green = $this->getGreen() - $other->value;
|
378 |
$this->blue = $this->getBlue() - $other->value;
|
379 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
380 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
381 |
+
} else {
|
|
|
382 |
$this->red = $this->getRed() - $other->getRed();
|
383 |
$this->green = $this->getGreen() - $other->getGreen();
|
384 |
$this->blue = $this->getBlue() - $other->getBlue();
|
385 |
}
|
386 |
+
|
387 |
return $this;
|
388 |
}
|
389 |
|
392 |
* @param mixed SassColour|SassNumber value to multiply by
|
393 |
* @return sassColour the colour result
|
394 |
*/
|
395 |
+
public function op_times($other)
|
396 |
+
{
|
397 |
if ($other instanceof SassNumber) {
|
398 |
if (!$other->isUnitless()) {
|
399 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
401 |
$this->red = $this->getRed() * $other->value;
|
402 |
$this->green = $this->getGreen() * $other->value;
|
403 |
$this->blue = $this->getBlue() * $other->value;
|
404 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
405 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
406 |
+
} else {
|
|
|
407 |
$this->red = $this->getRed() * $other->getRed();
|
408 |
$this->green = $this->getGreen() * $other->getGreen();
|
409 |
$this->blue = $this->getBlue() * $other->getBlue();
|
410 |
}
|
411 |
+
|
412 |
return $this;
|
413 |
}
|
414 |
|
417 |
* @param mixed value (SassColour or SassNumber) to divide by
|
418 |
* @return sassColour the colour result
|
419 |
*/
|
420 |
+
public function op_div($other)
|
421 |
+
{
|
422 |
if ($other instanceof SassNumber) {
|
423 |
if (!$other->isUnitless()) {
|
424 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
426 |
$this->red = $this->getRed() / $other->value;
|
427 |
$this->green = $this->getGreen() / $other->value;
|
428 |
$this->blue = $this->getBlue() / $other->value;
|
429 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
430 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
431 |
+
} else {
|
|
|
432 |
$this->red = $this->getRed() / $other->getRed();
|
433 |
$this->green = $this->getGreen() / $other->getGreen();
|
434 |
$this->blue = $this->getBlue() / $other->getBlue();
|
435 |
}
|
436 |
+
|
437 |
return $this;
|
438 |
}
|
439 |
|
442 |
* @param mixed value (SassColour or SassNumber) to divide by
|
443 |
* @return sassColour the colour result
|
444 |
*/
|
445 |
+
public function op_modulo($other)
|
446 |
+
{
|
447 |
if ($other instanceof SassNumber) {
|
448 |
if (!$other->isUnitless()) {
|
449 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
451 |
$this->red = fmod($this->getRed(), $other->value);
|
452 |
$this->green = fmod($this->getGreen(), $other->value);
|
453 |
$this->blue = fmod($this->getBlue(), $other->value);
|
454 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
455 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
456 |
+
} else {
|
|
|
457 |
$this->red = fmod($this->getRed(), $other->getRed());
|
458 |
$this->green = fmod($this->getGreen(), $other->getGreen());
|
459 |
$this->blue = fmod($this->getBlue(), $other->getBlue());
|
460 |
}
|
461 |
+
|
462 |
return $this;
|
463 |
}
|
464 |
|
467 |
* @param mixed value (SassColour or SassNumber) to bitwise AND with
|
468 |
* @return sassColour the colour result
|
469 |
*/
|
470 |
+
public function op_bw_and($other)
|
471 |
+
{
|
472 |
if ($other instanceof SassNumber) {
|
473 |
if (!$other->isUnitless()) {
|
474 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
476 |
$this->red = $this->getRed() & $other->value;
|
477 |
$this->green = $this->getGreen() & $other->value;
|
478 |
$this->blue = $this->getBlue() & $other->value;
|
479 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
480 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
481 |
+
} else {
|
|
|
482 |
$this->red = $this->getRed() & $other->getRed();
|
483 |
$this->green = $this->getGreen() & $other->getGreen();
|
484 |
$this->blue = $this->getBlue() & $other->getBlue();
|
485 |
}
|
486 |
+
|
487 |
return $this;
|
488 |
}
|
489 |
|
492 |
* @param mixed value (SassColour or SassNumber) to bitwise OR with
|
493 |
* @return sassColour the colour result
|
494 |
*/
|
495 |
+
public function op_bw_or($other)
|
496 |
+
{
|
497 |
if ($other instanceof SassNumber) {
|
498 |
if (!$other->isUnitless()) {
|
499 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
501 |
$this->red = $this->getRed() | $other->value;
|
502 |
$this->green = $this->getGreen() | $other->value;
|
503 |
$this->blue = $this->getBlue() | $other->value;
|
504 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
505 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
506 |
+
} else {
|
|
|
507 |
$this->red = $this->getRed() | $other->getRed();
|
508 |
$this->green = $this->getGreen() | $other->getGreen();
|
509 |
$this->blue = $this->getBlue() | $other->getBlue();
|
510 |
}
|
511 |
+
|
512 |
return $this;
|
513 |
}
|
514 |
|
517 |
* @param mixed value (SassColour or SassNumber) to bitwise XOR with
|
518 |
* @return sassColour the colour result
|
519 |
*/
|
520 |
+
public function op_bw_xor($other)
|
521 |
+
{
|
522 |
if ($other instanceof SassNumber) {
|
523 |
if (!$other->isUnitless()) {
|
524 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
526 |
$this->red = $this->getRed() ^ $other->value;
|
527 |
$this->green = $this->getGreen() ^ $other->value;
|
528 |
$this->blue = $this->getBlue() ^ $other->value;
|
529 |
+
} elseif (!$other instanceof SassColour) {
|
|
|
530 |
throw new SassColourException('Argument must be a SassColour or SassNumber', SassScriptParser::$context->node);
|
531 |
+
} else {
|
|
|
532 |
$this->red = $this->getRed() ^ $other->getRed();
|
533 |
$this->green = $this->getGreen() ^ $other->getGreen();
|
534 |
$this->blue = $this->getBlue() ^ $other->getBlue();
|
535 |
}
|
536 |
+
|
537 |
return $this;
|
538 |
}
|
539 |
|
541 |
* Colour bitwise NOT
|
542 |
* @return sassColour the colour result
|
543 |
*/
|
544 |
+
public function op_not()
|
545 |
+
{
|
546 |
$this->red = ~$this->getRed();
|
547 |
$this->green = ~$this->getGreen();
|
548 |
$this->blue = ~$this->getBlue();
|
549 |
+
|
550 |
return $this;
|
551 |
}
|
552 |
|
555 |
* @param sassNumber amount to shift left by
|
556 |
* @return sassColour the colour result
|
557 |
*/
|
558 |
+
public function op_shiftl($other)
|
559 |
+
{
|
560 |
if (!$other instanceof SassNumber ||!$other->isUnitless()) {
|
561 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
562 |
}
|
563 |
$this->red = $this->getRed() << $other->value;
|
564 |
$this->green = $this->getGreen() << $other->value;
|
565 |
$this->blue = $this->getBlue() << $other->value;
|
566 |
+
|
567 |
return $this;
|
568 |
}
|
569 |
|
572 |
* @param sassNumber amount to shift right by
|
573 |
* @return sassColour the colour result
|
574 |
*/
|
575 |
+
public function op_shiftr($other)
|
576 |
+
{
|
577 |
if (!$other instanceof SassNumber || !$other->isUnitless()) {
|
578 |
throw new SassColourException('Number must be a unitless number', SassScriptParser::$context->node);
|
579 |
}
|
580 |
$this->red = $this->getRed() >> $other->value;
|
581 |
$this->green = $this->getGreen() >> $other->value;
|
582 |
$this->blue = $this->getBlue() >> $other->value;
|
583 |
+
|
584 |
return $this;
|
585 |
}
|
586 |
|
589 |
* RGB or HSL attributes may be changed, but not both at once.
|
590 |
* @param array attributes to change
|
591 |
*/
|
592 |
+
public function with($attributes)
|
593 |
+
{
|
594 |
if ($this->assertValid($attributes, false) === 'hsl') {
|
595 |
$colour = array_merge(array(
|
596 |
'hue' => $this->getHue(),
|
598 |
'lightness' => $this->getLightness(),
|
599 |
'alpha' => $this->alpha
|
600 |
), $attributes);
|
601 |
+
} else {
|
|
|
602 |
$colour = array_merge(array(
|
603 |
'red' => $this->getRed(),
|
604 |
'green' => $this->getGreen(),
|
607 |
), $attributes);
|
608 |
}
|
609 |
|
|
|
610 |
$colour = new SassColour($colour);
|
611 |
$colour->getRed(); # will get RGB and HSL
|
612 |
+
|
613 |
return $colour;
|
614 |
}
|
615 |
|
617 |
* Returns the alpha component (opacity) of this colour.
|
618 |
* @return float the alpha component (opacity) of this colour.
|
619 |
*/
|
620 |
+
public function getAlpha($value = false)
|
621 |
+
{
|
622 |
if ($value && isset($this->alpha->$value)) {
|
623 |
return $this->alpha->value;
|
624 |
}
|
625 |
+
|
626 |
return $this->alpha;
|
627 |
}
|
628 |
|
630 |
* Returns the hue of this colour.
|
631 |
* @return float the hue of this colour.
|
632 |
*/
|
633 |
+
public function getHue($value = false)
|
634 |
+
{
|
635 |
if (is_null($this->hue)) {
|
636 |
$this->rgb2hsl();
|
637 |
}
|
638 |
if ($value && isset($this->hue->value)) {
|
639 |
return $this->hue->value;
|
640 |
}
|
641 |
+
|
642 |
return $this->hue;
|
643 |
}
|
644 |
|
646 |
* Returns the saturation of this colour.
|
647 |
* @return float the saturation of this colour.
|
648 |
*/
|
649 |
+
public function getSaturation($value = false)
|
650 |
+
{
|
651 |
if (is_null($this->saturation)) {
|
652 |
$this->rgb2hsl();
|
653 |
}
|
654 |
if ($value && isset($this->saturation->value)) {
|
655 |
return $this->saturation->value;
|
656 |
}
|
657 |
+
|
658 |
return $this->saturation;
|
659 |
}
|
660 |
|
662 |
* Returns the lightness of this colour.
|
663 |
* @return float the lightness of this colour.
|
664 |
*/
|
665 |
+
public function getLightness($value = false)
|
666 |
+
{
|
667 |
if (is_null($this->lightness)) {
|
668 |
$this->rgb2hsl();
|
669 |
}
|
670 |
if ($value && isset($this->lightness->value)) {
|
671 |
return $this->lightness->value;
|
672 |
}
|
673 |
+
|
674 |
return $this->lightness;
|
675 |
}
|
676 |
|
678 |
* Returns the blue component of this colour.
|
679 |
* @return integer the blue component of this colour.
|
680 |
*/
|
681 |
+
public function getBlue($value = false)
|
682 |
+
{
|
683 |
if (is_null($this->blue)) {
|
684 |
$this->hsl2rgb();
|
685 |
}
|
686 |
if ($value && isset($this->blue->value)) {
|
687 |
return $this->blue->value;
|
688 |
}
|
689 |
+
|
690 |
return max(0, min(255, str_replace(',','.',round($this->blue))));
|
691 |
}
|
692 |
|
694 |
* Returns the green component of this colour.
|
695 |
* @return integer the green component of this colour.
|
696 |
*/
|
697 |
+
public function getGreen($value = false)
|
698 |
+
{
|
699 |
if (is_null($this->green)) {
|
700 |
$this->hsl2rgb();
|
701 |
}
|
702 |
if ($value && isset($this->green->value)) {
|
703 |
return $this->green->value;
|
704 |
}
|
705 |
+
|
706 |
return max(0, min(255, str_replace(',','.',round($this->green))));
|
707 |
}
|
708 |
|
710 |
* Returns the red component of this colour.
|
711 |
* @return integer the red component of this colour.
|
712 |
*/
|
713 |
+
public function getRed($value = false)
|
714 |
+
{
|
715 |
if (is_null($this->red)) {
|
716 |
$this->hsl2rgb();
|
717 |
}
|
718 |
if ($value && isset($this->red->value)) {
|
719 |
return $this->red->value;
|
720 |
}
|
721 |
+
|
722 |
return max(0, min(255, str_replace(',','.',round($this->red))));
|
723 |
}
|
724 |
|
726 |
* Returns an array with the RGB components of this colour.
|
727 |
* @return array the RGB components of this colour
|
728 |
*/
|
729 |
+
public function getRgb()
|
730 |
+
{
|
731 |
return array($this->red, $this->green, $this->blue);
|
732 |
}
|
733 |
|
735 |
* Returns an array with the RGB and alpha components of this colour.
|
736 |
* @return array the RGB and alpha components of this colour
|
737 |
*/
|
738 |
+
public function getRgba()
|
739 |
+
{
|
740 |
return array($this->getRed(), $this->getGreen(), $this->getBlue(), $this->alpha);
|
741 |
}
|
742 |
|
744 |
* Returns an array with the HSL components of this colour.
|
745 |
* @return array the HSL components of this colour
|
746 |
*/
|
747 |
+
public function getHsl()
|
748 |
+
{
|
749 |
return array($this->getHue(), $this->getSaturation(), $this->getLightness());
|
750 |
}
|
751 |
|
753 |
* Returns an array with the HSL and alpha components of this colour.
|
754 |
* @return array the HSL and alpha components of this colour
|
755 |
*/
|
756 |
+
public function getHsla()
|
757 |
+
{
|
758 |
return array($this->getHue(), $this->getSaturation(), $this->getLightness(), $this->alpha);
|
759 |
}
|
760 |
|
763 |
* @return array the colour
|
764 |
* @deprecated
|
765 |
*/
|
766 |
+
public function getValue()
|
767 |
+
{
|
768 |
return $this->rgb;
|
769 |
}
|
770 |
|
772 |
* Returns whether this colour object is translucent; that is, whether the alpha channel is non-1.
|
773 |
* @return boolean true if this colour is translucent, false if not
|
774 |
*/
|
775 |
+
public function isTranslucent()
|
776 |
+
{
|
777 |
return $this->alpha < 1;
|
778 |
}
|
779 |
|
782 |
* @param boolean whether to use CSS3 SVG1.0 colour names
|
783 |
* @return string the colour as a named colour, rgba(r,g,g,a) or #rrggbb
|
784 |
*/
|
785 |
+
public function toString($css3 = true)
|
786 |
+
{
|
787 |
$rgba = $this->getRgba();
|
788 |
|
789 |
foreach ($rgba as $k => $v) {
|
794 |
|
795 |
if ($rgba[3] == 0) {
|
796 |
return 'transparent';
|
797 |
+
} elseif ($rgba[3] < 1) {
|
|
|
798 |
$rgba[3] = str_replace(',','.',round($rgba[3], 2));
|
799 |
+
|
800 |
return sprintf('rgba(%d, %d, %d, %s)', $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
|
801 |
+
} else {
|
|
|
802 |
$colour = sprintf('#%02x%02x%02x', str_replace(',','.',round($rgba[0])), str_replace(',','.',round($rgba[1])), str_replace(',','.',round($rgba[2])));
|
803 |
}
|
804 |
|
806 |
if (empty(self::$_svgColours)) {
|
807 |
self::$_svgColours = array_flip(self::$svgColours);
|
808 |
}
|
809 |
+
|
810 |
return (array_key_exists($colour, self::$_svgColours) ? self::$_svgColours[$colour] : $colour);
|
811 |
+
} else {
|
|
|
812 |
return (array_key_exists($colour, self::$_html4Colours) ? self::$_html4Colours[$colour] : $colour);
|
813 |
}
|
814 |
}
|
815 |
|
816 |
+
public function asHex($inc_hash = TRUE)
|
817 |
+
{
|
818 |
return sprintf(($inc_hash ? '#' : '') . '%02x%02x%02x', str_replace(',','.',round($this->red)), str_replace(',','.',round($this->green)), str_replace(',','.',round($this->blue)));
|
819 |
}
|
820 |
|
823 |
* Algorithm from the CSS3 spec: {@link http://www.w3.org/TR/css3-color/#hsl-color}
|
824 |
* @uses hue2rgb()
|
825 |
*/
|
826 |
+
public function hsl2rgb()
|
827 |
+
{
|
828 |
$h = $this->getHue(true) / 360;
|
829 |
$s = $this->getSaturation(true) / 100;
|
830 |
$l = $this->getLightness(true) / 100;
|
841 |
/**
|
842 |
* Converts from hue to RGB colourspace
|
843 |
*/
|
844 |
+
public function hue2rgb($p, $q, $t)
|
845 |
+
{
|
846 |
if ($t < 0)
|
847 |
$t += 1;
|
848 |
if ($t > 1)
|
862 |
* Converts from RGB to HSL colourspace
|
863 |
* Algorithm adapted from {@link http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript}
|
864 |
*/
|
865 |
+
public function rgb2hsl()
|
866 |
+
{
|
867 |
list($r, $g, $b) = array($this->red / 255, $this->green / 255, $this->blue / 255);
|
868 |
|
869 |
$max = max($r, $g, $b);
|
873 |
if ($max == $min) {
|
874 |
$h = 0;
|
875 |
$s = 0;
|
876 |
+
} elseif ($max == $r)
|
|
|
877 |
$h = 60 * ($g - $b) / $d;
|
878 |
else if ($max == $g)
|
879 |
$h = 60 * ($b - $r) / $d + 120;
|
905 |
* @throws SassColourException if mixed colour space keys given or not all
|
906 |
* keys for a colour space are required but not given (contructor)
|
907 |
*/
|
908 |
+
public function assertValid($colour, $all = true)
|
909 |
+
{
|
910 |
if (array_key_exists('red', $colour) || array_key_exists('green', $colour) || array_key_exists('blue', $colour)) {
|
911 |
if (array_key_exists('hue', $colour) || array_key_exists('saturation', $colour) || array_key_exists('lightness', $colour)) {
|
912 |
throw new SassColourException('SassColour can not have HSL and RGB keys specified', SassScriptParser::$context->node);
|
914 |
if ($all && (!array_key_exists('red', $colour) || !array_key_exists('green', $colour) || !array_key_exists('blue', $colour))) {
|
915 |
throw new SassColourException('SassColour must have all RGB keys specified', SassScriptParser::$context->node);
|
916 |
}
|
917 |
+
|
918 |
return 'rgb';
|
919 |
+
} elseif (array_key_exists('hue', $colour) || array_key_exists('saturation', $colour) || array_key_exists('lightness', $colour)) {
|
|
|
920 |
if ($all && (!array_key_exists('hue', $colour) || !array_key_exists('saturation', $colour) || !array_key_exists('lightness', $colour))) {
|
921 |
throw new SassColourException('SassColour must have all HSL keys specified', SassScriptParser::$context->node);
|
922 |
}
|
923 |
+
|
924 |
return 'hsl';
|
925 |
+
} elseif ($all && sizeof($colour) < 3) {
|
|
|
926 |
throw new SassColourException('SassColour array must have at least 3 elements', SassScriptParser::$context->node);
|
927 |
}
|
928 |
}
|
933 |
* @param string the subject string
|
934 |
* @return mixed match at the start of the string or false if no match
|
935 |
*/
|
936 |
+
public static function isa($subject)
|
937 |
+
{
|
938 |
if (empty(self::$regex)) {
|
939 |
self::$regex = str_replace('{CSS_COLOURS}', join('|', array_reverse(array_keys(self::$svgColours))), self::MATCH);
|
940 |
}
|
941 |
+
|
942 |
return (preg_match(self::$regex, strtolower($subject), $matches) ?
|
943 |
$matches[0] : false);
|
944 |
}
|
945 |
|
946 |
+
public function nth($i)
|
947 |
+
{
|
948 |
if ($i == 1) return clone $this;
|
949 |
return new SassBoolean(false);
|
950 |
}
|
951 |
|
952 |
+
public function length()
|
953 |
+
{
|
954 |
return 1;
|
955 |
}
|
956 |
}
|
lib/phpsass/script/literals/SassList.php
CHANGED
@@ -9,74 +9,76 @@
|
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassBoolean class.
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.script.literals
|
18 |
*/
|
19 |
-
class SassList extends SassLiteral
|
20 |
-
|
21 |
-
|
22 |
|
23 |
/**
|
24 |
* SassBoolean constructor
|
25 |
* @param string value of the boolean type
|
26 |
* @return SassBoolean
|
27 |
*/
|
28 |
-
public function __construct($value, $separator = 'auto')
|
|
|
29 |
if (is_array($value)) {
|
30 |
$this->value = $value;
|
31 |
$this->separator = ($separator == 'auto' ? ', ' : $separator);
|
32 |
-
}
|
33 |
-
else if ($value == '()'){
|
34 |
$this->value = array();
|
35 |
$this->separator = ($separator == 'auto' ? ', ' : $separator);
|
36 |
-
}
|
37 |
-
else if (list($list, $separator) = $this->_parse_list($value, $separator, true, SassScriptParser::$context)) {
|
38 |
$this->value = $list;
|
39 |
$this->separator = ($separator == ',' ? ', ' : ' ');
|
40 |
-
}
|
41 |
-
else {
|
42 |
throw new SassListException('Invalid SassList', SassScriptParser::$context->node);
|
43 |
}
|
44 |
}
|
45 |
|
46 |
-
function nth($i)
|
|
|
47 |
$i = $i - 1; # SASS uses 1-offset arrays
|
48 |
if (isset($this->value[$i])) {
|
49 |
return $this->value[$i];
|
50 |
}
|
|
|
51 |
return new SassBoolean(false);
|
52 |
}
|
53 |
|
54 |
-
function length()
|
|
|
55 |
return count($this->value);
|
56 |
}
|
57 |
|
58 |
-
function append($other, $separator = null)
|
|
|
59 |
if ($separator) {
|
60 |
$this->separator = $separator;
|
61 |
}
|
62 |
if ($other instanceof SassList) {
|
63 |
$this->value = array_merge($this->value, $other->value);
|
64 |
-
}
|
65 |
-
else if ($other instanceof SassLiteral) {
|
66 |
$this->value[] = $other;
|
67 |
-
}
|
68 |
-
else {
|
69 |
throw new SassListException('Appendation can only occur with literals', SassScriptParser::$context->node);
|
70 |
}
|
71 |
}
|
72 |
|
73 |
// New function index returns the list index of a value within a list. For example: index(1px solid red, solid) returns 2. When the value is not found false is returned.
|
74 |
-
function index($value)
|
|
|
75 |
for ($i = 0; $i < count($this->value); $i++) {
|
76 |
if (trim((string) $value) == trim((string) $this->value[$i])) {
|
77 |
return new SassNumber($i);
|
78 |
}
|
79 |
}
|
|
|
80 |
return new SassBoolean(false);
|
81 |
}
|
82 |
|
@@ -84,7 +86,8 @@ class SassList extends SassLiteral {
|
|
84 |
* Returns the value of this boolean.
|
85 |
* @return boolean the value of this boolean
|
86 |
*/
|
87 |
-
public function getValue()
|
|
|
88 |
$result = array();
|
89 |
foreach ($this->value as $k => $v) {
|
90 |
if ($v instanceOf SassString) {
|
@@ -103,6 +106,7 @@ class SassList extends SassLiteral {
|
|
103 |
}
|
104 |
}
|
105 |
$this->value = $result;
|
|
|
106 |
return $this->value;
|
107 |
}
|
108 |
|
@@ -110,7 +114,8 @@ class SassList extends SassLiteral {
|
|
110 |
* Returns a string representation of the value.
|
111 |
* @return string string representation of the value.
|
112 |
*/
|
113 |
-
public function toString()
|
|
|
114 |
$aliases = array(
|
115 |
'comma' => ',',
|
116 |
'space' => '',
|
@@ -119,6 +124,7 @@ class SassList extends SassLiteral {
|
|
119 |
if (isset($aliases[$this->separator])) {
|
120 |
$this->separator = $aliases[$this->separator];
|
121 |
}
|
|
|
122 |
return implode($this->separator . ' ', $this->getValue());
|
123 |
}
|
124 |
|
@@ -128,12 +134,15 @@ class SassList extends SassLiteral {
|
|
128 |
* @param string the subject string
|
129 |
* @return mixed match at the start of the string or false if no match
|
130 |
*/
|
131 |
-
public static function isa($subject)
|
|
|
132 |
list($list, $separator) = self::_parse_list($subject, 'auto', false);
|
|
|
133 |
return count($list) > 1 ? $subject : FALSE;
|
134 |
}
|
135 |
|
136 |
-
public static function _parse_list($list, $separator = 'auto', $lex = true, $context = null)
|
|
|
137 |
if ($lex) {
|
138 |
$context = new SassContext($context);
|
139 |
$list = SassScriptParser::$instance->evaluate($list, $context);
|
@@ -146,8 +155,7 @@ class SassList extends SassLiteral {
|
|
146 |
$separator = ' ';
|
147 |
$list = self::_build_list($list, ' ');
|
148 |
}
|
149 |
-
}
|
150 |
-
else {
|
151 |
$list = self::_build_list($list, $separator);
|
152 |
}
|
153 |
|
@@ -157,10 +165,12 @@ class SassList extends SassLiteral {
|
|
157 |
$list[$k] = SassScriptParser::$instance->evaluate($v, $context);
|
158 |
}
|
159 |
}
|
|
|
160 |
return array($list, $separator);
|
161 |
}
|
162 |
|
163 |
-
public static function _build_list($list, $separator = ',')
|
|
|
164 |
if (is_object($list)) {
|
165 |
$list = $list->value;
|
166 |
}
|
@@ -178,15 +188,14 @@ class SassList extends SassLiteral {
|
|
178 |
$braces = 0;
|
179 |
$quotes = false;
|
180 |
$stack = '';
|
181 |
-
for($i = 0; $i < strlen($list); $i++) {
|
182 |
$char = substr($list, $i, 1);
|
183 |
switch ($char) {
|
184 |
case '"':
|
185 |
case "'":
|
186 |
if (!$quotes) {
|
187 |
$quotes = $char;
|
188 |
-
}
|
189 |
-
else if ($quotes && $quotes == $char) {
|
190 |
$quotes = false;
|
191 |
}
|
192 |
$stack .= $char;
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassLiteral.php';
|
13 |
|
14 |
/**
|
15 |
* SassBoolean class.
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.script.literals
|
18 |
*/
|
19 |
+
class SassList extends SassLiteral
|
20 |
+
{
|
21 |
+
public $separator = ' ';
|
22 |
|
23 |
/**
|
24 |
* SassBoolean constructor
|
25 |
* @param string value of the boolean type
|
26 |
* @return SassBoolean
|
27 |
*/
|
28 |
+
public function __construct($value, $separator = 'auto')
|
29 |
+
{
|
30 |
if (is_array($value)) {
|
31 |
$this->value = $value;
|
32 |
$this->separator = ($separator == 'auto' ? ', ' : $separator);
|
33 |
+
} elseif ($value == '()') {
|
|
|
34 |
$this->value = array();
|
35 |
$this->separator = ($separator == 'auto' ? ', ' : $separator);
|
36 |
+
} elseif (list($list, $separator) = $this->_parse_list($value, $separator, true, SassScriptParser::$context)) {
|
|
|
37 |
$this->value = $list;
|
38 |
$this->separator = ($separator == ',' ? ', ' : ' ');
|
39 |
+
} else {
|
|
|
40 |
throw new SassListException('Invalid SassList', SassScriptParser::$context->node);
|
41 |
}
|
42 |
}
|
43 |
|
44 |
+
public function nth($i)
|
45 |
+
{
|
46 |
$i = $i - 1; # SASS uses 1-offset arrays
|
47 |
if (isset($this->value[$i])) {
|
48 |
return $this->value[$i];
|
49 |
}
|
50 |
+
|
51 |
return new SassBoolean(false);
|
52 |
}
|
53 |
|
54 |
+
public function length()
|
55 |
+
{
|
56 |
return count($this->value);
|
57 |
}
|
58 |
|
59 |
+
public function append($other, $separator = null)
|
60 |
+
{
|
61 |
if ($separator) {
|
62 |
$this->separator = $separator;
|
63 |
}
|
64 |
if ($other instanceof SassList) {
|
65 |
$this->value = array_merge($this->value, $other->value);
|
66 |
+
} elseif ($other instanceof SassLiteral) {
|
|
|
67 |
$this->value[] = $other;
|
68 |
+
} else {
|
|
|
69 |
throw new SassListException('Appendation can only occur with literals', SassScriptParser::$context->node);
|
70 |
}
|
71 |
}
|
72 |
|
73 |
// New function index returns the list index of a value within a list. For example: index(1px solid red, solid) returns 2. When the value is not found false is returned.
|
74 |
+
public function index($value)
|
75 |
+
{
|
76 |
for ($i = 0; $i < count($this->value); $i++) {
|
77 |
if (trim((string) $value) == trim((string) $this->value[$i])) {
|
78 |
return new SassNumber($i);
|
79 |
}
|
80 |
}
|
81 |
+
|
82 |
return new SassBoolean(false);
|
83 |
}
|
84 |
|
86 |
* Returns the value of this boolean.
|
87 |
* @return boolean the value of this boolean
|
88 |
*/
|
89 |
+
public function getValue()
|
90 |
+
{
|
91 |
$result = array();
|
92 |
foreach ($this->value as $k => $v) {
|
93 |
if ($v instanceOf SassString) {
|
106 |
}
|
107 |
}
|
108 |
$this->value = $result;
|
109 |
+
|
110 |
return $this->value;
|
111 |
}
|
112 |
|
114 |
* Returns a string representation of the value.
|
115 |
* @return string string representation of the value.
|
116 |
*/
|
117 |
+
public function toString()
|
118 |
+
{
|
119 |
$aliases = array(
|
120 |
'comma' => ',',
|
121 |
'space' => '',
|
124 |
if (isset($aliases[$this->separator])) {
|
125 |
$this->separator = $aliases[$this->separator];
|
126 |
}
|
127 |
+
|
128 |
return implode($this->separator . ' ', $this->getValue());
|
129 |
}
|
130 |
|
134 |
* @param string the subject string
|
135 |
* @return mixed match at the start of the string or false if no match
|
136 |
*/
|
137 |
+
public static function isa($subject)
|
138 |
+
{
|
139 |
list($list, $separator) = self::_parse_list($subject, 'auto', false);
|
140 |
+
|
141 |
return count($list) > 1 ? $subject : FALSE;
|
142 |
}
|
143 |
|
144 |
+
public static function _parse_list($list, $separator = 'auto', $lex = true, $context = null)
|
145 |
+
{
|
146 |
if ($lex) {
|
147 |
$context = new SassContext($context);
|
148 |
$list = SassScriptParser::$instance->evaluate($list, $context);
|
155 |
$separator = ' ';
|
156 |
$list = self::_build_list($list, ' ');
|
157 |
}
|
158 |
+
} else {
|
|
|
159 |
$list = self::_build_list($list, $separator);
|
160 |
}
|
161 |
|
165 |
$list[$k] = SassScriptParser::$instance->evaluate($v, $context);
|
166 |
}
|
167 |
}
|
168 |
+
|
169 |
return array($list, $separator);
|
170 |
}
|
171 |
|
172 |
+
public static function _build_list($list, $separator = ',')
|
173 |
+
{
|
174 |
if (is_object($list)) {
|
175 |
$list = $list->value;
|
176 |
}
|
188 |
$braces = 0;
|
189 |
$quotes = false;
|
190 |
$stack = '';
|
191 |
+
for ($i = 0; $i < strlen($list); $i++) {
|
192 |
$char = substr($list, $i, 1);
|
193 |
switch ($char) {
|
194 |
case '"':
|
195 |
case "'":
|
196 |
if (!$quotes) {
|
197 |
$quotes = $char;
|
198 |
+
} elseif ($quotes && $quotes == $char) {
|
|
|
199 |
$quotes = false;
|
200 |
}
|
201 |
$stack .= $char;
|
lib/phpsass/script/literals/SassLiteral.php
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassLiteral class.
|
@@ -19,11 +19,12 @@ require_once('SassLiteralExceptions.php');
|
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.script.literals
|
21 |
*/
|
22 |
-
abstract class SassLiteral
|
|
|
23 |
/**
|
24 |
* @var array maps class names to data types
|
25 |
*/
|
26 |
-
static
|
27 |
'SassBoolean' => 'bool',
|
28 |
'SassColour' => 'color',
|
29 |
'SassNumber' => 'number',
|
@@ -41,7 +42,8 @@ abstract class SassLiteral {
|
|
41 |
* @param string value of the literal type
|
42 |
* @return SassLiteral
|
43 |
*/
|
44 |
-
public function __construct($value = null, $context)
|
|
|
45 |
$this->value = $value;
|
46 |
$this->context = $context;
|
47 |
}
|
@@ -51,17 +53,18 @@ abstract class SassLiteral {
|
|
51 |
* @param string name of property to get
|
52 |
* @return mixed return value of getter function
|
53 |
*/
|
54 |
-
public function __get($name)
|
|
|
55 |
$getter = 'get' . ucfirst($name);
|
56 |
if (method_exists($this, $getter)) {
|
57 |
return $this->$getter();
|
58 |
-
}
|
59 |
-
else {
|
60 |
throw new SassLiteralException('No getter function for ' . $name, SassScriptParser::$context->node);
|
61 |
}
|
62 |
}
|
63 |
|
64 |
-
public function __toString()
|
|
|
65 |
return $this->toString();
|
66 |
}
|
67 |
|
@@ -69,15 +72,17 @@ abstract class SassLiteral {
|
|
69 |
* Returns the boolean representation of the value of this
|
70 |
* @return boolean the boolean representation of the value of this
|
71 |
*/
|
72 |
-
public function toBoolean()
|
73 |
-
|
|
|
74 |
}
|
75 |
|
76 |
/**
|
77 |
* Returns the type of this
|
78 |
* @return string the type of this
|
79 |
*/
|
80 |
-
public function getTypeOf()
|
|
|
81 |
return self::$typeOf[get_class($this)];
|
82 |
}
|
83 |
|
@@ -85,11 +90,13 @@ abstract class SassLiteral {
|
|
85 |
* Returns the value of this
|
86 |
* @return mixed the value of this
|
87 |
*/
|
88 |
-
public function getValue()
|
|
|
89 |
throw new SassLiteralException('Child classes must override this method', SassScriptParser::$context->node);
|
90 |
}
|
91 |
|
92 |
-
public function getChildren()
|
|
|
93 |
return array();
|
94 |
}
|
95 |
|
@@ -97,7 +104,8 @@ abstract class SassLiteral {
|
|
97 |
* Adds a child object to this.
|
98 |
* @param sassLiteral the child object
|
99 |
*/
|
100 |
-
public function addChild($sassLiteral)
|
|
|
101 |
$this->children[] = $sassLiteral;
|
102 |
}
|
103 |
|
@@ -106,7 +114,8 @@ abstract class SassLiteral {
|
|
106 |
* @param sassLiteral value to add
|
107 |
* @return sassString the string values of this and other with no seperation
|
108 |
*/
|
109 |
-
public function op_plus($other)
|
|
|
110 |
return new SassString($this->toString().$other->toString());
|
111 |
}
|
112 |
|
@@ -115,7 +124,8 @@ abstract class SassLiteral {
|
|
115 |
* @param SassLiteral value to subtract
|
116 |
* @return sassString the string values of this and other seperated by '-'
|
117 |
*/
|
118 |
-
public function op_minus($other)
|
|
|
119 |
return new SassString($this->toString().'-'.$other->toString());
|
120 |
}
|
121 |
|
@@ -124,7 +134,8 @@ abstract class SassLiteral {
|
|
124 |
* @param SassLiteral value to multiply by
|
125 |
* @return sassString the string values of this and other seperated by '*'
|
126 |
*/
|
127 |
-
public function op_times($other)
|
|
|
128 |
return new SassString($this->toString().'*'.$other->toString());
|
129 |
}
|
130 |
|
@@ -133,7 +144,8 @@ abstract class SassLiteral {
|
|
133 |
* @param SassLiteral value to divide by
|
134 |
* @return sassString the string values of this and other seperated by '/'
|
135 |
*/
|
136 |
-
public function op_div($other)
|
|
|
137 |
return new SassString($this->toString().' / '.$other->toString());
|
138 |
}
|
139 |
|
@@ -143,7 +155,8 @@ abstract class SassLiteral {
|
|
143 |
* @return SassLiteral result
|
144 |
* @throws Exception if modulo not supported for the data type
|
145 |
*/
|
146 |
-
public function op_modulo($other)
|
|
|
147 |
throw new SassLiteralException(get_class($this) . ' does not support Modulus', SassScriptParser::$context->node);
|
148 |
}
|
149 |
|
@@ -153,7 +166,8 @@ abstract class SassLiteral {
|
|
153 |
* @return string result
|
154 |
* @throws Exception if bitwise AND not supported for the data type
|
155 |
*/
|
156 |
-
public function op_bw_and($other)
|
|
|
157 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise AND', SassScriptParser::$context->node);
|
158 |
}
|
159 |
|
@@ -163,7 +177,8 @@ abstract class SassLiteral {
|
|
163 |
* @return string result
|
164 |
* @throws Exception if bitwise OR not supported for the data type
|
165 |
*/
|
166 |
-
public function op_bw_or($other)
|
|
|
167 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise OR', SassScriptParser::$context->node);
|
168 |
}
|
169 |
|
@@ -173,7 +188,8 @@ abstract class SassLiteral {
|
|
173 |
* @return string result
|
174 |
* @throws Exception if bitwise XOR not supported for the data type
|
175 |
*/
|
176 |
-
public function op_bw_xor($other)
|
|
|
177 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise XOR', SassScriptParser::$context->node);
|
178 |
}
|
179 |
|
@@ -183,7 +199,8 @@ abstract class SassLiteral {
|
|
183 |
* @return string result
|
184 |
* @throws Exception if bitwise NOT not supported for the data type
|
185 |
*/
|
186 |
-
public function op_bw_not()
|
|
|
187 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise NOT', SassScriptParser::$context->node);
|
188 |
}
|
189 |
|
@@ -193,7 +210,8 @@ abstract class SassLiteral {
|
|
193 |
* @return string result
|
194 |
* @throws Exception if bitwise Shift Left not supported for the data type
|
195 |
*/
|
196 |
-
public function op_shiftl($other)
|
|
|
197 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise Shift Left', SassScriptParser::$context->node);
|
198 |
}
|
199 |
|
@@ -203,7 +221,8 @@ abstract class SassLiteral {
|
|
203 |
* @return string result
|
204 |
* @throws Exception if bitwise Shift Right not supported for the data type
|
205 |
*/
|
206 |
-
public function op_shiftr($other)
|
|
|
207 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise Shift Right', SassScriptParser::$context->node);
|
208 |
}
|
209 |
|
@@ -212,7 +231,8 @@ abstract class SassLiteral {
|
|
212 |
* @param sassLiteral the value to and with this
|
213 |
* @return SassLiteral other if this is boolean true, this if false
|
214 |
*/
|
215 |
-
public function op_and($other)
|
|
|
216 |
return ($this->toBoolean() ? $other : $this);
|
217 |
}
|
218 |
|
@@ -221,11 +241,13 @@ abstract class SassLiteral {
|
|
221 |
* @param sassLiteral the value to or with this
|
222 |
* @return SassLiteral this if this is boolean true, other if false
|
223 |
*/
|
224 |
-
public function op_or($other)
|
|
|
225 |
return ($this->toBoolean() ? $this : $other);
|
226 |
}
|
227 |
|
228 |
-
public function op_assign($other)
|
|
|
229 |
return $other;
|
230 |
}
|
231 |
|
@@ -235,7 +257,8 @@ abstract class SassLiteral {
|
|
235 |
* @return SassBoolean SassBoolean object with the value true if this or
|
236 |
* other, but not both, are true, false if not
|
237 |
*/
|
238 |
-
public function op_xor($other)
|
|
|
239 |
return new SassBoolean($this->toBoolean() xor $other->toBoolean());
|
240 |
}
|
241 |
|
@@ -244,7 +267,8 @@ abstract class SassLiteral {
|
|
244 |
* @return SassBoolean SassBoolean object with the value true if the
|
245 |
* boolean of this is false or false if it is true
|
246 |
*/
|
247 |
-
public function op_not()
|
|
|
248 |
return new SassBoolean(!$this->toBoolean());
|
249 |
}
|
250 |
|
@@ -254,7 +278,8 @@ abstract class SassLiteral {
|
|
254 |
* @return SassBoolean SassBoolean object with the value true if the values
|
255 |
* of this is greater than the value of other, false if it is not
|
256 |
*/
|
257 |
-
public function op_gt($other)
|
|
|
258 |
return new SassBoolean($this->value > $other->value);
|
259 |
}
|
260 |
|
@@ -264,7 +289,8 @@ abstract class SassLiteral {
|
|
264 |
* @return SassBoolean SassBoolean object with the value true if the values
|
265 |
* of this is greater than or equal to the value of other, false if it is not
|
266 |
*/
|
267 |
-
public function op_gte($other)
|
|
|
268 |
return new SassBoolean($this->value >= $other->value);
|
269 |
}
|
270 |
|
@@ -274,7 +300,8 @@ abstract class SassLiteral {
|
|
274 |
* @return SassBoolean SassBoolean object with the value true if the values
|
275 |
* of this is less than the value of other, false if it is not
|
276 |
*/
|
277 |
-
public function op_lt($other)
|
|
|
278 |
return new SassBoolean($this->value < $other->value);
|
279 |
}
|
280 |
|
@@ -284,7 +311,8 @@ abstract class SassLiteral {
|
|
284 |
* @return SassBoolean SassBoolean object with the value true if the values
|
285 |
* of this is less than or equal to the value of other, false if it is not
|
286 |
*/
|
287 |
-
public function op_lte($other)
|
|
|
288 |
return new SassBoolean($this->value <= $other->value);
|
289 |
}
|
290 |
|
@@ -294,7 +322,8 @@ abstract class SassLiteral {
|
|
294 |
* @return SassBoolean SassBoolean object with the value true if this and
|
295 |
* other are equal, false if they are not
|
296 |
*/
|
297 |
-
public function op_eq($other)
|
|
|
298 |
return new SassBoolean($this == $other);
|
299 |
}
|
300 |
|
@@ -304,7 +333,8 @@ abstract class SassLiteral {
|
|
304 |
* @return SassBoolean SassBoolean object with the value true if this and
|
305 |
* other are not equal, false if they are
|
306 |
*/
|
307 |
-
public function op_neq($other)
|
|
|
308 |
return new SassBoolean(!$this->op_eq($other)->toBoolean());
|
309 |
}
|
310 |
|
@@ -313,7 +343,8 @@ abstract class SassLiteral {
|
|
313 |
* @param sassLiteral the value to concatenate with a space to this
|
314 |
* @return sassString the string values of this and other seperated by " "
|
315 |
*/
|
316 |
-
public function op_concat($other)
|
|
|
317 |
return new SassString($this->toString().' '.$other->toString());
|
318 |
}
|
319 |
|
@@ -322,7 +353,8 @@ abstract class SassLiteral {
|
|
322 |
* @param sassLiteral the value to concatenate with a comma to this
|
323 |
* @return sassString the string values of this and other seperated by ","
|
324 |
*/
|
325 |
-
public function op_comma($other)
|
|
|
326 |
return new SassString($this->toString().', '.$other->toString());
|
327 |
}
|
328 |
|
@@ -332,7 +364,8 @@ abstract class SassLiteral {
|
|
332 |
* @param string expected type
|
333 |
* @throws SassScriptFunctionException if value is not the expected type
|
334 |
*/
|
335 |
-
public static function assertType($literal, $type)
|
|
|
336 |
if (!$literal instanceof $type) {
|
337 |
throw new SassScriptFunctionException(($literal instanceof SassLiteral ? get_class($literal) : 'literal') . ' must be a ' . $type, SassScriptParser::$context->node);
|
338 |
}
|
@@ -346,7 +379,8 @@ abstract class SassLiteral {
|
|
346 |
* @param string the units.
|
347 |
* @throws SassScriptFunctionException if value is not the expected type
|
348 |
*/
|
349 |
-
public static function assertInRange($literal, $min, $max, $units = '')
|
|
|
350 |
if ($literal->value < $min || $literal->value > $max) {
|
351 |
throw new SassScriptFunctionException($literal->typeOf . ' must be between ' . $min.$units . ' and ' . $max.$units . ' inclusive', SassScriptParser::$context->node);
|
352 |
}
|
@@ -358,7 +392,8 @@ abstract class SassLiteral {
|
|
358 |
*/
|
359 |
abstract public function toString();
|
360 |
|
361 |
-
public function render()
|
|
|
362 |
return $this->toString();
|
363 |
}
|
364 |
|
@@ -368,7 +403,8 @@ abstract class SassLiteral {
|
|
368 |
* @param string the subject string
|
369 |
* @return mixed match at the start of the string or false if no match
|
370 |
*/
|
371 |
-
public static function isa($subject)
|
|
|
372 |
throw new SassLiteralException('Child classes must override this method');
|
373 |
}
|
374 |
}
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassLiteralExceptions.php';
|
13 |
|
14 |
/**
|
15 |
* SassLiteral class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.script.literals
|
21 |
*/
|
22 |
+
abstract class SassLiteral
|
23 |
+
{
|
24 |
/**
|
25 |
* @var array maps class names to data types
|
26 |
*/
|
27 |
+
public static $typeOf = array(
|
28 |
'SassBoolean' => 'bool',
|
29 |
'SassColour' => 'color',
|
30 |
'SassNumber' => 'number',
|
42 |
* @param string value of the literal type
|
43 |
* @return SassLiteral
|
44 |
*/
|
45 |
+
public function __construct($value = null, $context)
|
46 |
+
{
|
47 |
$this->value = $value;
|
48 |
$this->context = $context;
|
49 |
}
|
53 |
* @param string name of property to get
|
54 |
* @return mixed return value of getter function
|
55 |
*/
|
56 |
+
public function __get($name)
|
57 |
+
{
|
58 |
$getter = 'get' . ucfirst($name);
|
59 |
if (method_exists($this, $getter)) {
|
60 |
return $this->$getter();
|
61 |
+
} else {
|
|
|
62 |
throw new SassLiteralException('No getter function for ' . $name, SassScriptParser::$context->node);
|
63 |
}
|
64 |
}
|
65 |
|
66 |
+
public function __toString()
|
67 |
+
{
|
68 |
return $this->toString();
|
69 |
}
|
70 |
|
72 |
* Returns the boolean representation of the value of this
|
73 |
* @return boolean the boolean representation of the value of this
|
74 |
*/
|
75 |
+
public function toBoolean()
|
76 |
+
{
|
77 |
+
return (boolean) $this->value || $this->value === null;
|
78 |
}
|
79 |
|
80 |
/**
|
81 |
* Returns the type of this
|
82 |
* @return string the type of this
|
83 |
*/
|
84 |
+
public function getTypeOf()
|
85 |
+
{
|
86 |
return self::$typeOf[get_class($this)];
|
87 |
}
|
88 |
|
90 |
* Returns the value of this
|
91 |
* @return mixed the value of this
|
92 |
*/
|
93 |
+
public function getValue()
|
94 |
+
{
|
95 |
throw new SassLiteralException('Child classes must override this method', SassScriptParser::$context->node);
|
96 |
}
|
97 |
|
98 |
+
public function getChildren()
|
99 |
+
{
|
100 |
return array();
|
101 |
}
|
102 |
|
104 |
* Adds a child object to this.
|
105 |
* @param sassLiteral the child object
|
106 |
*/
|
107 |
+
public function addChild($sassLiteral)
|
108 |
+
{
|
109 |
$this->children[] = $sassLiteral;
|
110 |
}
|
111 |
|
114 |
* @param sassLiteral value to add
|
115 |
* @return sassString the string values of this and other with no seperation
|
116 |
*/
|
117 |
+
public function op_plus($other)
|
118 |
+
{
|
119 |
return new SassString($this->toString().$other->toString());
|
120 |
}
|
121 |
|
124 |
* @param SassLiteral value to subtract
|
125 |
* @return sassString the string values of this and other seperated by '-'
|
126 |
*/
|
127 |
+
public function op_minus($other)
|
128 |
+
{
|
129 |
return new SassString($this->toString().'-'.$other->toString());
|
130 |
}
|
131 |
|
134 |
* @param SassLiteral value to multiply by
|
135 |
* @return sassString the string values of this and other seperated by '*'
|
136 |
*/
|
137 |
+
public function op_times($other)
|
138 |
+
{
|
139 |
return new SassString($this->toString().'*'.$other->toString());
|
140 |
}
|
141 |
|
144 |
* @param SassLiteral value to divide by
|
145 |
* @return sassString the string values of this and other seperated by '/'
|
146 |
*/
|
147 |
+
public function op_div($other)
|
148 |
+
{
|
149 |
return new SassString($this->toString().' / '.$other->toString());
|
150 |
}
|
151 |
|
155 |
* @return SassLiteral result
|
156 |
* @throws Exception if modulo not supported for the data type
|
157 |
*/
|
158 |
+
public function op_modulo($other)
|
159 |
+
{
|
160 |
throw new SassLiteralException(get_class($this) . ' does not support Modulus', SassScriptParser::$context->node);
|
161 |
}
|
162 |
|
166 |
* @return string result
|
167 |
* @throws Exception if bitwise AND not supported for the data type
|
168 |
*/
|
169 |
+
public function op_bw_and($other)
|
170 |
+
{
|
171 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise AND', SassScriptParser::$context->node);
|
172 |
}
|
173 |
|
177 |
* @return string result
|
178 |
* @throws Exception if bitwise OR not supported for the data type
|
179 |
*/
|
180 |
+
public function op_bw_or($other)
|
181 |
+
{
|
182 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise OR', SassScriptParser::$context->node);
|
183 |
}
|
184 |
|
188 |
* @return string result
|
189 |
* @throws Exception if bitwise XOR not supported for the data type
|
190 |
*/
|
191 |
+
public function op_bw_xor($other)
|
192 |
+
{
|
193 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise XOR', SassScriptParser::$context->node);
|
194 |
}
|
195 |
|
199 |
* @return string result
|
200 |
* @throws Exception if bitwise NOT not supported for the data type
|
201 |
*/
|
202 |
+
public function op_bw_not()
|
203 |
+
{
|
204 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise NOT', SassScriptParser::$context->node);
|
205 |
}
|
206 |
|
210 |
* @return string result
|
211 |
* @throws Exception if bitwise Shift Left not supported for the data type
|
212 |
*/
|
213 |
+
public function op_shiftl($other)
|
214 |
+
{
|
215 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise Shift Left', SassScriptParser::$context->node);
|
216 |
}
|
217 |
|
221 |
* @return string result
|
222 |
* @throws Exception if bitwise Shift Right not supported for the data type
|
223 |
*/
|
224 |
+
public function op_shiftr($other)
|
225 |
+
{
|
226 |
throw new SassLiteralException(get_class($this) . ' does not support Bitwise Shift Right', SassScriptParser::$context->node);
|
227 |
}
|
228 |
|
231 |
* @param sassLiteral the value to and with this
|
232 |
* @return SassLiteral other if this is boolean true, this if false
|
233 |
*/
|
234 |
+
public function op_and($other)
|
235 |
+
{
|
236 |
return ($this->toBoolean() ? $other : $this);
|
237 |
}
|
238 |
|
241 |
* @param sassLiteral the value to or with this
|
242 |
* @return SassLiteral this if this is boolean true, other if false
|
243 |
*/
|
244 |
+
public function op_or($other)
|
245 |
+
{
|
246 |
return ($this->toBoolean() ? $this : $other);
|
247 |
}
|
248 |
|
249 |
+
public function op_assign($other)
|
250 |
+
{
|
251 |
return $other;
|
252 |
}
|
253 |
|
257 |
* @return SassBoolean SassBoolean object with the value true if this or
|
258 |
* other, but not both, are true, false if not
|
259 |
*/
|
260 |
+
public function op_xor($other)
|
261 |
+
{
|
262 |
return new SassBoolean($this->toBoolean() xor $other->toBoolean());
|
263 |
}
|
264 |
|
267 |
* @return SassBoolean SassBoolean object with the value true if the
|
268 |
* boolean of this is false or false if it is true
|
269 |
*/
|
270 |
+
public function op_not()
|
271 |
+
{
|
272 |
return new SassBoolean(!$this->toBoolean());
|
273 |
}
|
274 |
|
278 |
* @return SassBoolean SassBoolean object with the value true if the values
|
279 |
* of this is greater than the value of other, false if it is not
|
280 |
*/
|
281 |
+
public function op_gt($other)
|
282 |
+
{
|
283 |
return new SassBoolean($this->value > $other->value);
|
284 |
}
|
285 |
|
289 |
* @return SassBoolean SassBoolean object with the value true if the values
|
290 |
* of this is greater than or equal to the value of other, false if it is not
|
291 |
*/
|
292 |
+
public function op_gte($other)
|
293 |
+
{
|
294 |
return new SassBoolean($this->value >= $other->value);
|
295 |
}
|
296 |
|
300 |
* @return SassBoolean SassBoolean object with the value true if the values
|
301 |
* of this is less than the value of other, false if it is not
|
302 |
*/
|
303 |
+
public function op_lt($other)
|
304 |
+
{
|
305 |
return new SassBoolean($this->value < $other->value);
|
306 |
}
|
307 |
|
311 |
* @return SassBoolean SassBoolean object with the value true if the values
|
312 |
* of this is less than or equal to the value of other, false if it is not
|
313 |
*/
|
314 |
+
public function op_lte($other)
|
315 |
+
{
|
316 |
return new SassBoolean($this->value <= $other->value);
|
317 |
}
|
318 |
|
322 |
* @return SassBoolean SassBoolean object with the value true if this and
|
323 |
* other are equal, false if they are not
|
324 |
*/
|
325 |
+
public function op_eq($other)
|
326 |
+
{
|
327 |
return new SassBoolean($this == $other);
|
328 |
}
|
329 |
|
333 |
* @return SassBoolean SassBoolean object with the value true if this and
|
334 |
* other are not equal, false if they are
|
335 |
*/
|
336 |
+
public function op_neq($other)
|
337 |
+
{
|
338 |
return new SassBoolean(!$this->op_eq($other)->toBoolean());
|
339 |
}
|
340 |
|
343 |
* @param sassLiteral the value to concatenate with a space to this
|
344 |
* @return sassString the string values of this and other seperated by " "
|
345 |
*/
|
346 |
+
public function op_concat($other)
|
347 |
+
{
|
348 |
return new SassString($this->toString().' '.$other->toString());
|
349 |
}
|
350 |
|
353 |
* @param sassLiteral the value to concatenate with a comma to this
|
354 |
* @return sassString the string values of this and other seperated by ","
|
355 |
*/
|
356 |
+
public function op_comma($other)
|
357 |
+
{
|
358 |
return new SassString($this->toString().', '.$other->toString());
|
359 |
}
|
360 |
|
364 |
* @param string expected type
|
365 |
* @throws SassScriptFunctionException if value is not the expected type
|
366 |
*/
|
367 |
+
public static function assertType($literal, $type)
|
368 |
+
{
|
369 |
if (!$literal instanceof $type) {
|
370 |
throw new SassScriptFunctionException(($literal instanceof SassLiteral ? get_class($literal) : 'literal') . ' must be a ' . $type, SassScriptParser::$context->node);
|
371 |
}
|
379 |
* @param string the units.
|
380 |
* @throws SassScriptFunctionException if value is not the expected type
|
381 |
*/
|
382 |
+
public static function assertInRange($literal, $min, $max, $units = '')
|
383 |
+
{
|
384 |
if ($literal->value < $min || $literal->value > $max) {
|
385 |
throw new SassScriptFunctionException($literal->typeOf . ' must be between ' . $min.$units . ' and ' . $max.$units . ' inclusive', SassScriptParser::$context->node);
|
386 |
}
|
392 |
*/
|
393 |
abstract public function toString();
|
394 |
|
395 |
+
public function render()
|
396 |
+
{
|
397 |
return $this->toString();
|
398 |
}
|
399 |
|
403 |
* @param string the subject string
|
404 |
* @return mixed match at the start of the string or false if no match
|
405 |
*/
|
406 |
+
public static function isa($subject)
|
407 |
+
{
|
408 |
throw new SassLiteralException('Child classes must override this method');
|
409 |
}
|
410 |
}
|
lib/phpsass/script/literals/SassLiteralExceptions.php
CHANGED
@@ -44,4 +44,4 @@ class SassNumberException extends SassLiteralException {}
|
|
44 |
* @package PHamlP
|
45 |
* @subpackage Sass.script.literals
|
46 |
*/
|
47 |
-
class SassStringException extends SassLiteralException {}
|
44 |
* @package PHamlP
|
45 |
* @subpackage Sass.script.literals
|
46 |
*/
|
47 |
+
class SassStringException extends SassLiteralException {}
|
lib/phpsass/script/literals/SassNumber.php
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassNumber class.
|
@@ -19,7 +19,8 @@ require_once('SassLiteral.php');
|
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.script.literals
|
21 |
*/
|
22 |
-
class SassNumber extends SassLiteral
|
|
|
23 |
/**
|
24 |
* Regx for matching and extracting numbers
|
25 |
*/
|
@@ -45,7 +46,7 @@ class SassNumber extends SassLiteral {
|
|
45 |
* pc: picas — 1 pica = 12 points
|
46 |
* pt: points — 1 point = 1/72nd of an inch
|
47 |
*/
|
48 |
-
static
|
49 |
'in' => 1,
|
50 |
'cm' => 2.54,
|
51 |
'mm' => 25.4,
|
@@ -53,7 +54,7 @@ class SassNumber extends SassLiteral {
|
|
53 |
'pt' => 72,
|
54 |
'px' => 96
|
55 |
);
|
56 |
-
static
|
57 |
'in', 'cm', 'mm', 'pc', 'pt', 'em', 'rem', 'ex', 'px', '%', 's', 'deg'
|
58 |
);
|
59 |
|
@@ -79,7 +80,8 @@ class SassNumber extends SassLiteral {
|
|
79 |
* @param string number
|
80 |
* @return SassNumber
|
81 |
*/
|
82 |
-
public function __construct($value)
|
|
|
83 |
preg_match(self::MATCH, $value, $matches);
|
84 |
|
85 |
$matches += array(null,null,'','');
|
@@ -109,20 +111,20 @@ class SassNumber extends SassLiteral {
|
|
109 |
* @return mixed SassNumber if other is a SassNumber or
|
110 |
* SassColour if it is a SassColour
|
111 |
*/
|
112 |
-
public function op_plus($other)
|
|
|
113 |
if ($other instanceof SassColour) {
|
114 |
return $other->op_plus($this);
|
115 |
-
}
|
116 |
-
else if ($other instanceOf SassString) {
|
117 |
$other = clone $other;
|
118 |
$other->value = $this->value . $other->value;
|
|
|
119 |
return $other;
|
120 |
-
}
|
121 |
-
elseif (!$other instanceof SassNumber) {
|
122 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
123 |
-
}
|
124 |
-
else {
|
125 |
$other = $this->convert($other);
|
|
|
126 |
return new SassNumber(($this->value + $other->value).$this->units);
|
127 |
}
|
128 |
}
|
@@ -131,7 +133,8 @@ class SassNumber extends SassLiteral {
|
|
131 |
* Unary + operator
|
132 |
* @return SassNumber the value of this number
|
133 |
*/
|
134 |
-
public function op_unary_plus()
|
|
|
135 |
return $this;
|
136 |
}
|
137 |
|
@@ -141,15 +144,15 @@ class SassNumber extends SassLiteral {
|
|
141 |
* @return mixed SassNumber if other is a SassNumber or
|
142 |
* SassColour if it is a SassColour
|
143 |
*/
|
144 |
-
public function op_minus($other)
|
|
|
145 |
if ($other instanceof SassColour) {
|
146 |
return $other->op_minus($this);
|
147 |
-
}
|
148 |
-
elseif (!$other instanceof SassNumber) {
|
149 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
150 |
-
}
|
151 |
-
else {
|
152 |
$other = $this->convert($other);
|
|
|
153 |
return new SassNumber(($this->value - $other->value) . $this->units);
|
154 |
}
|
155 |
}
|
@@ -158,11 +161,13 @@ class SassNumber extends SassLiteral {
|
|
158 |
* Unary - operator
|
159 |
* @return SassNumber the negative value of this number
|
160 |
*/
|
161 |
-
public function op_unary_minus()
|
|
|
162 |
return new SassNumber(($this->value * -1) . $this->units);
|
163 |
}
|
164 |
|
165 |
-
public function op_unary_concat()
|
|
|
166 |
return $this;
|
167 |
}
|
168 |
|
@@ -172,14 +177,13 @@ class SassNumber extends SassLiteral {
|
|
172 |
* @return mixed SassNumber if other is a SassNumber or
|
173 |
* SassColour if it is a SassColour
|
174 |
*/
|
175 |
-
public function op_times($other)
|
|
|
176 |
if ($other instanceof SassColour) {
|
177 |
return $other->op_times($this);
|
178 |
-
}
|
179 |
-
elseif (!$other instanceof SassNumber) {
|
180 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
181 |
-
}
|
182 |
-
else {
|
183 |
return new SassNumber(($this->value * $other->value).$this->unitString(
|
184 |
array_merge($this->numeratorUnits, $other->numeratorUnits),
|
185 |
array_merge($this->denominatorUnits, $other->denominatorUnits)
|
@@ -193,20 +197,18 @@ class SassNumber extends SassLiteral {
|
|
193 |
* @return mixed SassNumber if other is a SassNumber or
|
194 |
* SassColour if it is a SassColour
|
195 |
*/
|
196 |
-
public function op_div($other)
|
|
|
197 |
if ($other instanceof SassColour) {
|
198 |
return $other->op_div($this);
|
199 |
-
}
|
200 |
-
elseif (!$other instanceof SassNumber) {
|
201 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
202 |
-
}
|
203 |
-
elseif ($this->inExpression || $other->inExpression) {
|
204 |
return new SassNumber(($this->value / $other->value).$this->unitString(
|
205 |
array_merge($this->numeratorUnits, $other->denominatorUnits),
|
206 |
array_merge($this->denominatorUnits, $other->numeratorUnits)
|
207 |
));
|
208 |
-
}
|
209 |
-
else {
|
210 |
return new SassNumber(($this->value / $other->value).$this->unitString(
|
211 |
array_merge($this->numeratorUnits, $other->denominatorUnits),
|
212 |
$this->denominatorUnits
|
@@ -219,14 +221,14 @@ class SassNumber extends SassLiteral {
|
|
219 |
* @return SassBoolean SassBoolean object with the value true if the values
|
220 |
* of this and other are equal, false if they are not
|
221 |
*/
|
222 |
-
public function op_eq($other)
|
|
|
223 |
if (!$other instanceof SassNumber) {
|
224 |
return new SassBoolean(false);
|
225 |
}
|
226 |
try {
|
227 |
return new SassBoolean($this->value == $this->convert($other)->value);
|
228 |
-
}
|
229 |
-
catch (Exception $e) {
|
230 |
return new SassBoolean(false);
|
231 |
}
|
232 |
}
|
@@ -237,10 +239,12 @@ class SassNumber extends SassLiteral {
|
|
237 |
* @return SassBoolean SassBoolean object with the value true if the values
|
238 |
* of this is greater than the value of other, false if it is not
|
239 |
*/
|
240 |
-
public function op_gt($other)
|
|
|
241 |
if (!$other instanceof SassNumber) {
|
242 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
243 |
}
|
|
|
244 |
return new SassBoolean($this->value > $this->convert($other)->value);
|
245 |
}
|
246 |
|
@@ -250,10 +254,12 @@ class SassNumber extends SassLiteral {
|
|
250 |
* @return SassBoolean SassBoolean object with the value true if the values
|
251 |
* of this is greater than or equal to the value of other, false if it is not
|
252 |
*/
|
253 |
-
public function op_gte($other)
|
|
|
254 |
if (!$other instanceof SassNumber) {
|
255 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
256 |
}
|
|
|
257 |
return new SassBoolean($this->value >= $this->convert($other)->value);
|
258 |
}
|
259 |
|
@@ -263,10 +269,12 @@ class SassNumber extends SassLiteral {
|
|
263 |
* @return SassBoolean SassBoolean object with the value true if the values
|
264 |
* of this is less than the value of other, false if it is not
|
265 |
*/
|
266 |
-
public function op_lt($other)
|
|
|
267 |
if (!$other instanceof SassNumber) {
|
268 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
269 |
}
|
|
|
270 |
return new SassBoolean($this->value < $this->convert($other)->value);
|
271 |
}
|
272 |
|
@@ -276,10 +284,12 @@ class SassNumber extends SassLiteral {
|
|
276 |
* @return SassBoolean SassBoolean object with the value true if the values
|
277 |
* of this is less than or equal to the value of other, false if it is not
|
278 |
*/
|
279 |
-
public function op_lte($other)
|
|
|
280 |
if (!$other instanceof SassNumber) {
|
281 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
282 |
}
|
|
|
283 |
return new SassBoolean($this->value <= $this->convert($other)->value);
|
284 |
}
|
285 |
|
@@ -289,11 +299,13 @@ class SassNumber extends SassLiteral {
|
|
289 |
* @return mixed SassNumber if other is a SassNumber or
|
290 |
* SassColour if it is a SassColour
|
291 |
*/
|
292 |
-
public function op_modulo($other)
|
|
|
293 |
if (!$other instanceof SassNumber || !$other->isUnitless()) {
|
294 |
throw new SassNumberException('Number must be a unitless number', SassScriptParser::$context->node);
|
295 |
}
|
296 |
$this->value %= $this->convert($other)->value;
|
|
|
297 |
return $this;
|
298 |
}
|
299 |
|
@@ -305,14 +317,15 @@ class SassNumber extends SassLiteral {
|
|
305 |
* @return SassNumber the other number with its value and units coerced if neccessary
|
306 |
* @throws SassNumberException if the units are incompatible
|
307 |
*/
|
308 |
-
private function convert($other)
|
|
|
309 |
if ($this->isUnitless()) {
|
310 |
$this->numeratorUnits = $other->numeratorUnits;
|
311 |
$this->denominatorUnits = $other->denominatorUnits;
|
312 |
-
}
|
313 |
-
else {
|
314 |
$other = $other->coerce($this->numeratorUnits, $this->denominatorUnits);
|
315 |
}
|
|
|
316 |
return $other;
|
317 |
}
|
318 |
|
@@ -326,7 +339,8 @@ class SassNumber extends SassLiteral {
|
|
326 |
* @param array $denominatorUnits
|
327 |
* @return SassNumber
|
328 |
*/
|
329 |
-
public function coerce($numeratorUnits, $denominatorUnits)
|
|
|
330 |
return new SassNumber(($this->isUnitless() ?
|
331 |
$this->value : $this->value *
|
332 |
$this->coercionFactor($this->numeratorUnits, $numeratorUnits) /
|
@@ -340,7 +354,8 @@ class SassNumber extends SassLiteral {
|
|
340 |
* @param array units being converted to
|
341 |
* @return float the coercion factor to apply
|
342 |
*/
|
343 |
-
private function coercionFactor($fromUnits, $toUnits)
|
|
|
344 |
$units = $this->removeCommonUnits($fromUnits, $toUnits);
|
345 |
$fromUnits = $units[0];
|
346 |
$toUnits = $units[1];
|
@@ -357,11 +372,11 @@ class SassNumber extends SassLiteral {
|
|
357 |
foreach ($fromUnits as $i=>$from) {
|
358 |
if (array_key_exists($i, $toUnits) && array_key_exists($toUnits[$i], self::$unitConversion)) {
|
359 |
$coercionFactor *= self::$unitConversion[$toUnits[$i]] / self::$unitConversion[$from];
|
360 |
-
}
|
361 |
-
else {
|
362 |
throw new SassNumberException("Incompatible units: '" . join(' * ', $fromUnits) . "' and '" . join(' * ', $toUnits) . "'", SassScriptParser::$context->node);
|
363 |
}
|
364 |
}
|
|
|
365 |
return $coercionFactor;
|
366 |
}
|
367 |
|
@@ -370,13 +385,15 @@ class SassNumber extends SassLiteral {
|
|
370 |
* @param array units to test
|
371 |
* @return boolean true if all units can be converted, false if not
|
372 |
*/
|
373 |
-
private function areConvertable($units)
|
|
|
374 |
$convertable = array_keys(self::$unitConversion);
|
375 |
foreach ($units as $unit) {
|
376 |
if (!in_array($unit, $convertable)) {
|
377 |
return false;
|
378 |
}
|
379 |
}
|
|
|
380 |
return true;
|
381 |
}
|
382 |
|
@@ -388,18 +405,19 @@ class SassNumber extends SassLiteral {
|
|
388 |
* @param array second set of units
|
389 |
* @return array both sets of units with common units removed
|
390 |
*/
|
391 |
-
private function removeCommonUnits($u1, $u2)
|
|
|
392 |
$_u1 = array();
|
393 |
while (!empty($u1)) {
|
394 |
$u = array_shift($u1);
|
395 |
$i = array_search($u, $u2);
|
396 |
if ($i !== false) {
|
397 |
unset($u2[$i]);
|
398 |
-
}
|
399 |
-
else {
|
400 |
$_u1[] = $u;
|
401 |
}
|
402 |
}
|
|
|
403 |
return (array($_u1, $u2));
|
404 |
}
|
405 |
|
@@ -407,7 +425,8 @@ class SassNumber extends SassLiteral {
|
|
407 |
* Returns a value indicating if this number is unitless.
|
408 |
* @return boolean true if this number is unitless, false if not
|
409 |
*/
|
410 |
-
public function isUnitless()
|
|
|
411 |
return empty($this->numeratorUnits) && empty($this->denominatorUnits);
|
412 |
}
|
413 |
|
@@ -415,7 +434,8 @@ class SassNumber extends SassLiteral {
|
|
415 |
* Returns a value indicating if this number has units.
|
416 |
* @return boolean true if this number has, false if not
|
417 |
*/
|
418 |
-
public function hasUnits()
|
|
|
419 |
return !$this->isUnitless();
|
420 |
}
|
421 |
|
@@ -425,7 +445,8 @@ class SassNumber extends SassLiteral {
|
|
425 |
* @return boolean true if this number has units that can be represented in
|
426 |
* CSS, false if not
|
427 |
*/
|
428 |
-
public function hasLegalUnits()
|
|
|
429 |
return (empty($this->numeratorUnits) || count($this->numeratorUnits) === 1) && empty($this->denominatorUnits);
|
430 |
}
|
431 |
|
@@ -433,7 +454,8 @@ class SassNumber extends SassLiteral {
|
|
433 |
* Returns a string representation of the units.
|
434 |
* @return string the units
|
435 |
*/
|
436 |
-
public function unitString($numeratorUnits, $denominatorUnits)
|
|
|
437 |
foreach ($numeratorUnits as $i => $unit) {
|
438 |
if (!in_array($unit, self::$validUnits)) {
|
439 |
unset($numeratorUnits[$i]);
|
@@ -444,6 +466,7 @@ class SassNumber extends SassLiteral {
|
|
444 |
unset($denominatorUnits[$i]);
|
445 |
}
|
446 |
}
|
|
|
447 |
return join(' * ', $numeratorUnits) . (!empty($denominatorUnits) ? ' / ' . join(' * ', $denominatorUnits) : '');
|
448 |
}
|
449 |
|
@@ -451,7 +474,8 @@ class SassNumber extends SassLiteral {
|
|
451 |
* Returns the units of this number.
|
452 |
* @return string the units of this number
|
453 |
*/
|
454 |
-
public function getUnits()
|
|
|
455 |
return $this->unitString($this->numeratorUnits, $this->denominatorUnits);
|
456 |
}
|
457 |
|
@@ -459,7 +483,8 @@ class SassNumber extends SassLiteral {
|
|
459 |
* Returns the denominator units of this number.
|
460 |
* @return string the denominator units of this number
|
461 |
*/
|
462 |
-
public function getDenominatorUnits()
|
|
|
463 |
return join(' * ', $this->denominatorUnits);
|
464 |
}
|
465 |
|
@@ -467,7 +492,8 @@ class SassNumber extends SassLiteral {
|
|
467 |
* Returns the numerator units of this number.
|
468 |
* @return string the numerator units of this number
|
469 |
*/
|
470 |
-
public function getNumeratorUnits()
|
|
|
471 |
return join(' * ', $this->numeratorUnits);
|
472 |
}
|
473 |
|
@@ -475,12 +501,13 @@ class SassNumber extends SassLiteral {
|
|
475 |
* Returns a value indicating if this number can be compared to other.
|
476 |
* @return boolean true if this number can be compared to other, false if not
|
477 |
*/
|
478 |
-
public function isComparableTo($other)
|
|
|
479 |
try {
|
480 |
$this->op_plus($other);
|
|
|
481 |
return true;
|
482 |
-
}
|
483 |
-
catch (Exception $e) {
|
484 |
return false;
|
485 |
}
|
486 |
}
|
@@ -489,7 +516,8 @@ class SassNumber extends SassLiteral {
|
|
489 |
* Returns a value indicating if this number is an integer.
|
490 |
* @return boolean true if this number is an integer, false if not
|
491 |
*/
|
492 |
-
public function isInt()
|
|
|
493 |
return $this->value % 1 === 0;
|
494 |
}
|
495 |
|
@@ -497,7 +525,8 @@ class SassNumber extends SassLiteral {
|
|
497 |
* Returns the value of this number.
|
498 |
* @return float the value of this number.
|
499 |
*/
|
500 |
-
public function getValue()
|
|
|
501 |
return $this->value;
|
502 |
}
|
503 |
|
@@ -506,10 +535,12 @@ class SassNumber extends SassLiteral {
|
|
506 |
* @return integer the integer value.
|
507 |
* @throws SassNumberException if the number is not an integer
|
508 |
*/
|
509 |
-
public function toInt()
|
510 |
-
|
|
|
511 |
throw new SassNumberException('Not an integer: ' . $this->value, SassScriptParser::$context->node);
|
512 |
}
|
|
|
513 |
return intval($this->value);
|
514 |
}
|
515 |
|
@@ -519,10 +550,12 @@ class SassNumber extends SassLiteral {
|
|
519 |
* otherwise the result is rounded to the specified precision.
|
520 |
* @return string number as a string with it's units if any
|
521 |
*/
|
522 |
-
public function toString()
|
|
|
523 |
if (!isset($this->units)) {
|
524 |
$this->units = $this->getUnits();
|
525 |
}
|
|
|
526 |
return ($this->units == 'px' ? floor($this->value) : str_replace(',','.',round($this->value, self::PRECISION))) . $this->units;
|
527 |
}
|
528 |
|
@@ -532,7 +565,8 @@ class SassNumber extends SassLiteral {
|
|
532 |
* @param string the subject string
|
533 |
* @return mixed match at the start of the string or false if no match
|
534 |
*/
|
535 |
-
public static function isa($subject)
|
|
|
536 |
return (preg_match(self::MATCH, $subject, $matches) ? $matches[0] : false);
|
537 |
}
|
538 |
|
@@ -540,7 +574,8 @@ class SassNumber extends SassLiteral {
|
|
540 |
* Returns the number of values of SassNumber
|
541 |
* @return int
|
542 |
*/
|
543 |
-
public function length()
|
|
|
544 |
return count($this->value);
|
545 |
}
|
546 |
|
@@ -549,10 +584,12 @@ class SassNumber extends SassLiteral {
|
|
549 |
* @param int - the nth position of value
|
550 |
* @return SassBoolean|SassNumber
|
551 |
*/
|
552 |
-
public function nth($i)
|
|
|
553 |
if ($i == 1 && isset($this->value)) {
|
554 |
return new SassNumber($this->value);
|
555 |
}
|
|
|
556 |
return new SassBoolean(false);
|
557 |
}
|
558 |
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassLiteral.php';
|
13 |
|
14 |
/**
|
15 |
* SassNumber class.
|
19 |
* @package PHamlP
|
20 |
* @subpackage Sass.script.literals
|
21 |
*/
|
22 |
+
class SassNumber extends SassLiteral
|
23 |
+
{
|
24 |
/**
|
25 |
* Regx for matching and extracting numbers
|
26 |
*/
|
46 |
* pc: picas — 1 pica = 12 points
|
47 |
* pt: points — 1 point = 1/72nd of an inch
|
48 |
*/
|
49 |
+
private static $unitConversion = array(
|
50 |
'in' => 1,
|
51 |
'cm' => 2.54,
|
52 |
'mm' => 25.4,
|
54 |
'pt' => 72,
|
55 |
'px' => 96
|
56 |
);
|
57 |
+
private static $validUnits = array(
|
58 |
'in', 'cm', 'mm', 'pc', 'pt', 'em', 'rem', 'ex', 'px', '%', 's', 'deg'
|
59 |
);
|
60 |
|
80 |
* @param string number
|
81 |
* @return SassNumber
|
82 |
*/
|
83 |
+
public function __construct($value)
|
84 |
+
{
|
85 |
preg_match(self::MATCH, $value, $matches);
|
86 |
|
87 |
$matches += array(null,null,'','');
|
111 |
* @return mixed SassNumber if other is a SassNumber or
|
112 |
* SassColour if it is a SassColour
|
113 |
*/
|
114 |
+
public function op_plus($other)
|
115 |
+
{
|
116 |
if ($other instanceof SassColour) {
|
117 |
return $other->op_plus($this);
|
118 |
+
} elseif ($other instanceOf SassString) {
|
|
|
119 |
$other = clone $other;
|
120 |
$other->value = $this->value . $other->value;
|
121 |
+
|
122 |
return $other;
|
123 |
+
} elseif (!$other instanceof SassNumber) {
|
|
|
124 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
125 |
+
} else {
|
|
|
126 |
$other = $this->convert($other);
|
127 |
+
|
128 |
return new SassNumber(($this->value + $other->value).$this->units);
|
129 |
}
|
130 |
}
|
133 |
* Unary + operator
|
134 |
* @return SassNumber the value of this number
|
135 |
*/
|
136 |
+
public function op_unary_plus()
|
137 |
+
{
|
138 |
return $this;
|
139 |
}
|
140 |
|
144 |
* @return mixed SassNumber if other is a SassNumber or
|
145 |
* SassColour if it is a SassColour
|
146 |
*/
|
147 |
+
public function op_minus($other)
|
148 |
+
{
|
149 |
if ($other instanceof SassColour) {
|
150 |
return $other->op_minus($this);
|
151 |
+
} elseif (!$other instanceof SassNumber) {
|
|
|
152 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
153 |
+
} else {
|
|
|
154 |
$other = $this->convert($other);
|
155 |
+
|
156 |
return new SassNumber(($this->value - $other->value) . $this->units);
|
157 |
}
|
158 |
}
|
161 |
* Unary - operator
|
162 |
* @return SassNumber the negative value of this number
|
163 |
*/
|
164 |
+
public function op_unary_minus()
|
165 |
+
{
|
166 |
return new SassNumber(($this->value * -1) . $this->units);
|
167 |
}
|
168 |
|
169 |
+
public function op_unary_concat()
|
170 |
+
{
|
171 |
return $this;
|
172 |
}
|
173 |
|
177 |
* @return mixed SassNumber if other is a SassNumber or
|
178 |
* SassColour if it is a SassColour
|
179 |
*/
|
180 |
+
public function op_times($other)
|
181 |
+
{
|
182 |
if ($other instanceof SassColour) {
|
183 |
return $other->op_times($this);
|
184 |
+
} elseif (!$other instanceof SassNumber) {
|
|
|
185 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
186 |
+
} else {
|
|
|
187 |
return new SassNumber(($this->value * $other->value).$this->unitString(
|
188 |
array_merge($this->numeratorUnits, $other->numeratorUnits),
|
189 |
array_merge($this->denominatorUnits, $other->denominatorUnits)
|
197 |
* @return mixed SassNumber if other is a SassNumber or
|
198 |
* SassColour if it is a SassColour
|
199 |
*/
|
200 |
+
public function op_div($other)
|
201 |
+
{
|
202 |
if ($other instanceof SassColour) {
|
203 |
return $other->op_div($this);
|
204 |
+
} elseif (!$other instanceof SassNumber) {
|
|
|
205 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
206 |
+
} elseif ($this->inExpression || $other->inExpression) {
|
|
|
207 |
return new SassNumber(($this->value / $other->value).$this->unitString(
|
208 |
array_merge($this->numeratorUnits, $other->denominatorUnits),
|
209 |
array_merge($this->denominatorUnits, $other->numeratorUnits)
|
210 |
));
|
211 |
+
} else {
|
|
|
212 |
return new SassNumber(($this->value / $other->value).$this->unitString(
|
213 |
array_merge($this->numeratorUnits, $other->denominatorUnits),
|
214 |
$this->denominatorUnits
|
221 |
* @return SassBoolean SassBoolean object with the value true if the values
|
222 |
* of this and other are equal, false if they are not
|
223 |
*/
|
224 |
+
public function op_eq($other)
|
225 |
+
{
|
226 |
if (!$other instanceof SassNumber) {
|
227 |
return new SassBoolean(false);
|
228 |
}
|
229 |
try {
|
230 |
return new SassBoolean($this->value == $this->convert($other)->value);
|
231 |
+
} catch (Exception $e) {
|
|
|
232 |
return new SassBoolean(false);
|
233 |
}
|
234 |
}
|
239 |
* @return SassBoolean SassBoolean object with the value true if the values
|
240 |
* of this is greater than the value of other, false if it is not
|
241 |
*/
|
242 |
+
public function op_gt($other)
|
243 |
+
{
|
244 |
if (!$other instanceof SassNumber) {
|
245 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
246 |
}
|
247 |
+
|
248 |
return new SassBoolean($this->value > $this->convert($other)->value);
|
249 |
}
|
250 |
|
254 |
* @return SassBoolean SassBoolean object with the value true if the values
|
255 |
* of this is greater than or equal to the value of other, false if it is not
|
256 |
*/
|
257 |
+
public function op_gte($other)
|
258 |
+
{
|
259 |
if (!$other instanceof SassNumber) {
|
260 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
261 |
}
|
262 |
+
|
263 |
return new SassBoolean($this->value >= $this->convert($other)->value);
|
264 |
}
|
265 |
|
269 |
* @return SassBoolean SassBoolean object with the value true if the values
|
270 |
* of this is less than the value of other, false if it is not
|
271 |
*/
|
272 |
+
public function op_lt($other)
|
273 |
+
{
|
274 |
if (!$other instanceof SassNumber) {
|
275 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
276 |
}
|
277 |
+
|
278 |
return new SassBoolean($this->value < $this->convert($other)->value);
|
279 |
}
|
280 |
|
284 |
* @return SassBoolean SassBoolean object with the value true if the values
|
285 |
* of this is less than or equal to the value of other, false if it is not
|
286 |
*/
|
287 |
+
public function op_lte($other)
|
288 |
+
{
|
289 |
if (!$other instanceof SassNumber) {
|
290 |
throw new SassNumberException('Number must be a number', SassScriptParser::$context->node);
|
291 |
}
|
292 |
+
|
293 |
return new SassBoolean($this->value <= $this->convert($other)->value);
|
294 |
}
|
295 |
|
299 |
* @return mixed SassNumber if other is a SassNumber or
|
300 |
* SassColour if it is a SassColour
|
301 |
*/
|
302 |
+
public function op_modulo($other)
|
303 |
+
{
|
304 |
if (!$other instanceof SassNumber || !$other->isUnitless()) {
|
305 |
throw new SassNumberException('Number must be a unitless number', SassScriptParser::$context->node);
|
306 |
}
|
307 |
$this->value %= $this->convert($other)->value;
|
308 |
+
|
309 |
return $this;
|
310 |
}
|
311 |
|
317 |
* @return SassNumber the other number with its value and units coerced if neccessary
|
318 |
* @throws SassNumberException if the units are incompatible
|
319 |
*/
|
320 |
+
private function convert($other)
|
321 |
+
{
|
322 |
if ($this->isUnitless()) {
|
323 |
$this->numeratorUnits = $other->numeratorUnits;
|
324 |
$this->denominatorUnits = $other->denominatorUnits;
|
325 |
+
} else {
|
|
|
326 |
$other = $other->coerce($this->numeratorUnits, $this->denominatorUnits);
|
327 |
}
|
328 |
+
|
329 |
return $other;
|
330 |
}
|
331 |
|
339 |
* @param array $denominatorUnits
|
340 |
* @return SassNumber
|
341 |
*/
|
342 |
+
public function coerce($numeratorUnits, $denominatorUnits)
|
343 |
+
{
|
344 |
return new SassNumber(($this->isUnitless() ?
|
345 |
$this->value : $this->value *
|
346 |
$this->coercionFactor($this->numeratorUnits, $numeratorUnits) /
|
354 |
* @param array units being converted to
|
355 |
* @return float the coercion factor to apply
|
356 |
*/
|
357 |
+
private function coercionFactor($fromUnits, $toUnits)
|
358 |
+
{
|
359 |
$units = $this->removeCommonUnits($fromUnits, $toUnits);
|
360 |
$fromUnits = $units[0];
|
361 |
$toUnits = $units[1];
|
372 |
foreach ($fromUnits as $i=>$from) {
|
373 |
if (array_key_exists($i, $toUnits) && array_key_exists($toUnits[$i], self::$unitConversion)) {
|
374 |
$coercionFactor *= self::$unitConversion[$toUnits[$i]] / self::$unitConversion[$from];
|
375 |
+
} else {
|
|
|
376 |
throw new SassNumberException("Incompatible units: '" . join(' * ', $fromUnits) . "' and '" . join(' * ', $toUnits) . "'", SassScriptParser::$context->node);
|
377 |
}
|
378 |
}
|
379 |
+
|
380 |
return $coercionFactor;
|
381 |
}
|
382 |
|
385 |
* @param array units to test
|
386 |
* @return boolean true if all units can be converted, false if not
|
387 |
*/
|
388 |
+
private function areConvertable($units)
|
389 |
+
{
|
390 |
$convertable = array_keys(self::$unitConversion);
|
391 |
foreach ($units as $unit) {
|
392 |
if (!in_array($unit, $convertable)) {
|
393 |
return false;
|
394 |
}
|
395 |
}
|
396 |
+
|
397 |
return true;
|
398 |
}
|
399 |
|
405 |
* @param array second set of units
|
406 |
* @return array both sets of units with common units removed
|
407 |
*/
|
408 |
+
private function removeCommonUnits($u1, $u2)
|
409 |
+
{
|
410 |
$_u1 = array();
|
411 |
while (!empty($u1)) {
|
412 |
$u = array_shift($u1);
|
413 |
$i = array_search($u, $u2);
|
414 |
if ($i !== false) {
|
415 |
unset($u2[$i]);
|
416 |
+
} else {
|
|
|
417 |
$_u1[] = $u;
|
418 |
}
|
419 |
}
|
420 |
+
|
421 |
return (array($_u1, $u2));
|
422 |
}
|
423 |
|
425 |
* Returns a value indicating if this number is unitless.
|
426 |
* @return boolean true if this number is unitless, false if not
|
427 |
*/
|
428 |
+
public function isUnitless()
|
429 |
+
{
|
430 |
return empty($this->numeratorUnits) && empty($this->denominatorUnits);
|
431 |
}
|
432 |
|
434 |
* Returns a value indicating if this number has units.
|
435 |
* @return boolean true if this number has, false if not
|
436 |
*/
|
437 |
+
public function hasUnits()
|
438 |
+
{
|
439 |
return !$this->isUnitless();
|
440 |
}
|
441 |
|
445 |
* @return boolean true if this number has units that can be represented in
|
446 |
* CSS, false if not
|
447 |
*/
|
448 |
+
public function hasLegalUnits()
|
449 |
+
{
|
450 |
return (empty($this->numeratorUnits) || count($this->numeratorUnits) === 1) && empty($this->denominatorUnits);
|
451 |
}
|
452 |
|
454 |
* Returns a string representation of the units.
|
455 |
* @return string the units
|
456 |
*/
|
457 |
+
public function unitString($numeratorUnits, $denominatorUnits)
|
458 |
+
{
|
459 |
foreach ($numeratorUnits as $i => $unit) {
|
460 |
if (!in_array($unit, self::$validUnits)) {
|
461 |
unset($numeratorUnits[$i]);
|
466 |
unset($denominatorUnits[$i]);
|
467 |
}
|
468 |
}
|
469 |
+
|
470 |
return join(' * ', $numeratorUnits) . (!empty($denominatorUnits) ? ' / ' . join(' * ', $denominatorUnits) : '');
|
471 |
}
|
472 |
|
474 |
* Returns the units of this number.
|
475 |
* @return string the units of this number
|
476 |
*/
|
477 |
+
public function getUnits()
|
478 |
+
{
|
479 |
return $this->unitString($this->numeratorUnits, $this->denominatorUnits);
|
480 |
}
|
481 |
|
483 |
* Returns the denominator units of this number.
|
484 |
* @return string the denominator units of this number
|
485 |
*/
|
486 |
+
public function getDenominatorUnits()
|
487 |
+
{
|
488 |
return join(' * ', $this->denominatorUnits);
|
489 |
}
|
490 |
|
492 |
* Returns the numerator units of this number.
|
493 |
* @return string the numerator units of this number
|
494 |
*/
|
495 |
+
public function getNumeratorUnits()
|
496 |
+
{
|
497 |
return join(' * ', $this->numeratorUnits);
|
498 |
}
|
499 |
|
501 |
* Returns a value indicating if this number can be compared to other.
|
502 |
* @return boolean true if this number can be compared to other, false if not
|
503 |
*/
|
504 |
+
public function isComparableTo($other)
|
505 |
+
{
|
506 |
try {
|
507 |
$this->op_plus($other);
|
508 |
+
|
509 |
return true;
|
510 |
+
} catch (Exception $e) {
|
|
|
511 |
return false;
|
512 |
}
|
513 |
}
|
516 |
* Returns a value indicating if this number is an integer.
|
517 |
* @return boolean true if this number is an integer, false if not
|
518 |
*/
|
519 |
+
public function isInt()
|
520 |
+
{
|
521 |
return $this->value % 1 === 0;
|
522 |
}
|
523 |
|
525 |
* Returns the value of this number.
|
526 |
* @return float the value of this number.
|
527 |
*/
|
528 |
+
public function getValue()
|
529 |
+
{
|
530 |
return $this->value;
|
531 |
}
|
532 |
|
535 |
* @return integer the integer value.
|
536 |
* @throws SassNumberException if the number is not an integer
|
537 |
*/
|
538 |
+
public function toInt()
|
539 |
+
{
|
540 |
+
if (!$this->isInt()) {
|
541 |
throw new SassNumberException('Not an integer: ' . $this->value, SassScriptParser::$context->node);
|
542 |
}
|
543 |
+
|
544 |
return intval($this->value);
|
545 |
}
|
546 |
|
550 |
* otherwise the result is rounded to the specified precision.
|
551 |
* @return string number as a string with it's units if any
|
552 |
*/
|
553 |
+
public function toString()
|
554 |
+
{
|
555 |
if (!isset($this->units)) {
|
556 |
$this->units = $this->getUnits();
|
557 |
}
|
558 |
+
|
559 |
return ($this->units == 'px' ? floor($this->value) : str_replace(',','.',round($this->value, self::PRECISION))) . $this->units;
|
560 |
}
|
561 |
|
565 |
* @param string the subject string
|
566 |
* @return mixed match at the start of the string or false if no match
|
567 |
*/
|
568 |
+
public static function isa($subject)
|
569 |
+
{
|
570 |
return (preg_match(self::MATCH, $subject, $matches) ? $matches[0] : false);
|
571 |
}
|
572 |
|
574 |
* Returns the number of values of SassNumber
|
575 |
* @return int
|
576 |
*/
|
577 |
+
public function length()
|
578 |
+
{
|
579 |
return count($this->value);
|
580 |
}
|
581 |
|
584 |
* @param int - the nth position of value
|
585 |
* @return SassBoolean|SassNumber
|
586 |
*/
|
587 |
+
public function nth($i)
|
588 |
+
{
|
589 |
if ($i == 1 && isset($this->value)) {
|
590 |
return new SassNumber($this->value);
|
591 |
}
|
592 |
+
|
593 |
return new SassBoolean(false);
|
594 |
}
|
595 |
|
lib/phpsass/script/literals/SassString.php
CHANGED
@@ -9,7 +9,7 @@
|
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
|
14 |
/**
|
15 |
* SassString class.
|
@@ -17,7 +17,8 @@ require_once('SassLiteral.php');
|
|
17 |
* @package PHamlP
|
18 |
* @subpackage Sass.script.literals
|
19 |
*/
|
20 |
-
class SassString extends SassLiteral
|
|
|
21 |
const MATCH = '/^(((["\'])(.*?)(\3))|(-[a-zA-Z-]+[^\s]*?))/i';
|
22 |
const _MATCH = '/^(["\'])(.*?)(\1)?$/'; // Used to match strings such as "Times New Roman",serif
|
23 |
const VALUE = 2;
|
@@ -33,13 +34,13 @@ class SassString extends SassLiteral {
|
|
33 |
* @param string string
|
34 |
* @return SassString
|
35 |
*/
|
36 |
-
public function __construct($value)
|
|
|
37 |
preg_match(self::_MATCH, $value, $matches);
|
38 |
if ((isset($matches[self::QUOTE]))) {
|
39 |
$this->quote = $matches[self::QUOTE];
|
40 |
$this->value = $matches[self::VALUE];
|
41 |
-
}
|
42 |
-
else {
|
43 |
$this->quote = '';
|
44 |
$this->value = $value;
|
45 |
}
|
@@ -52,8 +53,10 @@ class SassString extends SassLiteral {
|
|
52 |
* @param sassString string to add to this
|
53 |
* @return sassString the string result
|
54 |
*/
|
55 |
-
public function op_plus($other)
|
|
|
56 |
$this->value .= $other->value;
|
|
|
57 |
return $this;
|
58 |
}
|
59 |
|
@@ -63,29 +66,34 @@ class SassString extends SassLiteral {
|
|
63 |
* @param sassNumber the number of times to repeat this
|
64 |
* @return sassString the string result
|
65 |
*/
|
66 |
-
public function op_times($other)
|
|
|
67 |
if (!($other instanceof SassNumber) || !$other->isUnitless()) {
|
68 |
throw new SassStringException('Value must be a unitless number', SassScriptParser::$context->node);
|
69 |
}
|
70 |
$this->value = str_repeat($this->value, $other->value);
|
|
|
71 |
return $this;
|
72 |
}
|
73 |
|
74 |
/**
|
75 |
* Equals - works better
|
76 |
*/
|
77 |
-
public function op_eq($other)
|
|
|
78 |
return new SassBoolean($this->value == $other->value || $this->toString() == $other->toString());
|
79 |
}
|
80 |
|
81 |
/**
|
82 |
* Evaluates the value as a boolean.
|
83 |
*/
|
84 |
-
public function toBoolean()
|
|
|
85 |
$value = strtolower(trim($this->value, ' "\''));
|
86 |
if (!$value || in_array($value, array('false', 'null', '0'))) {
|
87 |
return FALSE;
|
88 |
}
|
|
|
89 |
return TRUE;
|
90 |
}
|
91 |
|
@@ -93,7 +101,8 @@ class SassString extends SassLiteral {
|
|
93 |
* Returns the value of this string.
|
94 |
* @return string the string
|
95 |
*/
|
96 |
-
public function getValue()
|
|
|
97 |
return $this->value;
|
98 |
}
|
99 |
|
@@ -101,24 +110,28 @@ class SassString extends SassLiteral {
|
|
101 |
* Returns a string representation of the value.
|
102 |
* @return string string representation of the value.
|
103 |
*/
|
104 |
-
public function toString()
|
|
|
105 |
if ($this->quote) {
|
106 |
$value = $this->quote . $this->value . $this->quote;
|
107 |
-
}
|
108 |
-
else {
|
109 |
$value = strlen(trim($this->value)) ? trim($this->value) : $this->value;
|
110 |
}
|
|
|
111 |
return $value;
|
112 |
}
|
113 |
|
114 |
-
public function toVar()
|
|
|
115 |
return SassScriptParser::$context->getVariable($this->value);
|
116 |
}
|
117 |
|
118 |
-
public function getTypeOf()
|
|
|
119 |
if (SassList::isa($this->toString())) {
|
120 |
return 'list';
|
121 |
}
|
|
|
122 |
return 'string';
|
123 |
}
|
124 |
|
@@ -128,7 +141,8 @@ class SassString extends SassLiteral {
|
|
128 |
* @param string the subject string
|
129 |
* @return mixed match at the start of the string or false if no match
|
130 |
*/
|
131 |
-
public static function isa($subject)
|
|
|
132 |
return (preg_match(self::MATCH, $subject, $matches) ? $matches[0] : false);
|
133 |
}
|
134 |
}
|
9 |
* @subpackage Sass.script.literals
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassLiteral.php';
|
13 |
|
14 |
/**
|
15 |
* SassString class.
|
17 |
* @package PHamlP
|
18 |
* @subpackage Sass.script.literals
|
19 |
*/
|
20 |
+
class SassString extends SassLiteral
|
21 |
+
{
|
22 |
const MATCH = '/^(((["\'])(.*?)(\3))|(-[a-zA-Z-]+[^\s]*?))/i';
|
23 |
const _MATCH = '/^(["\'])(.*?)(\1)?$/'; // Used to match strings such as "Times New Roman",serif
|
24 |
const VALUE = 2;
|
34 |
* @param string string
|
35 |
* @return SassString
|
36 |
*/
|
37 |
+
public function __construct($value)
|
38 |
+
{
|
39 |
preg_match(self::_MATCH, $value, $matches);
|
40 |
if ((isset($matches[self::QUOTE]))) {
|
41 |
$this->quote = $matches[self::QUOTE];
|
42 |
$this->value = $matches[self::VALUE];
|
43 |
+
} else {
|
|
|
44 |
$this->quote = '';
|
45 |
$this->value = $value;
|
46 |
}
|
53 |
* @param sassString string to add to this
|
54 |
* @return sassString the string result
|
55 |
*/
|
56 |
+
public function op_plus($other)
|
57 |
+
{
|
58 |
$this->value .= $other->value;
|
59 |
+
|
60 |
return $this;
|
61 |
}
|
62 |
|
66 |
* @param sassNumber the number of times to repeat this
|
67 |
* @return sassString the string result
|
68 |
*/
|
69 |
+
public function op_times($other)
|
70 |
+
{
|
71 |
if (!($other instanceof SassNumber) || !$other->isUnitless()) {
|
72 |
throw new SassStringException('Value must be a unitless number', SassScriptParser::$context->node);
|
73 |
}
|
74 |
$this->value = str_repeat($this->value, $other->value);
|
75 |
+
|
76 |
return $this;
|
77 |
}
|
78 |
|
79 |
/**
|
80 |
* Equals - works better
|
81 |
*/
|
82 |
+
public function op_eq($other)
|
83 |
+
{
|
84 |
return new SassBoolean($this->value == $other->value || $this->toString() == $other->toString());
|
85 |
}
|
86 |
|
87 |
/**
|
88 |
* Evaluates the value as a boolean.
|
89 |
*/
|
90 |
+
public function toBoolean()
|
91 |
+
{
|
92 |
$value = strtolower(trim($this->value, ' "\''));
|
93 |
if (!$value || in_array($value, array('false', 'null', '0'))) {
|
94 |
return FALSE;
|
95 |
}
|
96 |
+
|
97 |
return TRUE;
|
98 |
}
|
99 |
|
101 |
* Returns the value of this string.
|
102 |
* @return string the string
|
103 |
*/
|
104 |
+
public function getValue()
|
105 |
+
{
|
106 |
return $this->value;
|
107 |
}
|
108 |
|
110 |
* Returns a string representation of the value.
|
111 |
* @return string string representation of the value.
|
112 |
*/
|
113 |
+
public function toString()
|
114 |
+
{
|
115 |
if ($this->quote) {
|
116 |
$value = $this->quote . $this->value . $this->quote;
|
117 |
+
} else {
|
|
|
118 |
$value = strlen(trim($this->value)) ? trim($this->value) : $this->value;
|
119 |
}
|
120 |
+
|
121 |
return $value;
|
122 |
}
|
123 |
|
124 |
+
public function toVar()
|
125 |
+
{
|
126 |
return SassScriptParser::$context->getVariable($this->value);
|
127 |
}
|
128 |
|
129 |
+
public function getTypeOf()
|
130 |
+
{
|
131 |
if (SassList::isa($this->toString())) {
|
132 |
return 'list';
|
133 |
}
|
134 |
+
|
135 |
return 'string';
|
136 |
}
|
137 |
|
141 |
* @param string the subject string
|
142 |
* @return mixed match at the start of the string or false if no match
|
143 |
*/
|
144 |
+
public static function isa($subject)
|
145 |
+
{
|
146 |
return (preg_match(self::MATCH, $subject, $matches) ? $matches[0] : false);
|
147 |
}
|
148 |
}
|
lib/phpsass/tests/alt.css
CHANGED
@@ -1,15 +1,16 @@
|
|
1 |
h1 {
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
1 |
h1 {
|
2 |
+
float: left;
|
3 |
+
width: 274px;
|
4 |
+
height: 75px;
|
5 |
+
margin: 0;
|
6 |
+
background-repeat: no-repeat;
|
7 |
+
background-image: none; }
|
8 |
+
h1 a:hover,
|
9 |
+
h1 a:visited {
|
10 |
+
color: green; }
|
11 |
+
h1 b:hover {
|
12 |
+
color: red;
|
13 |
+
background-color: green; }
|
14 |
+
h1 const {
|
15 |
+
nosp: 3;
|
16 |
+
sp: 3; }
|
lib/phpsass/tests/extend_included.css
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
.error {
|
2 |
-
border: 1px #f00;
|
3 |
-
background-color: #fdd; }
|
|
|
|
|
|
lib/phpsass/tests/functions.css
CHANGED
@@ -1,69 +1,9 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
14: content: x($two: 'foo', bar) if(x($two: 'foo', bar) == bar foo, true, false);
|
11 |
-
15: adjust-color: adjust-color(#00F, $blue: -15);
|
12 |
-
16: }
|
13 |
-
|
14 |
-
Backtrace:
|
15 |
-
functions.scss:14
|
16 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:395:in `arglist'
|
17 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:370:in `fn_arglist'
|
18 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:332:in `funcall'
|
19 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:320:in `ident'
|
20 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:228:in `unary_not'
|
21 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:228:in `unary_div'
|
22 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:228:in `unary_minus'
|
23 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:228:in `unary_plus'
|
24 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:209:in `times_div_or_mod'
|
25 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:209:in `plus_or_minus'
|
26 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:209:in `relational'
|
27 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:209:in `eq_or_neq'
|
28 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:209:in `and_expr'
|
29 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:209:in `or_expr'
|
30 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:299:in `space'
|
31 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:284:in `interpolation'
|
32 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:247:in `expr'
|
33 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:470:in `assert_expr'
|
34 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/script/parser.rb:49:in `parse'
|
35 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:1008:in `sass_script'
|
36 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:868:in `value!'
|
37 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:845:in `declaration'
|
38 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:568:in `block in declaration_or_ruleset'
|
39 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:1108:in `call'
|
40 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:1108:in `rethrow'
|
41 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:578:in `declaration_or_ruleset'
|
42 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:540:in `block_child'
|
43 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:532:in `block_contents'
|
44 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:521:in `block'
|
45 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:515:in `ruleset'
|
46 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:539:in `block_child'
|
47 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:532:in `block_contents'
|
48 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:70:in `stylesheet'
|
49 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/scss/parser.rb:27:in `parse'
|
50 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/engine.rb:342:in `_to_tree'
|
51 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/engine.rb:315:in `_render'
|
52 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/engine.rb:262:in `render'
|
53 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/plugin/compiler.rb:341:in `update_stylesheet'
|
54 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/plugin/compiler.rb:203:in `block in update_stylesheets'
|
55 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/plugin/compiler.rb:201:in `each'
|
56 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/plugin/compiler.rb:201:in `update_stylesheets'
|
57 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/plugin.rb:81:in `update_stylesheets'
|
58 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/exec.rb:424:in `watch_or_update'
|
59 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/exec.rb:307:in `process_result'
|
60 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/exec.rb:41:in `parse'
|
61 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/lib/sass/exec.rb:21:in `parse!'
|
62 |
-
/var/lib/gems/1.9.1/gems/sass-3.2.3/bin/scss:8:in `<top (required)>'
|
63 |
-
/usr/local/bin/scss:23:in `load'
|
64 |
-
/usr/local/bin/scss:23:in `<main>'
|
65 |
-
*/
|
66 |
-
body:before {
|
67 |
-
white-space: pre;
|
68 |
-
font-family: monospace;
|
69 |
-
content: "Syntax error: Positional arguments must come before keyword arguments.\A on line 14 of functions.scss\A \A 9: #{test()} {\A 10: content: x() if(x() == 'one two', true, false);\A 11: content: x('foo', 'bar') if(x('foo', 'bar') == 'foo bar', true, false);\A 12: content: x('foo') if(x('foo') == 'foo two', true, false);\A 13: content: x($two: 'foo') if(x($two: 'foo') == 'one foo', true, false);\A 14: content: x($two: 'foo', bar) if(x($two: 'foo', bar) == bar foo, true, false);\A 15: adjust-color: adjust-color(#00F, $blue: -15);\A 16: }"; }
|
1 |
+
foo,
|
2 |
+
bar,
|
3 |
+
foo + bar {
|
4 |
+
content: 'one two' true;
|
5 |
+
content: 'foo bar' true;
|
6 |
+
content: 'foo two' true;
|
7 |
+
content: 'one foo' true;
|
8 |
+
content: bar foo true;
|
9 |
+
adjust-color: #0000f0; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/phpsass/tests/phpSassTest.php
CHANGED
@@ -4,19 +4,20 @@
|
|
4 |
* PHP Sass tests.
|
5 |
* @group sass
|
6 |
*/
|
7 |
-
class PHPSass_TestCase extends PHPUnit_Framework_TestCase
|
8 |
-
|
9 |
/**
|
10 |
* This is the path to a directory of SASS, SCSS and CSS files used in tests.
|
11 |
*/
|
12 |
-
|
13 |
|
14 |
/**
|
15 |
* This is the location of the PHPSass library being used.
|
16 |
*/
|
17 |
-
|
18 |
|
19 |
-
protected function setUp()
|
|
|
20 |
parent::setUp();
|
21 |
|
22 |
$this->requirePHPSassLibrary();
|
@@ -30,8 +31,8 @@ class PHPSass_TestCase extends PHPUnit_Framework_TestCase {
|
|
30 |
* few known locations, and then failing all of that we fall back to
|
31 |
* downloading it from the web.
|
32 |
*/
|
33 |
-
protected function requirePHPSassLibrary()
|
34 |
-
|
35 |
// Allow people to specify the library before we are called.
|
36 |
if (isset($this->phpsass_library_path)) {
|
37 |
|
@@ -43,13 +44,13 @@ class PHPSass_TestCase extends PHPUnit_Framework_TestCase {
|
|
43 |
|
44 |
if (isset($this->phpsass_library_path)) {
|
45 |
require_once($this->phpsass_library_path . '/SassParser.php');
|
46 |
-
}
|
47 |
-
else {
|
48 |
throw new Exception('Could not find PHPSass compiler.');
|
49 |
}
|
50 |
}
|
51 |
|
52 |
-
protected function runSassTest($input, $output = FALSE, $settings = array())
|
|
|
53 |
$name = $input;
|
54 |
|
55 |
$path = $this->css_tests_path;
|
@@ -93,256 +94,316 @@ class PHPSass_TestCase extends PHPUnit_Framework_TestCase {
|
|
93 |
/**
|
94 |
* Logging callback for PHPSass debug messages.
|
95 |
*/
|
96 |
-
public function sassParserDebug($message, $context)
|
97 |
-
|
98 |
}
|
99 |
|
100 |
/**
|
101 |
* Logging callback for PHPSass warning messages.
|
102 |
*/
|
103 |
-
public function sassParserWarning($message, $context)
|
104 |
-
|
105 |
}
|
106 |
|
107 |
-
protected function trimResult(&$input)
|
|
|
108 |
$trim = preg_replace('/[\s;]+/', '', $input);
|
109 |
$trim = preg_replace('/\/\*.+?\*\//m', '', $trim);
|
|
|
110 |
return $trim;
|
111 |
}
|
112 |
|
113 |
-
public function testAlt()
|
|
|
114 |
$this->runSassTest('alt.sass');
|
115 |
$this->runSassTest('alt.scss');
|
116 |
}
|
117 |
|
118 |
-
public function testBasic()
|
|
|
119 |
$this->runSassTest('basic.sass');
|
120 |
}
|
121 |
|
122 |
|
123 |
-
public function testComments()
|
|
|
124 |
$this->runSassTest('comments.sass');
|
125 |
}
|
126 |
|
127 |
-
public function testCompact()
|
|
|
128 |
$this->runSassTest('compact.sass');
|
129 |
}
|
130 |
|
131 |
-
public function testComplex()
|
|
|
132 |
$this->runSassTest('complex.sass');
|
133 |
}
|
134 |
|
135 |
-
public function testCompressed()
|
|
|
136 |
$this->runSassTest('compressed.sass');
|
137 |
}
|
138 |
|
139 |
-
public function testContent()
|
|
|
140 |
$this->runSassTest('content.scss');
|
141 |
}
|
142 |
|
143 |
-
public function testCss3()
|
|
|
144 |
$this->runSassTest('css3.scss');
|
145 |
}
|
146 |
|
147 |
-
public function testDefault()
|
|
|
148 |
$this->runSassTest('default.sass');
|
149 |
}
|
150 |
|
151 |
-
public function testEach()
|
|
|
152 |
$this->runSassTest('each.scss');
|
153 |
}
|
154 |
|
155 |
-
public function testExpanded()
|
|
|
156 |
$this->runSassTest('expanded.sass');
|
157 |
}
|
158 |
|
159 |
-
public function testExtend()
|
|
|
160 |
$this->runSassTest('extend.sass');
|
161 |
}
|
162 |
|
163 |
-
public function testExtendPlaceholders()
|
|
|
164 |
$this->runSassTest('extend_placeholders.scss');
|
165 |
}
|
166 |
|
167 |
-
public function testFilters()
|
|
|
168 |
$this->runSassTest('filters.scss');
|
169 |
}
|
170 |
|
171 |
-
public function testFunctions()
|
|
|
172 |
$this->runSassTest('functions.scss');
|
173 |
}
|
174 |
|
175 |
-
public function testHolmes()
|
|
|
176 |
$this->runSassTest('holmes.sass');
|
177 |
}
|
178 |
|
179 |
-
public function testHSLFunction()
|
|
|
180 |
$this->runSassTest('hsl-functions.scss');
|
181 |
}
|
182 |
|
183 |
-
public function testIf()
|
|
|
184 |
$this->runSassTest('if.sass');
|
185 |
}
|
186 |
|
187 |
-
public function testImportedContent()
|
|
|
188 |
$this->runSassTest('import_content.sass');
|
189 |
}
|
190 |
|
191 |
-
public function testInterpolation()
|
|
|
192 |
$this->runSassTest('interpolation.scss');
|
193 |
}
|
194 |
|
195 |
-
public function testIntrospection()
|
|
|
196 |
$this->runSassTest('introspection.scss');
|
197 |
}
|
198 |
|
199 |
-
public function testImport()
|
|
|
200 |
$this->runSassTest('import.sass');
|
201 |
}
|
202 |
|
203 |
-
public function testLineNumbers()
|
|
|
204 |
$this->runSassTest('line_numbers.sass');
|
205 |
}
|
206 |
|
207 |
-
public function testList()
|
|
|
208 |
$this->runSassTest('list.scss');
|
209 |
}
|
210 |
|
211 |
-
public function testMedia()
|
|
|
212 |
$this->runSassTest('media.scss');
|
213 |
}
|
214 |
|
215 |
-
public function testMiscFunctions()
|
|
|
216 |
$this->runSassTest('misc-functions.scss');
|
217 |
}
|
218 |
|
219 |
-
public function testMisc()
|
|
|
220 |
$this->runSassTest('misc.scss');
|
221 |
}
|
222 |
|
223 |
-
public function testMixinContent()
|
|
|
224 |
$this->runSassTest('mixin-content.sass');
|
225 |
$this->runSassTest('mixin-content.scss');
|
226 |
}
|
227 |
|
228 |
-
public function testMixinJa1()
|
|
|
229 |
$this->runSassTest('mixin-ja1.sass');
|
230 |
}
|
231 |
|
232 |
-
public function testMixinParams()
|
|
|
233 |
$this->runSassTest('mixin-params.scss');
|
234 |
}
|
235 |
|
236 |
-
public function testMixins()
|
|
|
237 |
$this->runSassTest('mixins.sass');
|
238 |
}
|
239 |
|
240 |
-
public function testMixinInMixin()
|
|
|
241 |
$this->runSassTest('mixin_in_mixin.scss');
|
242 |
}
|
243 |
|
244 |
-
public function testMultiline()
|
|
|
245 |
$this->runSassTest('multiline.sass');
|
246 |
}
|
247 |
|
248 |
-
public function testNestedImport()
|
|
|
249 |
$this->runSassTest('nested_import.sass');
|
250 |
}
|
251 |
|
252 |
-
public function testNested()
|
|
|
253 |
$this->runSassTest('nested.sass');
|
254 |
}
|
255 |
|
256 |
-
public function testNestedMedia()
|
|
|
257 |
$this->runSassTest('nested_media.scss');
|
258 |
}
|
259 |
|
260 |
-
public function testNestedPseudo()
|
|
|
261 |
$this->runSassTest('nested_pseudo.scss');
|
262 |
}
|
263 |
|
264 |
-
public function testNumber()
|
|
|
265 |
$this->runSassTest('number.scss');
|
266 |
}
|
267 |
|
268 |
-
public function testOpacity()
|
|
|
269 |
$this->runSassTest('opacity.scss');
|
270 |
}
|
271 |
|
272 |
-
public function testOtherColor()
|
|
|
273 |
$this->runSassTest('other-color.scss');
|
274 |
}
|
275 |
|
276 |
-
public function testParentRef()
|
|
|
277 |
$this->runSassTest('parent_ref.sass');
|
278 |
}
|
279 |
|
280 |
-
public function testProprietarySelector()
|
|
|
281 |
$this->runSassTest('proprietary-selector.scss');
|
282 |
}
|
283 |
|
284 |
-
public function testRGBFunctions()
|
|
|
285 |
$this->runSassTest('rgb-functions.scss');
|
286 |
}
|
287 |
|
288 |
-
public function testScssImportee()
|
|
|
289 |
$this->runSassTest('scss_importee.scss');
|
290 |
}
|
291 |
|
292 |
-
public function testScssImport()
|
|
|
293 |
$this->runSassTest('scss_import.scss');
|
294 |
}
|
295 |
|
296 |
-
public function testSplats()
|
|
|
297 |
$this->runSassTest('splats.scss');
|
298 |
}
|
299 |
|
300 |
-
public function testString()
|
|
|
301 |
$this->runSassTest('string.scss');
|
302 |
}
|
303 |
|
304 |
-
public function testUnits()
|
|
|
305 |
$this->runSassTest('units.sass');
|
306 |
}
|
307 |
|
308 |
-
public function testListVariable()
|
|
|
309 |
$this->runSassTest('list_variable.scss');
|
310 |
}
|
311 |
|
312 |
-
public function testMediaInFor()
|
|
|
313 |
$this->runSassTest('media_in_for.scss');
|
314 |
}
|
315 |
|
316 |
-
public function testMediaInMixin()
|
|
|
317 |
$this->runSassTest('media_in_mixin.scss');
|
318 |
}
|
319 |
|
320 |
-
public function testMediaInTwoMixins()
|
|
|
321 |
$this->runSassTest('media_in_mixin_in_mixin.scss');
|
322 |
}
|
323 |
|
324 |
-
public function testIfParentheses()
|
|
|
325 |
$this->runSassTest('if_parentheses.scss');
|
326 |
}
|
327 |
|
328 |
-
public function testListEmpty()
|
|
|
329 |
$this->runSassTest('list_empty.scss');
|
330 |
}
|
331 |
|
332 |
-
public function testWarnImported()
|
|
|
333 |
$this->markTestIncomplete('This test has not been implemented yet.');
|
334 |
//$this->runSassTest('warn_imported.sass');
|
335 |
}
|
336 |
|
337 |
-
public function testWarn()
|
|
|
338 |
$this->runSassTest('warn.sass');
|
339 |
}
|
340 |
|
341 |
-
public function testColour()
|
|
|
342 |
$this->runSassTest('colour-nth.scss');
|
343 |
}
|
344 |
|
345 |
-
public function testMixinSetvar()
|
|
|
346 |
$this->runSassTest('mixin_setvar.scss');
|
347 |
}
|
348 |
}
|
4 |
* PHP Sass tests.
|
5 |
* @group sass
|
6 |
*/
|
7 |
+
class PHPSass_TestCase extends PHPUnit_Framework_TestCase
|
8 |
+
{
|
9 |
/**
|
10 |
* This is the path to a directory of SASS, SCSS and CSS files used in tests.
|
11 |
*/
|
12 |
+
public $css_tests_path;
|
13 |
|
14 |
/**
|
15 |
* This is the location of the PHPSass library being used.
|
16 |
*/
|
17 |
+
public $phpsass_library_path;
|
18 |
|
19 |
+
protected function setUp()
|
20 |
+
{
|
21 |
parent::setUp();
|
22 |
|
23 |
$this->requirePHPSassLibrary();
|
31 |
* few known locations, and then failing all of that we fall back to
|
32 |
* downloading it from the web.
|
33 |
*/
|
34 |
+
protected function requirePHPSassLibrary()
|
35 |
+
{
|
36 |
// Allow people to specify the library before we are called.
|
37 |
if (isset($this->phpsass_library_path)) {
|
38 |
|
44 |
|
45 |
if (isset($this->phpsass_library_path)) {
|
46 |
require_once($this->phpsass_library_path . '/SassParser.php');
|
47 |
+
} else {
|
|
|
48 |
throw new Exception('Could not find PHPSass compiler.');
|
49 |
}
|
50 |
}
|
51 |
|
52 |
+
protected function runSassTest($input, $output = FALSE, $settings = array())
|
53 |
+
{
|
54 |
$name = $input;
|
55 |
|
56 |
$path = $this->css_tests_path;
|
94 |
/**
|
95 |
* Logging callback for PHPSass debug messages.
|
96 |
*/
|
97 |
+
public function sassParserDebug($message, $context)
|
98 |
+
{
|
99 |
}
|
100 |
|
101 |
/**
|
102 |
* Logging callback for PHPSass warning messages.
|
103 |
*/
|
104 |
+
public function sassParserWarning($message, $context)
|
105 |
+
{
|
106 |
}
|
107 |
|
108 |
+
protected function trimResult(&$input)
|
109 |
+
{
|
110 |
$trim = preg_replace('/[\s;]+/', '', $input);
|
111 |
$trim = preg_replace('/\/\*.+?\*\//m', '', $trim);
|
112 |
+
|
113 |
return $trim;
|
114 |
}
|
115 |
|
116 |
+
public function testAlt()
|
117 |
+
{
|
118 |
$this->runSassTest('alt.sass');
|
119 |
$this->runSassTest('alt.scss');
|
120 |
}
|
121 |
|
122 |
+
public function testBasic()
|
123 |
+
{
|
124 |
$this->runSassTest('basic.sass');
|
125 |
}
|
126 |
|
127 |
|
128 |
+
public function testComments()
|
129 |
+
{
|
130 |
$this->runSassTest('comments.sass');
|
131 |
}
|
132 |
|
133 |
+
public function testCompact()
|
134 |
+
{
|
135 |
$this->runSassTest('compact.sass');
|
136 |
}
|
137 |
|
138 |
+
public function testComplex()
|
139 |
+
{
|
140 |
$this->runSassTest('complex.sass');
|
141 |
}
|
142 |
|
143 |
+
public function testCompressed()
|
144 |
+
{
|
145 |
$this->runSassTest('compressed.sass');
|
146 |
}
|
147 |
|
148 |
+
public function testContent()
|
149 |
+
{
|
150 |
$this->runSassTest('content.scss');
|
151 |
}
|
152 |
|
153 |
+
public function testCss3()
|
154 |
+
{
|
155 |
$this->runSassTest('css3.scss');
|
156 |
}
|
157 |
|
158 |
+
public function testDefault()
|
159 |
+
{
|
160 |
$this->runSassTest('default.sass');
|
161 |
}
|
162 |
|
163 |
+
public function testEach()
|
164 |
+
{
|
165 |
$this->runSassTest('each.scss');
|
166 |
}
|
167 |
|
168 |
+
public function testExpanded()
|
169 |
+
{
|
170 |
$this->runSassTest('expanded.sass');
|
171 |
}
|
172 |
|
173 |
+
public function testExtend()
|
174 |
+
{
|
175 |
$this->runSassTest('extend.sass');
|
176 |
}
|
177 |
|
178 |
+
public function testExtendPlaceholders()
|
179 |
+
{
|
180 |
$this->runSassTest('extend_placeholders.scss');
|
181 |
}
|
182 |
|
183 |
+
public function testFilters()
|
184 |
+
{
|
185 |
$this->runSassTest('filters.scss');
|
186 |
}
|
187 |
|
188 |
+
public function testFunctions()
|
189 |
+
{
|
190 |
$this->runSassTest('functions.scss');
|
191 |
}
|
192 |
|
193 |
+
public function testHolmes()
|
194 |
+
{
|
195 |
$this->runSassTest('holmes.sass');
|
196 |
}
|
197 |
|
198 |
+
public function testHSLFunction()
|
199 |
+
{
|
200 |
$this->runSassTest('hsl-functions.scss');
|
201 |
}
|
202 |
|
203 |
+
public function testIf()
|
204 |
+
{
|
205 |
$this->runSassTest('if.sass');
|
206 |
}
|
207 |
|
208 |
+
public function testImportedContent()
|
209 |
+
{
|
210 |
$this->runSassTest('import_content.sass');
|
211 |
}
|
212 |
|
213 |
+
public function testInterpolation()
|
214 |
+
{
|
215 |
$this->runSassTest('interpolation.scss');
|
216 |
}
|
217 |
|
218 |
+
public function testIntrospection()
|
219 |
+
{
|
220 |
$this->runSassTest('introspection.scss');
|
221 |
}
|
222 |
|
223 |
+
public function testImport()
|
224 |
+
{
|
225 |
$this->runSassTest('import.sass');
|
226 |
}
|
227 |
|
228 |
+
public function testLineNumbers()
|
229 |
+
{
|
230 |
$this->runSassTest('line_numbers.sass');
|
231 |
}
|
232 |
|
233 |
+
public function testList()
|
234 |
+
{
|
235 |
$this->runSassTest('list.scss');
|
236 |
}
|
237 |
|
238 |
+
public function testMedia()
|
239 |
+
{
|
240 |
$this->runSassTest('media.scss');
|
241 |
}
|
242 |
|
243 |
+
public function testMiscFunctions()
|
244 |
+
{
|
245 |
$this->runSassTest('misc-functions.scss');
|
246 |
}
|
247 |
|
248 |
+
public function testMisc()
|
249 |
+
{
|
250 |
$this->runSassTest('misc.scss');
|
251 |
}
|
252 |
|
253 |
+
public function testMixinContent()
|
254 |
+
{
|
255 |
$this->runSassTest('mixin-content.sass');
|
256 |
$this->runSassTest('mixin-content.scss');
|
257 |
}
|
258 |
|
259 |
+
public function testMixinJa1()
|
260 |
+
{
|
261 |
$this->runSassTest('mixin-ja1.sass');
|
262 |
}
|
263 |
|
264 |
+
public function testMixinParams()
|
265 |
+
{
|
266 |
$this->runSassTest('mixin-params.scss');
|
267 |
}
|
268 |
|
269 |
+
public function testMixins()
|
270 |
+
{
|
271 |
$this->runSassTest('mixins.sass');
|
272 |
}
|
273 |
|
274 |
+
public function testMixinInMixin()
|
275 |
+
{
|
276 |
$this->runSassTest('mixin_in_mixin.scss');
|
277 |
}
|
278 |
|
279 |
+
public function testMultiline()
|
280 |
+
{
|
281 |
$this->runSassTest('multiline.sass');
|
282 |
}
|
283 |
|
284 |
+
public function testNestedImport()
|
285 |
+
{
|
286 |
$this->runSassTest('nested_import.sass');
|
287 |
}
|
288 |
|
289 |
+
public function testNested()
|
290 |
+
{
|
291 |
$this->runSassTest('nested.sass');
|
292 |
}
|
293 |
|
294 |
+
public function testNestedMedia()
|
295 |
+
{
|
296 |
$this->runSassTest('nested_media.scss');
|
297 |
}
|
298 |
|
299 |
+
public function testNestedPseudo()
|
300 |
+
{
|
301 |
$this->runSassTest('nested_pseudo.scss');
|
302 |
}
|
303 |
|
304 |
+
public function testNumber()
|
305 |
+
{
|
306 |
$this->runSassTest('number.scss');
|
307 |
}
|
308 |
|
309 |
+
public function testOpacity()
|
310 |
+
{
|
311 |
$this->runSassTest('opacity.scss');
|
312 |
}
|
313 |
|
314 |
+
public function testOtherColor()
|
315 |
+
{
|
316 |
$this->runSassTest('other-color.scss');
|
317 |
}
|
318 |
|
319 |
+
public function testParentRef()
|
320 |
+
{
|
321 |
$this->runSassTest('parent_ref.sass');
|
322 |
}
|
323 |
|
324 |
+
public function testProprietarySelector()
|
325 |
+
{
|
326 |
$this->runSassTest('proprietary-selector.scss');
|
327 |
}
|
328 |
|
329 |
+
public function testRGBFunctions()
|
330 |
+
{
|
331 |
$this->runSassTest('rgb-functions.scss');
|
332 |
}
|
333 |
|
334 |
+
public function testScssImportee()
|
335 |
+
{
|
336 |
$this->runSassTest('scss_importee.scss');
|
337 |
}
|
338 |
|
339 |
+
public function testScssImport()
|
340 |
+
{
|
341 |
$this->runSassTest('scss_import.scss');
|
342 |
}
|
343 |
|
344 |
+
public function testSplats()
|
345 |
+
{
|
346 |
$this->runSassTest('splats.scss');
|
347 |
}
|
348 |
|
349 |
+
public function testString()
|
350 |
+
{
|
351 |
$this->runSassTest('string.scss');
|
352 |
}
|
353 |
|
354 |
+
public function testUnits()
|
355 |
+
{
|
356 |
$this->runSassTest('units.sass');
|
357 |
}
|
358 |
|
359 |
+
public function testListVariable()
|
360 |
+
{
|
361 |
$this->runSassTest('list_variable.scss');
|
362 |
}
|
363 |
|
364 |
+
public function testMediaInFor()
|
365 |
+
{
|
366 |
$this->runSassTest('media_in_for.scss');
|
367 |
}
|
368 |
|
369 |
+
public function testMediaInMixin()
|
370 |
+
{
|
371 |
$this->runSassTest('media_in_mixin.scss');
|
372 |
}
|
373 |
|
374 |
+
public function testMediaInTwoMixins()
|
375 |
+
{
|
376 |
$this->runSassTest('media_in_mixin_in_mixin.scss');
|
377 |
}
|
378 |
|
379 |
+
public function testIfParentheses()
|
380 |
+
{
|
381 |
$this->runSassTest('if_parentheses.scss');
|
382 |
}
|
383 |
|
384 |
+
public function testListEmpty()
|
385 |
+
{
|
386 |
$this->runSassTest('list_empty.scss');
|
387 |
}
|
388 |
|
389 |
+
public function testWarnImported()
|
390 |
+
{
|
391 |
$this->markTestIncomplete('This test has not been implemented yet.');
|
392 |
//$this->runSassTest('warn_imported.sass');
|
393 |
}
|
394 |
|
395 |
+
public function testWarn()
|
396 |
+
{
|
397 |
$this->runSassTest('warn.sass');
|
398 |
}
|
399 |
|
400 |
+
public function testColour()
|
401 |
+
{
|
402 |
$this->runSassTest('colour-nth.scss');
|
403 |
}
|
404 |
|
405 |
+
public function testMixinSetvar()
|
406 |
+
{
|
407 |
$this->runSassTest('mixin_setvar.scss');
|
408 |
}
|
409 |
}
|
lib/phpsass/tree/SassCommentNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassCommentNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = '/';
|
20 |
const MATCH = '%^/\*\s*?(.*?)\s*?(\*/)?$%s';
|
21 |
const COMMENT = 1;
|
@@ -27,13 +28,15 @@ class SassCommentNode extends SassNode {
|
|
27 |
* @param object source token
|
28 |
* @return CommentNode
|
29 |
*/
|
30 |
-
public function __construct($token)
|
|
|
31 |
parent::__construct($token);
|
32 |
preg_match(self::MATCH, $token->source, $matches);
|
33 |
$this->value = $matches[self::COMMENT];
|
34 |
}
|
35 |
|
36 |
-
protected function getValue()
|
|
|
37 |
return $this->value;
|
38 |
}
|
39 |
|
@@ -41,7 +44,8 @@ class SassCommentNode extends SassNode {
|
|
41 |
* Parse this node.
|
42 |
* @return array the parsed node - an empty array
|
43 |
*/
|
44 |
-
public function parse($context)
|
|
|
45 |
return array($this);
|
46 |
}
|
47 |
|
@@ -49,7 +53,8 @@ class SassCommentNode extends SassNode {
|
|
49 |
* Render this node.
|
50 |
* @return string the rendered node
|
51 |
*/
|
52 |
-
public function render()
|
|
|
53 |
return $this->renderer->renderComment($this);
|
54 |
}
|
55 |
|
@@ -58,7 +63,8 @@ class SassCommentNode extends SassNode {
|
|
58 |
* @param object token
|
59 |
* @return boolean true if the token represents this type of node, false if not
|
60 |
*/
|
61 |
-
public static function isa($token)
|
|
|
62 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
63 |
}
|
64 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassCommentNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = '/';
|
21 |
const MATCH = '%^/\*\s*?(.*?)\s*?(\*/)?$%s';
|
22 |
const COMMENT = 1;
|
28 |
* @param object source token
|
29 |
* @return CommentNode
|
30 |
*/
|
31 |
+
public function __construct($token)
|
32 |
+
{
|
33 |
parent::__construct($token);
|
34 |
preg_match(self::MATCH, $token->source, $matches);
|
35 |
$this->value = $matches[self::COMMENT];
|
36 |
}
|
37 |
|
38 |
+
protected function getValue()
|
39 |
+
{
|
40 |
return $this->value;
|
41 |
}
|
42 |
|
44 |
* Parse this node.
|
45 |
* @return array the parsed node - an empty array
|
46 |
*/
|
47 |
+
public function parse($context)
|
48 |
+
{
|
49 |
return array($this);
|
50 |
}
|
51 |
|
53 |
* Render this node.
|
54 |
* @return string the rendered node
|
55 |
*/
|
56 |
+
public function render()
|
57 |
+
{
|
58 |
return $this->renderer->renderComment($this);
|
59 |
}
|
60 |
|
63 |
* @param object token
|
64 |
* @return boolean true if the token represents this type of node, false if not
|
65 |
*/
|
66 |
+
public static function isa($token)
|
67 |
+
{
|
68 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
69 |
}
|
70 |
}
|
lib/phpsass/tree/SassContentNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassContentNode extends SassNode
|
|
|
19 |
const MATCH = '/^(@content)(.*)$/i';
|
20 |
const IDENTIFIER = 1;
|
21 |
|
@@ -29,7 +30,8 @@ class SassContentNode extends SassNode {
|
|
29 |
* @param object source token
|
30 |
* @return SassContentNode
|
31 |
*/
|
32 |
-
public function __construct($token)
|
|
|
33 |
parent::__construct($token);
|
34 |
preg_match(self::MATCH, $token->source, $matches);
|
35 |
|
@@ -45,7 +47,8 @@ class SassContentNode extends SassNode {
|
|
45 |
* @param SassContext the context in which this node is parsed
|
46 |
* @return array the parsed node
|
47 |
*/
|
48 |
-
public function parse($pcontext)
|
|
|
49 |
$return = $this;
|
50 |
$context = new SassContext($pcontext);
|
51 |
|
@@ -56,6 +59,7 @@ class SassContentNode extends SassNode {
|
|
56 |
$ctx->variables = $pcontext->variables;
|
57 |
$children = array_merge($children, $child->parse($ctx));
|
58 |
}
|
|
|
59 |
return $children;
|
60 |
}
|
61 |
|
@@ -64,7 +68,8 @@ class SassContentNode extends SassNode {
|
|
64 |
* @param object token
|
65 |
* @return boolean true if the token represents this type of node, false if not
|
66 |
*/
|
67 |
-
public static function isa($token)
|
|
|
68 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
69 |
}
|
70 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassContentNode extends SassNode
|
19 |
+
{
|
20 |
const MATCH = '/^(@content)(.*)$/i';
|
21 |
const IDENTIFIER = 1;
|
22 |
|
30 |
* @param object source token
|
31 |
* @return SassContentNode
|
32 |
*/
|
33 |
+
public function __construct($token)
|
34 |
+
{
|
35 |
parent::__construct($token);
|
36 |
preg_match(self::MATCH, $token->source, $matches);
|
37 |
|
47 |
* @param SassContext the context in which this node is parsed
|
48 |
* @return array the parsed node
|
49 |
*/
|
50 |
+
public function parse($pcontext)
|
51 |
+
{
|
52 |
$return = $this;
|
53 |
$context = new SassContext($pcontext);
|
54 |
|
59 |
$ctx->variables = $pcontext->variables;
|
60 |
$children = array_merge($children, $child->parse($ctx));
|
61 |
}
|
62 |
+
|
63 |
return $children;
|
64 |
}
|
65 |
|
68 |
* @param object token
|
69 |
* @return boolean true if the token represents this type of node, false if not
|
70 |
*/
|
71 |
+
public static function isa($token)
|
72 |
+
{
|
73 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
74 |
}
|
75 |
}
|
lib/phpsass/tree/SassContext.php
CHANGED
@@ -17,7 +17,8 @@
|
|
17 |
* @package PHamlP
|
18 |
* @subpackage Sass.tree
|
19 |
*/
|
20 |
-
class SassContext
|
|
|
21 |
/**
|
22 |
* @var SassContext enclosing context
|
23 |
*/
|
@@ -53,14 +54,16 @@ class SassContext {
|
|
53 |
* @param SassContext - the enclosing context
|
54 |
* @return SassContext
|
55 |
*/
|
56 |
-
public function __construct($parent = null)
|
|
|
57 |
$this->parent = $parent;
|
58 |
}
|
59 |
|
60 |
/**
|
61 |
*
|
62 |
*/
|
63 |
-
public function getContent()
|
|
|
64 |
if ($this->content) {
|
65 |
return $this->content;
|
66 |
}
|
@@ -75,8 +78,10 @@ class SassContext {
|
|
75 |
* @param string name of mixin
|
76 |
* @return SassMixinDefinitionNode the mixin
|
77 |
*/
|
78 |
-
public function addMixin($name, $mixin)
|
|
|
79 |
$this->mixins[$name] = $mixin;
|
|
|
80 |
return $this;
|
81 |
}
|
82 |
|
@@ -86,11 +91,11 @@ class SassContext {
|
|
86 |
* @return SassMixinDefinitionNode the mixin
|
87 |
* @throws SassContextException if mixin not defined in this context
|
88 |
*/
|
89 |
-
public function getMixin($name)
|
|
|
90 |
if (isset($this->mixins[$name])) {
|
91 |
return $this->mixins[$name];
|
92 |
-
}
|
93 |
-
elseif (!empty($this->parent)) {
|
94 |
return $this->parent->getMixin($name);
|
95 |
}
|
96 |
throw new SassContextException('Undefined Mixin: ' . $name, $this->node);
|
@@ -101,11 +106,13 @@ class SassContext {
|
|
101 |
* @param string name of function
|
102 |
* @return SassFunctionDefinitionNode the function
|
103 |
*/
|
104 |
-
public function addFunction($name, $function)
|
|
|
105 |
$this->functions[$name] = $function;
|
106 |
if (!empty($this->parent)) {
|
107 |
$this->parent->addFunction($name);
|
108 |
}
|
|
|
109 |
return $this;
|
110 |
}
|
111 |
|
@@ -115,7 +122,8 @@ class SassContext {
|
|
115 |
* @return SassFunctionDefinitionNode the mixin
|
116 |
* @throws SassContextException if function not defined in this context
|
117 |
*/
|
118 |
-
public function getFunction($name)
|
|
|
119 |
if ($fn = $this->hasFunction($name)) {
|
120 |
return $fn;
|
121 |
}
|
@@ -127,12 +135,14 @@ class SassContext {
|
|
127 |
* @param string name of function to check for
|
128 |
* @return boolean
|
129 |
*/
|
130 |
-
public function hasFunction($name)
|
|
|
131 |
if (isset($this->functions[$name])) {
|
132 |
return $this->functions[$name];
|
133 |
-
}
|
134 |
return $this->parent->hasFunction($name);
|
135 |
}
|
|
|
136 |
return FALSE;
|
137 |
}
|
138 |
|
@@ -142,15 +152,14 @@ class SassContext {
|
|
142 |
* @return string the variable
|
143 |
* @throws SassContextException if variable not defined in this context
|
144 |
*/
|
145 |
-
public function getVariable($name)
|
|
|
146 |
$name = str_replace('-', '_', $name);
|
147 |
if ($this->hasVariable($name)) {
|
148 |
return $this->variables[$name];
|
149 |
-
}
|
150 |
-
elseif (!empty($this->parent)) {
|
151 |
return $this->parent->getVariable($name);
|
152 |
-
}
|
153 |
-
else {
|
154 |
// Return false instead of throwing an exception.
|
155 |
// throw new SassContextException('Undefined Variable: ' . $name, $this->node);
|
156 |
return new SassBoolean('false');
|
@@ -162,8 +171,10 @@ class SassContext {
|
|
162 |
* @param string name of variable to test
|
163 |
* @return boolean true if the variable exists in this context, false if not
|
164 |
*/
|
165 |
-
public function hasVariable($name)
|
|
|
166 |
$name = str_replace('-', '_', $name);
|
|
|
167 |
return isset($this->variables[$name]);
|
168 |
}
|
169 |
|
@@ -172,13 +183,16 @@ class SassContext {
|
|
172 |
* @param string name of variable
|
173 |
* @param sassLiteral value of variable
|
174 |
*/
|
175 |
-
public function setVariable($name, $value)
|
|
|
176 |
$name = str_replace('-', '_', $name);
|
177 |
$this->variables[$name] = $value;
|
|
|
178 |
return $this;
|
179 |
}
|
180 |
|
181 |
-
public function setVariables($vars)
|
|
|
182 |
foreach ($vars as $key => $value) {
|
183 |
if ($value !== NULL) {
|
184 |
$this->setVariable($key, $value);
|
@@ -191,7 +205,8 @@ class SassContext {
|
|
191 |
* Note that if there are variables or mixins with the same name in the two
|
192 |
* contexts they will be set to that defined in this context.
|
193 |
*/
|
194 |
-
public function merge()
|
|
|
195 |
$this->parent->variables = array_merge($this->parent->variables, $this->variables);
|
196 |
$this->parent->mixins = array_merge($this->parent->mixins, $this->mixins);
|
197 |
}
|
17 |
* @package PHamlP
|
18 |
* @subpackage Sass.tree
|
19 |
*/
|
20 |
+
class SassContext
|
21 |
+
{
|
22 |
/**
|
23 |
* @var SassContext enclosing context
|
24 |
*/
|
54 |
* @param SassContext - the enclosing context
|
55 |
* @return SassContext
|
56 |
*/
|
57 |
+
public function __construct($parent = null)
|
58 |
+
{
|
59 |
$this->parent = $parent;
|
60 |
}
|
61 |
|
62 |
/**
|
63 |
*
|
64 |
*/
|
65 |
+
public function getContent()
|
66 |
+
{
|
67 |
if ($this->content) {
|
68 |
return $this->content;
|
69 |
}
|
78 |
* @param string name of mixin
|
79 |
* @return SassMixinDefinitionNode the mixin
|
80 |
*/
|
81 |
+
public function addMixin($name, $mixin)
|
82 |
+
{
|
83 |
$this->mixins[$name] = $mixin;
|
84 |
+
|
85 |
return $this;
|
86 |
}
|
87 |
|
91 |
* @return SassMixinDefinitionNode the mixin
|
92 |
* @throws SassContextException if mixin not defined in this context
|
93 |
*/
|
94 |
+
public function getMixin($name)
|
95 |
+
{
|
96 |
if (isset($this->mixins[$name])) {
|
97 |
return $this->mixins[$name];
|
98 |
+
} elseif (!empty($this->parent)) {
|
|
|
99 |
return $this->parent->getMixin($name);
|
100 |
}
|
101 |
throw new SassContextException('Undefined Mixin: ' . $name, $this->node);
|
106 |
* @param string name of function
|
107 |
* @return SassFunctionDefinitionNode the function
|
108 |
*/
|
109 |
+
public function addFunction($name, $function)
|
110 |
+
{
|
111 |
$this->functions[$name] = $function;
|
112 |
if (!empty($this->parent)) {
|
113 |
$this->parent->addFunction($name);
|
114 |
}
|
115 |
+
|
116 |
return $this;
|
117 |
}
|
118 |
|
122 |
* @return SassFunctionDefinitionNode the mixin
|
123 |
* @throws SassContextException if function not defined in this context
|
124 |
*/
|
125 |
+
public function getFunction($name)
|
126 |
+
{
|
127 |
if ($fn = $this->hasFunction($name)) {
|
128 |
return $fn;
|
129 |
}
|
135 |
* @param string name of function to check for
|
136 |
* @return boolean
|
137 |
*/
|
138 |
+
public function hasFunction($name)
|
139 |
+
{
|
140 |
if (isset($this->functions[$name])) {
|
141 |
return $this->functions[$name];
|
142 |
+
} elseif (!empty($this->parent)) {
|
143 |
return $this->parent->hasFunction($name);
|
144 |
}
|
145 |
+
|
146 |
return FALSE;
|
147 |
}
|
148 |
|
152 |
* @return string the variable
|
153 |
* @throws SassContextException if variable not defined in this context
|
154 |
*/
|
155 |
+
public function getVariable($name)
|
156 |
+
{
|
157 |
$name = str_replace('-', '_', $name);
|
158 |
if ($this->hasVariable($name)) {
|
159 |
return $this->variables[$name];
|
160 |
+
} elseif (!empty($this->parent)) {
|
|
|
161 |
return $this->parent->getVariable($name);
|
162 |
+
} else {
|
|
|
163 |
// Return false instead of throwing an exception.
|
164 |
// throw new SassContextException('Undefined Variable: ' . $name, $this->node);
|
165 |
return new SassBoolean('false');
|
171 |
* @param string name of variable to test
|
172 |
* @return boolean true if the variable exists in this context, false if not
|
173 |
*/
|
174 |
+
public function hasVariable($name)
|
175 |
+
{
|
176 |
$name = str_replace('-', '_', $name);
|
177 |
+
|
178 |
return isset($this->variables[$name]);
|
179 |
}
|
180 |
|
183 |
* @param string name of variable
|
184 |
* @param sassLiteral value of variable
|
185 |
*/
|
186 |
+
public function setVariable($name, $value)
|
187 |
+
{
|
188 |
$name = str_replace('-', '_', $name);
|
189 |
$this->variables[$name] = $value;
|
190 |
+
|
191 |
return $this;
|
192 |
}
|
193 |
|
194 |
+
public function setVariables($vars)
|
195 |
+
{
|
196 |
foreach ($vars as $key => $value) {
|
197 |
if ($value !== NULL) {
|
198 |
$this->setVariable($key, $value);
|
205 |
* Note that if there are variables or mixins with the same name in the two
|
206 |
* contexts they will be set to that defined in this context.
|
207 |
*/
|
208 |
+
public function merge()
|
209 |
+
{
|
210 |
$this->parent->variables = array_merge($this->parent->variables, $this->variables);
|
211 |
$this->parent->mixins = array_merge($this->parent->mixins, $this->mixins);
|
212 |
}
|
lib/phpsass/tree/SassDebugNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassDebugNode extends SassNode
|
|
|
19 |
const IDENTIFIER = '@';
|
20 |
const MATCH = '/^@(?:debug|warn)\s+(.+?)\s*;?$/';
|
21 |
const MESSAGE = 1;
|
@@ -44,13 +45,13 @@ class SassDebugNode extends SassNode {
|
|
44 |
* @param array parameters for the message
|
45 |
* @return SassDebugNode
|
46 |
*/
|
47 |
-
public function __construct($token, $message = false)
|
|
|
48 |
parent::__construct($token);
|
49 |
if (is_string($message)) {
|
50 |
$this->message = $message;
|
51 |
$this->warning = true;
|
52 |
-
}
|
53 |
-
else {
|
54 |
preg_match(self::MATCH, $token->source, $matches);
|
55 |
$this->message = $matches[self::MESSAGE];
|
56 |
$this->warning = $message;
|
@@ -62,7 +63,8 @@ class SassDebugNode extends SassNode {
|
|
62 |
* This raises an error.
|
63 |
* @return array An empty array
|
64 |
*/
|
65 |
-
public function parse($context)
|
|
|
66 |
if (!$this->warning) {
|
67 |
$result = $this->evaluate($this->message, $context)->toString();
|
68 |
|
@@ -84,7 +86,8 @@ class SassDebugNode extends SassNode {
|
|
84 |
* @param int Error number
|
85 |
* @param string Message
|
86 |
*/
|
87 |
-
public function errorHandler($errno, $message)
|
|
|
88 |
echo '<div style="background-color:#ce4dd6;border-bottom:1px dashed #88338d;color:white;font:10pt verdana;margin:0;padding:0.5em 2%;width:96%;"><p style="height:auto;margin:0.25em 0;padding:0;width:100%;"><span style="font-weight:bold;">SASS '.($this->warning ? 'WARNING' : 'DEBUG').":</span> $message</p><p style=\"margin:0.1em;padding:0;padding-left:0.5em;width:100%;\">{$this->filename}::{$this->line}</p><p style=\"margin:0.1em;padding:0;padding-left:0.5em;width:100%;\">Source: {$this->source}</p></div>";
|
89 |
}
|
90 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassDebugNode extends SassNode
|
19 |
+
{
|
20 |
const IDENTIFIER = '@';
|
21 |
const MATCH = '/^@(?:debug|warn)\s+(.+?)\s*;?$/';
|
22 |
const MESSAGE = 1;
|
45 |
* @param array parameters for the message
|
46 |
* @return SassDebugNode
|
47 |
*/
|
48 |
+
public function __construct($token, $message = false)
|
49 |
+
{
|
50 |
parent::__construct($token);
|
51 |
if (is_string($message)) {
|
52 |
$this->message = $message;
|
53 |
$this->warning = true;
|
54 |
+
} else {
|
|
|
55 |
preg_match(self::MATCH, $token->source, $matches);
|
56 |
$this->message = $matches[self::MESSAGE];
|
57 |
$this->warning = $message;
|
63 |
* This raises an error.
|
64 |
* @return array An empty array
|
65 |
*/
|
66 |
+
public function parse($context)
|
67 |
+
{
|
68 |
if (!$this->warning) {
|
69 |
$result = $this->evaluate($this->message, $context)->toString();
|
70 |
|
86 |
* @param int Error number
|
87 |
* @param string Message
|
88 |
*/
|
89 |
+
public function errorHandler($errno, $message)
|
90 |
+
{
|
91 |
echo '<div style="background-color:#ce4dd6;border-bottom:1px dashed #88338d;color:white;font:10pt verdana;margin:0;padding:0.5em 2%;width:96%;"><p style="height:auto;margin:0.25em 0;padding:0;width:100%;"><span style="font-weight:bold;">SASS '.($this->warning ? 'WARNING' : 'DEBUG').":</span> $message</p><p style=\"margin:0.1em;padding:0;padding-left:0.5em;width:100%;\">{$this->filename}::{$this->line}</p><p style=\"margin:0.1em;padding:0;padding-left:0.5em;width:100%;\">Source: {$this->source}</p></div>";
|
92 |
}
|
93 |
}
|
lib/phpsass/tree/SassDirectiveNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassDirectiveNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = '@';
|
20 |
const MATCH = '/^(@[\w-]+)/';
|
21 |
|
@@ -26,15 +27,18 @@ class SassDirectiveNode extends SassNode {
|
|
26 |
* @param object source token
|
27 |
* @return SassDirectiveNode
|
28 |
*/
|
29 |
-
public function __construct($token)
|
|
|
30 |
parent::__construct($token);
|
31 |
}
|
32 |
|
33 |
-
protected function getDirective()
|
|
|
34 |
return $this->token->source;
|
35 |
preg_match('/^(@[\w-]+)(?:\s*(\w+))*/', $this->token->source, $matches);
|
36 |
array_shift($matches);
|
37 |
$parts = implode(' ', $matches);
|
|
|
38 |
return strtolower($parts);
|
39 |
}
|
40 |
|
@@ -43,10 +47,12 @@ class SassDirectiveNode extends SassNode {
|
|
43 |
* @param SassContext the context in which this node is parsed
|
44 |
* @return array the parsed node
|
45 |
*/
|
46 |
-
public function parse($context)
|
|
|
47 |
$this->token->source = self::interpolate_nonstrict($this->token->source, $context);
|
48 |
|
49 |
$this->children = $this->parseChildren($context);
|
|
|
50 |
return array($this);
|
51 |
}
|
52 |
|
@@ -54,7 +60,8 @@ class SassDirectiveNode extends SassNode {
|
|
54 |
* Render this node.
|
55 |
* @return string the rendered node
|
56 |
*/
|
57 |
-
public function render()
|
|
|
58 |
$properties = array();
|
59 |
foreach ($this->children as $child) {
|
60 |
$properties[] = $child->render();
|
@@ -68,7 +75,8 @@ class SassDirectiveNode extends SassNode {
|
|
68 |
* @param object token
|
69 |
* @return boolean true if the token represents this type of node, false if not
|
70 |
*/
|
71 |
-
public static function isa($token)
|
|
|
72 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
73 |
}
|
74 |
|
@@ -77,13 +85,15 @@ class SassDirectiveNode extends SassNode {
|
|
77 |
* @param object token
|
78 |
* @return string the directive
|
79 |
*/
|
80 |
-
public static function extractDirective($token)
|
81 |
-
|
82 |
preg_match(self::MATCH, $token->source, $matches);
|
|
|
83 |
return strtolower($matches[1]);
|
84 |
}
|
85 |
|
86 |
-
public static function interpolate_nonstrict($string, $context)
|
|
|
87 |
for ($i = 0, $n = preg_match_all(self::INTERPOLATION_MATCH, $string, $matches); $i < $n; $i++) {
|
88 |
$var = SassScriptParser::$instance->evaluate($matches[0][$i], $context);
|
89 |
|
@@ -93,16 +103,13 @@ class SassDirectiveNode extends SassNode {
|
|
93 |
$var = $var->toString();
|
94 |
}
|
95 |
|
96 |
-
if(preg_match('/^unquote\((["\'])(.*)\1\)$/', $var, $match)){
|
97 |
$val = $match[2];
|
98 |
-
}
|
99 |
-
else if($var == '""'){
|
100 |
$val = "";
|
101 |
-
}
|
102 |
-
else if(preg_match('/^(["\'])(.*)\1$/', $var, $match)){
|
103 |
$val = $match[2];
|
104 |
-
}
|
105 |
-
else {
|
106 |
$val = $var;
|
107 |
}
|
108 |
$matches[1][$i] = $val;
|
@@ -111,6 +118,7 @@ class SassDirectiveNode extends SassNode {
|
|
111 |
$matches[0][] = '}';
|
112 |
$matches[1][] = '';
|
113 |
$matches[1][] = '';
|
|
|
114 |
return str_replace($matches[0], $matches[1], $string);
|
115 |
}
|
116 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassDirectiveNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = '@';
|
21 |
const MATCH = '/^(@[\w-]+)/';
|
22 |
|
27 |
* @param object source token
|
28 |
* @return SassDirectiveNode
|
29 |
*/
|
30 |
+
public function __construct($token)
|
31 |
+
{
|
32 |
parent::__construct($token);
|
33 |
}
|
34 |
|
35 |
+
protected function getDirective()
|
36 |
+
{
|
37 |
return $this->token->source;
|
38 |
preg_match('/^(@[\w-]+)(?:\s*(\w+))*/', $this->token->source, $matches);
|
39 |
array_shift($matches);
|
40 |
$parts = implode(' ', $matches);
|
41 |
+
|
42 |
return strtolower($parts);
|
43 |
}
|
44 |
|
47 |
* @param SassContext the context in which this node is parsed
|
48 |
* @return array the parsed node
|
49 |
*/
|
50 |
+
public function parse($context)
|
51 |
+
{
|
52 |
$this->token->source = self::interpolate_nonstrict($this->token->source, $context);
|
53 |
|
54 |
$this->children = $this->parseChildren($context);
|
55 |
+
|
56 |
return array($this);
|
57 |
}
|
58 |
|
60 |
* Render this node.
|
61 |
* @return string the rendered node
|
62 |
*/
|
63 |
+
public function render()
|
64 |
+
{
|
65 |
$properties = array();
|
66 |
foreach ($this->children as $child) {
|
67 |
$properties[] = $child->render();
|
75 |
* @param object token
|
76 |
* @return boolean true if the token represents this type of node, false if not
|
77 |
*/
|
78 |
+
public static function isa($token)
|
79 |
+
{
|
80 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
81 |
}
|
82 |
|
85 |
* @param object token
|
86 |
* @return string the directive
|
87 |
*/
|
88 |
+
public static function extractDirective($token)
|
89 |
+
{
|
90 |
preg_match(self::MATCH, $token->source, $matches);
|
91 |
+
|
92 |
return strtolower($matches[1]);
|
93 |
}
|
94 |
|
95 |
+
public static function interpolate_nonstrict($string, $context)
|
96 |
+
{
|
97 |
for ($i = 0, $n = preg_match_all(self::INTERPOLATION_MATCH, $string, $matches); $i < $n; $i++) {
|
98 |
$var = SassScriptParser::$instance->evaluate($matches[0][$i], $context);
|
99 |
|
103 |
$var = $var->toString();
|
104 |
}
|
105 |
|
106 |
+
if (preg_match('/^unquote\((["\'])(.*)\1\)$/', $var, $match)) {
|
107 |
$val = $match[2];
|
108 |
+
} elseif ($var == '""') {
|
|
|
109 |
$val = "";
|
110 |
+
} elseif (preg_match('/^(["\'])(.*)\1$/', $var, $match)) {
|
|
|
111 |
$val = $match[2];
|
112 |
+
} else {
|
|
|
113 |
$val = $var;
|
114 |
}
|
115 |
$matches[1][$i] = $val;
|
118 |
$matches[0][] = '}';
|
119 |
$matches[1][] = '';
|
120 |
$matches[1][] = '';
|
121 |
+
|
122 |
return str_replace($matches[0], $matches[1], $string);
|
123 |
}
|
124 |
}
|
lib/phpsass/tree/SassEachNode.php
CHANGED
@@ -22,7 +22,8 @@
|
|
22 |
* @package PHamlP
|
23 |
* @subpackage Sass.tree
|
24 |
*/
|
25 |
-
class SassEachNode extends SassNode
|
|
|
26 |
const MATCH = '/@each\s+[!\$](.+?)in\s+(.+)$/i';
|
27 |
|
28 |
const VARIABLE = 1;
|
@@ -42,12 +43,12 @@ class SassEachNode extends SassNode {
|
|
42 |
* @param object source token
|
43 |
* @return SassEachNode
|
44 |
*/
|
45 |
-
public function __construct($token)
|
|
|
46 |
parent::__construct($token);
|
47 |
if (!preg_match(self::MATCH, $token->source, $matches)) {
|
48 |
throw new SassEachNodeException('Invalid @each directive', $this);
|
49 |
-
}
|
50 |
-
else {
|
51 |
$this->variable = trim($matches[self::VARIABLE]);
|
52 |
$this->in = $matches[self::IN];
|
53 |
}
|
@@ -58,7 +59,8 @@ class SassEachNode extends SassNode {
|
|
58 |
* @param SassContext the context in which this node is parsed
|
59 |
* @return array parsed child nodes
|
60 |
*/
|
61 |
-
public function parse($context)
|
|
|
62 |
$children = array();
|
63 |
|
64 |
if ($this->variable && $this->in) {
|
@@ -71,6 +73,7 @@ class SassEachNode extends SassNode {
|
|
71 |
}
|
72 |
}
|
73 |
$context->merge();
|
|
|
74 |
return $children;
|
75 |
}
|
76 |
}
|
22 |
* @package PHamlP
|
23 |
* @subpackage Sass.tree
|
24 |
*/
|
25 |
+
class SassEachNode extends SassNode
|
26 |
+
{
|
27 |
const MATCH = '/@each\s+[!\$](.+?)in\s+(.+)$/i';
|
28 |
|
29 |
const VARIABLE = 1;
|
43 |
* @param object source token
|
44 |
* @return SassEachNode
|
45 |
*/
|
46 |
+
public function __construct($token)
|
47 |
+
{
|
48 |
parent::__construct($token);
|
49 |
if (!preg_match(self::MATCH, $token->source, $matches)) {
|
50 |
throw new SassEachNodeException('Invalid @each directive', $this);
|
51 |
+
} else {
|
|
|
52 |
$this->variable = trim($matches[self::VARIABLE]);
|
53 |
$this->in = $matches[self::IN];
|
54 |
}
|
59 |
* @param SassContext the context in which this node is parsed
|
60 |
* @return array parsed child nodes
|
61 |
*/
|
62 |
+
public function parse($context)
|
63 |
+
{
|
64 |
$children = array();
|
65 |
|
66 |
if ($this->variable && $this->in) {
|
73 |
}
|
74 |
}
|
75 |
$context->merge();
|
76 |
+
|
77 |
return $children;
|
78 |
}
|
79 |
}
|
lib/phpsass/tree/SassElseNode.php
CHANGED
@@ -16,13 +16,15 @@
|
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.tree
|
18 |
*/
|
19 |
-
class SassElseNode extends SassIfNode
|
|
|
20 |
/**
|
21 |
* SassElseNode constructor.
|
22 |
* @param object source token
|
23 |
* @return SassElseNode
|
24 |
*/
|
25 |
-
public function __construct($token)
|
|
|
26 |
parent::__construct($token, false);
|
27 |
}
|
28 |
-
}
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.tree
|
18 |
*/
|
19 |
+
class SassElseNode extends SassIfNode
|
20 |
+
{
|
21 |
/**
|
22 |
* SassElseNode constructor.
|
23 |
* @param object source token
|
24 |
* @return SassElseNode
|
25 |
*/
|
26 |
+
public function __construct($token)
|
27 |
+
{
|
28 |
parent::__construct($token, false);
|
29 |
}
|
30 |
+
}
|
lib/phpsass/tree/SassExtendNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassExtendNode extends SassNode
|
|
|
19 |
const IDENTIFIER = '@';
|
20 |
const MATCH = '/^@extend\s+(.+)/i';
|
21 |
const VALUE = 1;
|
@@ -30,7 +31,8 @@ class SassExtendNode extends SassNode {
|
|
30 |
* @param object source token
|
31 |
* @return SassExtendNode
|
32 |
*/
|
33 |
-
public function __construct($token)
|
|
|
34 |
parent::__construct($token);
|
35 |
preg_match(self::MATCH, $token->source, $matches);
|
36 |
$this->value = $matches[self::VALUE];
|
@@ -40,10 +42,12 @@ class SassExtendNode extends SassNode {
|
|
40 |
* Parse this node.
|
41 |
* @return array An empty array
|
42 |
*/
|
43 |
-
public function parse($context)
|
|
|
44 |
# resolve selectors in relation to variables
|
45 |
# allows extend inside nested loops.
|
46 |
$this->root->extend($this->value, $this->parent->resolveSelectors($context));
|
|
|
47 |
return array();
|
48 |
}
|
49 |
-
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassExtendNode extends SassNode
|
19 |
+
{
|
20 |
const IDENTIFIER = '@';
|
21 |
const MATCH = '/^@extend\s+(.+)/i';
|
22 |
const VALUE = 1;
|
31 |
* @param object source token
|
32 |
* @return SassExtendNode
|
33 |
*/
|
34 |
+
public function __construct($token)
|
35 |
+
{
|
36 |
parent::__construct($token);
|
37 |
preg_match(self::MATCH, $token->source, $matches);
|
38 |
$this->value = $matches[self::VALUE];
|
42 |
* Parse this node.
|
43 |
* @return array An empty array
|
44 |
*/
|
45 |
+
public function parse($context)
|
46 |
+
{
|
47 |
# resolve selectors in relation to variables
|
48 |
# allows extend inside nested loops.
|
49 |
$this->root->extend($this->value, $this->parent->resolveSelectors($context));
|
50 |
+
|
51 |
return array();
|
52 |
}
|
53 |
+
}
|
lib/phpsass/tree/SassForNode.php
CHANGED
@@ -25,7 +25,8 @@
|
|
25 |
* @package PHamlP
|
26 |
* @subpackage Sass.tree
|
27 |
*/
|
28 |
-
class SassForNode extends SassNode
|
|
|
29 |
const MATCH = '/@for\s+[!\$](\w+)\s+from\s+(.+?)\s+(through|to)\s+(.+?)(?:\s+step\s+(.+))?$/i';
|
30 |
|
31 |
const VARIABLE = 1;
|
@@ -62,7 +63,8 @@ class SassForNode extends SassNode {
|
|
62 |
* @param object source token
|
63 |
* @return SassForNode
|
64 |
*/
|
65 |
-
public function __construct($token)
|
|
|
66 |
parent::__construct($token);
|
67 |
if (!preg_match(self::MATCH, $token->source, $matches)) {
|
68 |
throw new SassForNodeException('Invalid @for directive', $this);
|
@@ -79,11 +81,12 @@ class SassForNode extends SassNode {
|
|
79 |
* @param SassContext the context in which this node is parsed
|
80 |
* @return array parsed child nodes
|
81 |
*/
|
82 |
-
public function parse($context)
|
|
|
83 |
$children = array();
|
84 |
-
$from = (float)$this->evaluate($this->from, $context)->value;
|
85 |
-
$to = (float)$this->evaluate($this->to, $context)->value;
|
86 |
-
$step = (float)$this->evaluate($this->step, $context)->value * ($to > $from ? 1 : -1);
|
87 |
|
88 |
if ($this->inclusive) {
|
89 |
$to += ($from < $to ? 1 : -1);
|
@@ -94,6 +97,7 @@ class SassForNode extends SassNode {
|
|
94 |
$context->setVariable($this->variable, new SassNumber($i));
|
95 |
$children = array_merge($children, $this->parseChildren($context));
|
96 |
}
|
|
|
97 |
return $children;
|
98 |
}
|
99 |
-
}
|
25 |
* @package PHamlP
|
26 |
* @subpackage Sass.tree
|
27 |
*/
|
28 |
+
class SassForNode extends SassNode
|
29 |
+
{
|
30 |
const MATCH = '/@for\s+[!\$](\w+)\s+from\s+(.+?)\s+(through|to)\s+(.+?)(?:\s+step\s+(.+))?$/i';
|
31 |
|
32 |
const VARIABLE = 1;
|
63 |
* @param object source token
|
64 |
* @return SassForNode
|
65 |
*/
|
66 |
+
public function __construct($token)
|
67 |
+
{
|
68 |
parent::__construct($token);
|
69 |
if (!preg_match(self::MATCH, $token->source, $matches)) {
|
70 |
throw new SassForNodeException('Invalid @for directive', $this);
|
81 |
* @param SassContext the context in which this node is parsed
|
82 |
* @return array parsed child nodes
|
83 |
*/
|
84 |
+
public function parse($context)
|
85 |
+
{
|
86 |
$children = array();
|
87 |
+
$from = (float) $this->evaluate($this->from, $context)->value;
|
88 |
+
$to = (float) $this->evaluate($this->to, $context)->value;
|
89 |
+
$step = (float) $this->evaluate($this->step, $context)->value * ($to > $from ? 1 : -1);
|
90 |
|
91 |
if ($this->inclusive) {
|
92 |
$to += ($from < $to ? 1 : -1);
|
97 |
$context->setVariable($this->variable, new SassNumber($i));
|
98 |
$children = array_merge($children, $this->parseChildren($context));
|
99 |
}
|
100 |
+
|
101 |
return $children;
|
102 |
}
|
103 |
+
}
|
lib/phpsass/tree/SassFunctionDefinitionNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassFunctionDefinitionNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = FALSE;
|
20 |
const MATCH = '/^@function\s+([_-\w]+)\s*(?:\((.*?)\))?\s*$/im';
|
21 |
const IDENTIFIER = 1;
|
@@ -39,7 +40,8 @@ class SassFunctionDefinitionNode extends SassNode {
|
|
39 |
* @param object source token
|
40 |
* @return SassFunctionDefinitionNode
|
41 |
*/
|
42 |
-
public function __construct($token)
|
|
|
43 |
// if ($token->level !== 0) {
|
44 |
// throw new SassFunctionDefinitionNodeException('Functions can only be defined at root level', $token);
|
45 |
// }
|
@@ -66,8 +68,10 @@ class SassFunctionDefinitionNode extends SassNode {
|
|
66 |
* @param SassContext the context in which this node is parsed
|
67 |
* @return array the parsed node - an empty array
|
68 |
*/
|
69 |
-
public function parse($context)
|
|
|
70 |
$context->addFunction($this->name, $this);
|
|
|
71 |
return array();
|
72 |
}
|
73 |
|
@@ -75,7 +79,8 @@ class SassFunctionDefinitionNode extends SassNode {
|
|
75 |
* Returns the arguments with default values for this function
|
76 |
* @return array the arguments with default values for this function
|
77 |
*/
|
78 |
-
public function getArgs()
|
|
|
79 |
return $this->args;
|
80 |
}
|
81 |
|
@@ -84,7 +89,8 @@ class SassFunctionDefinitionNode extends SassNode {
|
|
84 |
* @param object token
|
85 |
* @return boolean true if the token represents this type of node, false if not
|
86 |
*/
|
87 |
-
public static function isa($token)
|
|
|
88 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
89 |
}
|
90 |
|
@@ -95,7 +101,8 @@ class SassFunctionDefinitionNode extends SassNode {
|
|
95 |
* @throws SassReturn - if the @return is fired then this is thrown to break early
|
96 |
* @return SassBoolean(false) - if no @return was fired, return false
|
97 |
*/
|
98 |
-
public function execute($pcontext, $provided)
|
|
|
99 |
list($arguments, $context) = SassScriptFunction::fill_parameters($this->args, $provided, $pcontext, $this);
|
100 |
$context->setVariables($arguments);
|
101 |
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassFunctionDefinitionNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = FALSE;
|
21 |
const MATCH = '/^@function\s+([_-\w]+)\s*(?:\((.*?)\))?\s*$/im';
|
22 |
const IDENTIFIER = 1;
|
40 |
* @param object source token
|
41 |
* @return SassFunctionDefinitionNode
|
42 |
*/
|
43 |
+
public function __construct($token)
|
44 |
+
{
|
45 |
// if ($token->level !== 0) {
|
46 |
// throw new SassFunctionDefinitionNodeException('Functions can only be defined at root level', $token);
|
47 |
// }
|
68 |
* @param SassContext the context in which this node is parsed
|
69 |
* @return array the parsed node - an empty array
|
70 |
*/
|
71 |
+
public function parse($context)
|
72 |
+
{
|
73 |
$context->addFunction($this->name, $this);
|
74 |
+
|
75 |
return array();
|
76 |
}
|
77 |
|
79 |
* Returns the arguments with default values for this function
|
80 |
* @return array the arguments with default values for this function
|
81 |
*/
|
82 |
+
public function getArgs()
|
83 |
+
{
|
84 |
return $this->args;
|
85 |
}
|
86 |
|
89 |
* @param object token
|
90 |
* @return boolean true if the token represents this type of node, false if not
|
91 |
*/
|
92 |
+
public static function isa($token)
|
93 |
+
{
|
94 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
95 |
}
|
96 |
|
101 |
* @throws SassReturn - if the @return is fired then this is thrown to break early
|
102 |
* @return SassBoolean(false) - if no @return was fired, return false
|
103 |
*/
|
104 |
+
public function execute($pcontext, $provided)
|
105 |
+
{
|
106 |
list($arguments, $context) = SassScriptFunction::fill_parameters($this->args, $provided, $pcontext, $this);
|
107 |
$context->setVariables($arguments);
|
108 |
|
lib/phpsass/tree/SassIfNode.php
CHANGED
@@ -16,9 +16,10 @@
|
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.tree
|
18 |
*/
|
19 |
-
class SassIfNode extends SassNode
|
20 |
-
|
21 |
-
const
|
|
|
22 |
const IF_EXPRESSION = 1;
|
23 |
const ELSE_IF = 1;
|
24 |
const ELSE_EXPRESSION = 2;
|
@@ -37,13 +38,13 @@ class SassIfNode extends SassNode {
|
|
37 |
* @param boolean true for an "if" node, false for an "else if | else" node
|
38 |
* @return SassIfNode
|
39 |
*/
|
40 |
-
public function __construct($token, $if=true)
|
|
|
41 |
parent::__construct($token);
|
42 |
if ($if) {
|
43 |
preg_match(self::MATCH_IF, $token->source, $matches);
|
44 |
$this->expression = $matches[SassIfNode::IF_EXPRESSION];
|
45 |
-
}
|
46 |
-
else {
|
47 |
preg_match(self::MATCH_ELSE, $token->source, $matches);
|
48 |
$this->expression = (sizeof($matches)==1 ? null : $matches[SassIfNode::ELSE_EXPRESSION]);
|
49 |
}
|
@@ -54,15 +55,16 @@ class SassIfNode extends SassNode {
|
|
54 |
* @param SassIfNode "else" statement node to add
|
55 |
* @return SassIfNode this node
|
56 |
*/
|
57 |
-
public function addElse($node)
|
|
|
58 |
if (is_null($this->else)) {
|
59 |
$node->parent = $this;
|
60 |
$node->root = $this->root;
|
61 |
$this->else = $node;
|
62 |
-
}
|
63 |
-
else {
|
64 |
$this->else->addElse($node);
|
65 |
}
|
|
|
66 |
return $this;
|
67 |
}
|
68 |
|
@@ -71,16 +73,16 @@ class SassIfNode extends SassNode {
|
|
71 |
* @param SassContext the context in which this node is parsed
|
72 |
* @return array parsed child nodes
|
73 |
*/
|
74 |
-
public function parse($context)
|
|
|
75 |
if ($this->isElse() || $this->evaluate($this->expression, $context)->toBoolean()) {
|
76 |
$children = $this->parseChildren($context);
|
77 |
-
}
|
78 |
-
elseif (!empty($this->else)) {
|
79 |
$children = $this->else->parse($context);
|
80 |
-
}
|
81 |
-
else {
|
82 |
$children = array();
|
83 |
}
|
|
|
84 |
return $children;
|
85 |
}
|
86 |
|
@@ -89,7 +91,8 @@ class SassIfNode extends SassNode {
|
|
89 |
* @return true if this node is an "else" node, false if this node is an "if"
|
90 |
* or "else if" node
|
91 |
*/
|
92 |
-
private function isElse()
|
|
|
93 |
return ($this->expression=='');
|
94 |
}
|
95 |
-
}
|
16 |
* @package PHamlP
|
17 |
* @subpackage Sass.tree
|
18 |
*/
|
19 |
+
class SassIfNode extends SassNode
|
20 |
+
{
|
21 |
+
const MATCH_IF = '/^@if\s*(.+)$/i';
|
22 |
+
const MATCH_ELSE = '/@else(\s*if\s*(.+))?/i';
|
23 |
const IF_EXPRESSION = 1;
|
24 |
const ELSE_IF = 1;
|
25 |
const ELSE_EXPRESSION = 2;
|
38 |
* @param boolean true for an "if" node, false for an "else if | else" node
|
39 |
* @return SassIfNode
|
40 |
*/
|
41 |
+
public function __construct($token, $if=true)
|
42 |
+
{
|
43 |
parent::__construct($token);
|
44 |
if ($if) {
|
45 |
preg_match(self::MATCH_IF, $token->source, $matches);
|
46 |
$this->expression = $matches[SassIfNode::IF_EXPRESSION];
|
47 |
+
} else {
|
|
|
48 |
preg_match(self::MATCH_ELSE, $token->source, $matches);
|
49 |
$this->expression = (sizeof($matches)==1 ? null : $matches[SassIfNode::ELSE_EXPRESSION]);
|
50 |
}
|
55 |
* @param SassIfNode "else" statement node to add
|
56 |
* @return SassIfNode this node
|
57 |
*/
|
58 |
+
public function addElse($node)
|
59 |
+
{
|
60 |
if (is_null($this->else)) {
|
61 |
$node->parent = $this;
|
62 |
$node->root = $this->root;
|
63 |
$this->else = $node;
|
64 |
+
} else {
|
|
|
65 |
$this->else->addElse($node);
|
66 |
}
|
67 |
+
|
68 |
return $this;
|
69 |
}
|
70 |
|
73 |
* @param SassContext the context in which this node is parsed
|
74 |
* @return array parsed child nodes
|
75 |
*/
|
76 |
+
public function parse($context)
|
77 |
+
{
|
78 |
if ($this->isElse() || $this->evaluate($this->expression, $context)->toBoolean()) {
|
79 |
$children = $this->parseChildren($context);
|
80 |
+
} elseif (!empty($this->else)) {
|
|
|
81 |
$children = $this->else->parse($context);
|
82 |
+
} else {
|
|
|
83 |
$children = array();
|
84 |
}
|
85 |
+
|
86 |
return $children;
|
87 |
}
|
88 |
|
91 |
* @return true if this node is an "else" node, false if this node is an "if"
|
92 |
* or "else if" node
|
93 |
*/
|
94 |
+
private function isElse()
|
95 |
+
{
|
96 |
return ($this->expression=='');
|
97 |
}
|
98 |
+
}
|
lib/phpsass/tree/SassImportNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassImportNode extends SassNode
|
|
|
19 |
const IDENTIFIER = '@';
|
20 |
const MATCH = '/^@import\s+(.+)/i';
|
21 |
const MATCH_CSS = '/^((url)\((.+)\)|.+" \w+|http|.+\.css$)/im';
|
@@ -31,7 +32,8 @@ class SassImportNode extends SassNode {
|
|
31 |
* @param object source token
|
32 |
* @return SassImportNode
|
33 |
*/
|
34 |
-
public function __construct($token, $parent)
|
|
|
35 |
parent::__construct($token);
|
36 |
$this->parent = $parent;
|
37 |
preg_match(self::MATCH, $token->source, $matches);
|
@@ -48,7 +50,8 @@ class SassImportNode extends SassNode {
|
|
48 |
* @param SassContext the context in which this node is parsed
|
49 |
* @return array the parsed node
|
50 |
*/
|
51 |
-
public function parse($context)
|
|
|
52 |
$imported = array();
|
53 |
foreach ($this->files as $file) {
|
54 |
if (preg_match(self::MATCH_CSS, $file, $matches)) {
|
@@ -57,6 +60,7 @@ class SassImportNode extends SassNode {
|
|
57 |
} else {
|
58 |
$file = "url('$file')";
|
59 |
}
|
|
|
60 |
return array(new SassString("@import $file;"), new SassString("\n"));
|
61 |
}
|
62 |
$file = trim($file, '\'"');
|
@@ -78,11 +82,10 @@ class SassImportNode extends SassNode {
|
|
78 |
foreach ($files as $subfile) {
|
79 |
if (preg_match(self::MATCH_CSS, $subfile)) {
|
80 |
$tree->addChild(new SassString("@import url('$subfile');"));
|
81 |
-
}
|
82 |
-
else {
|
83 |
$this->parser->filename = $subfile;
|
84 |
$subtree = SassFile::get_tree($subfile, $this->parser);
|
85 |
-
foreach($subtree->getChildren() as $child) {
|
86 |
$tree->addChild($child);
|
87 |
}
|
88 |
}
|
@@ -100,6 +103,7 @@ class SassImportNode extends SassNode {
|
|
100 |
}
|
101 |
}
|
102 |
}
|
|
|
103 |
return $imported;
|
104 |
}
|
105 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassImportNode extends SassNode
|
19 |
+
{
|
20 |
const IDENTIFIER = '@';
|
21 |
const MATCH = '/^@import\s+(.+)/i';
|
22 |
const MATCH_CSS = '/^((url)\((.+)\)|.+" \w+|http|.+\.css$)/im';
|
32 |
* @param object source token
|
33 |
* @return SassImportNode
|
34 |
*/
|
35 |
+
public function __construct($token, $parent)
|
36 |
+
{
|
37 |
parent::__construct($token);
|
38 |
$this->parent = $parent;
|
39 |
preg_match(self::MATCH, $token->source, $matches);
|
50 |
* @param SassContext the context in which this node is parsed
|
51 |
* @return array the parsed node
|
52 |
*/
|
53 |
+
public function parse($context)
|
54 |
+
{
|
55 |
$imported = array();
|
56 |
foreach ($this->files as $file) {
|
57 |
if (preg_match(self::MATCH_CSS, $file, $matches)) {
|
60 |
} else {
|
61 |
$file = "url('$file')";
|
62 |
}
|
63 |
+
|
64 |
return array(new SassString("@import $file;"), new SassString("\n"));
|
65 |
}
|
66 |
$file = trim($file, '\'"');
|
82 |
foreach ($files as $subfile) {
|
83 |
if (preg_match(self::MATCH_CSS, $subfile)) {
|
84 |
$tree->addChild(new SassString("@import url('$subfile');"));
|
85 |
+
} else {
|
|
|
86 |
$this->parser->filename = $subfile;
|
87 |
$subtree = SassFile::get_tree($subfile, $this->parser);
|
88 |
+
foreach ($subtree->getChildren() as $child) {
|
89 |
$tree->addChild($child);
|
90 |
}
|
91 |
}
|
103 |
}
|
104 |
}
|
105 |
}
|
106 |
+
|
107 |
return $imported;
|
108 |
}
|
109 |
}
|
lib/phpsass/tree/SassMediaNode.php
CHANGED
@@ -15,12 +15,12 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassMediaNode extends SassNode
|
|
|
19 |
const IDENTIFIER = '@';
|
20 |
const MATCH = '/^@(media)\s+(.+?)\s*;?$/';
|
21 |
const MEDIA = 1;
|
22 |
|
23 |
-
|
24 |
public $token;
|
25 |
|
26 |
/**
|
@@ -47,7 +47,8 @@ class SassMediaNode extends SassNode {
|
|
47 |
* @param array parameters for the message
|
48 |
* @return SassMediaNode
|
49 |
*/
|
50 |
-
public function __construct($token)
|
|
|
51 |
parent::__construct($token);
|
52 |
|
53 |
preg_match(self::MATCH, $token->source, $matches);
|
@@ -60,7 +61,8 @@ class SassMediaNode extends SassNode {
|
|
60 |
* This raises an error.
|
61 |
* @return array An empty array
|
62 |
*/
|
63 |
-
public function parse($context)
|
|
|
64 |
// If we are in a loop, function or mixin then the parent isn't what should
|
65 |
// go inside the media node. Walk up the parent tree to find the rule node
|
66 |
// to put inside the media node or the root node if the media node should be
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassMediaNode extends SassNode
|
19 |
+
{
|
20 |
const IDENTIFIER = '@';
|
21 |
const MATCH = '/^@(media)\s+(.+?)\s*;?$/';
|
22 |
const MEDIA = 1;
|
23 |
|
|
|
24 |
public $token;
|
25 |
|
26 |
/**
|
47 |
* @param array parameters for the message
|
48 |
* @return SassMediaNode
|
49 |
*/
|
50 |
+
public function __construct($token)
|
51 |
+
{
|
52 |
parent::__construct($token);
|
53 |
|
54 |
preg_match(self::MATCH, $token->source, $matches);
|
61 |
* This raises an error.
|
62 |
* @return array An empty array
|
63 |
*/
|
64 |
+
public function parse($context)
|
65 |
+
{
|
66 |
// If we are in a loop, function or mixin then the parent isn't what should
|
67 |
// go inside the media node. Walk up the parent tree to find the rule node
|
68 |
// to put inside the media node or the root node if the media node should be
|
lib/phpsass/tree/SassMixinDefinitionNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassMixinDefinitionNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = '=';
|
20 |
const MATCH = '/^(=|@mixin\s+)([-\w]+)\s*(?:\((.*?)\))?\s*$/im';
|
21 |
const IDENTIFIER = 1;
|
@@ -37,7 +38,8 @@ class SassMixinDefinitionNode extends SassNode {
|
|
37 |
* @param object source token
|
38 |
* @return SassMixinDefinitionNode
|
39 |
*/
|
40 |
-
public function __construct($token)
|
|
|
41 |
preg_match(self::MATCH, $token->source, $matches);
|
42 |
parent::__construct($token);
|
43 |
if (empty($matches)) {
|
@@ -55,8 +57,10 @@ class SassMixinDefinitionNode extends SassNode {
|
|
55 |
* @param SassContext the context in which this node is parsed
|
56 |
* @return array the parsed node - an empty array
|
57 |
*/
|
58 |
-
public function parse($context)
|
|
|
59 |
$context->addMixin($this->name, $this);
|
|
|
60 |
return array();
|
61 |
}
|
62 |
|
@@ -64,7 +68,8 @@ class SassMixinDefinitionNode extends SassNode {
|
|
64 |
* Returns the arguments with default values for this mixin
|
65 |
* @return array the arguments with default values for this mixin
|
66 |
*/
|
67 |
-
public function getArgs()
|
|
|
68 |
return $this->args;
|
69 |
}
|
70 |
|
@@ -73,7 +78,8 @@ class SassMixinDefinitionNode extends SassNode {
|
|
73 |
* @param object token
|
74 |
* @return boolean true if the token represents this type of node, false if not
|
75 |
*/
|
76 |
-
public static function isa($token)
|
|
|
77 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
78 |
}
|
79 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassMixinDefinitionNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = '=';
|
21 |
const MATCH = '/^(=|@mixin\s+)([-\w]+)\s*(?:\((.*?)\))?\s*$/im';
|
22 |
const IDENTIFIER = 1;
|
38 |
* @param object source token
|
39 |
* @return SassMixinDefinitionNode
|
40 |
*/
|
41 |
+
public function __construct($token)
|
42 |
+
{
|
43 |
preg_match(self::MATCH, $token->source, $matches);
|
44 |
parent::__construct($token);
|
45 |
if (empty($matches)) {
|
57 |
* @param SassContext the context in which this node is parsed
|
58 |
* @return array the parsed node - an empty array
|
59 |
*/
|
60 |
+
public function parse($context)
|
61 |
+
{
|
62 |
$context->addMixin($this->name, $this);
|
63 |
+
|
64 |
return array();
|
65 |
}
|
66 |
|
68 |
* Returns the arguments with default values for this mixin
|
69 |
* @return array the arguments with default values for this mixin
|
70 |
*/
|
71 |
+
public function getArgs()
|
72 |
+
{
|
73 |
return $this->args;
|
74 |
}
|
75 |
|
78 |
* @param object token
|
79 |
* @return boolean true if the token represents this type of node, false if not
|
80 |
*/
|
81 |
+
public static function isa($token)
|
82 |
+
{
|
83 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
84 |
}
|
85 |
}
|
lib/phpsass/tree/SassMixinNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassMixinNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = '+';
|
20 |
const MATCH = '/^(\+|@include\s+)([a-z0-9_-]+)\s*(?:\((.*?)\))?\s*$/i';
|
21 |
const IDENTIFIER = 1;
|
@@ -36,7 +37,8 @@ class SassMixinNode extends SassNode {
|
|
36 |
* @param object source token
|
37 |
* @return SassMixinNode
|
38 |
*/
|
39 |
-
public function __construct($token)
|
|
|
40 |
parent::__construct($token);
|
41 |
preg_match(self::MATCH, $token->source, $matches);
|
42 |
|
@@ -56,7 +58,8 @@ class SassMixinNode extends SassNode {
|
|
56 |
* @param SassContext the context in which this node is parsed
|
57 |
* @return array the parsed node
|
58 |
*/
|
59 |
-
public function parse($pcontext)
|
|
|
60 |
$mixin = $pcontext->getMixin($this->name);
|
61 |
$context = new SassContext($pcontext);
|
62 |
$context->content = $this->children;
|
@@ -83,7 +86,8 @@ class SassMixinNode extends SassNode {
|
|
83 |
* @param object token
|
84 |
* @return boolean true if the token represents this type of node, false if not
|
85 |
*/
|
86 |
-
public static function isa($token)
|
|
|
87 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
88 |
}
|
89 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassMixinNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = '+';
|
21 |
const MATCH = '/^(\+|@include\s+)([a-z0-9_-]+)\s*(?:\((.*?)\))?\s*$/i';
|
22 |
const IDENTIFIER = 1;
|
37 |
* @param object source token
|
38 |
* @return SassMixinNode
|
39 |
*/
|
40 |
+
public function __construct($token)
|
41 |
+
{
|
42 |
parent::__construct($token);
|
43 |
preg_match(self::MATCH, $token->source, $matches);
|
44 |
|
58 |
* @param SassContext the context in which this node is parsed
|
59 |
* @return array the parsed node
|
60 |
*/
|
61 |
+
public function parse($pcontext)
|
62 |
+
{
|
63 |
$mixin = $pcontext->getMixin($this->name);
|
64 |
$context = new SassContext($pcontext);
|
65 |
$context->content = $this->children;
|
86 |
* @param object token
|
87 |
* @return boolean true if the token represents this type of node, false if not
|
88 |
*/
|
89 |
+
public static function isa($token)
|
90 |
+
{
|
91 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
92 |
}
|
93 |
}
|
lib/phpsass/tree/SassNode.php
CHANGED
@@ -9,30 +9,30 @@
|
|
9 |
* @subpackage Sass.tree
|
10 |
*/
|
11 |
|
12 |
-
require_once
|
13 |
-
require_once
|
14 |
-
require_once
|
15 |
-
require_once
|
16 |
-
require_once
|
17 |
-
require_once
|
18 |
-
require_once
|
19 |
-
require_once
|
20 |
-
require_once
|
21 |
-
require_once
|
22 |
-
require_once
|
23 |
-
require_once
|
24 |
-
require_once
|
25 |
-
require_once
|
26 |
-
require_once
|
27 |
-
require_once
|
28 |
-
require_once
|
29 |
-
require_once
|
30 |
-
|
31 |
-
require_once
|
32 |
-
require_once
|
33 |
-
require_once
|
34 |
-
require_once
|
35 |
-
require_once
|
36 |
|
37 |
/**
|
38 |
* SassNode class.
|
@@ -40,7 +40,8 @@ require_once('SassMediaNode.php');
|
|
40 |
* @package PHamlP
|
41 |
* @subpackage Sass.tree
|
42 |
*/
|
43 |
-
class SassNode
|
|
|
44 |
/**
|
45 |
* @var SassNode parent of this node
|
46 |
*/
|
@@ -63,7 +64,8 @@ class SassNode {
|
|
63 |
* @param object source token
|
64 |
* @return SassNode
|
65 |
*/
|
66 |
-
public function __construct($token)
|
|
|
67 |
$this->token = $token;
|
68 |
}
|
69 |
|
@@ -72,7 +74,8 @@ class SassNode {
|
|
72 |
* @param string name of property to get
|
73 |
* @return mixed return value of getter function
|
74 |
*/
|
75 |
-
public function __get($name)
|
|
|
76 |
$getter = 'get' . ucfirst($name);
|
77 |
if (method_exists($this, $getter)) {
|
78 |
return $this->$getter();
|
@@ -86,10 +89,12 @@ class SassNode {
|
|
86 |
* @return mixed value of property
|
87 |
* @return SassNode this node
|
88 |
*/
|
89 |
-
public function __set($name, $value)
|
|
|
90 |
$setter = 'set' . ucfirst($name);
|
91 |
if (method_exists($this, $setter)) {
|
92 |
$this->$setter($value);
|
|
|
93 |
return $this;
|
94 |
}
|
95 |
throw new SassNodeException('No setter function for ' . $name, $this);
|
@@ -99,7 +104,8 @@ class SassNode {
|
|
99 |
* Resets children when cloned
|
100 |
* @see parse
|
101 |
*/
|
102 |
-
public function __clone()
|
|
|
103 |
$this->children = array();
|
104 |
}
|
105 |
|
@@ -107,7 +113,8 @@ class SassNode {
|
|
107 |
* Return a value indicating if this node has a parent
|
108 |
* @return array the node's parent
|
109 |
*/
|
110 |
-
public function hasParent()
|
|
|
111 |
return !empty($this->parent);
|
112 |
}
|
113 |
|
@@ -115,7 +122,8 @@ class SassNode {
|
|
115 |
* Returns the node's parent
|
116 |
* @return array the node's parent
|
117 |
*/
|
118 |
-
public function getParent()
|
|
|
119 |
return $this->parent;
|
120 |
}
|
121 |
|
@@ -123,14 +131,14 @@ class SassNode {
|
|
123 |
* Adds a child to this node.
|
124 |
* @return SassNode the child to add
|
125 |
*/
|
126 |
-
public function addChild($child)
|
|
|
127 |
if ($child instanceof SassElseNode) {
|
128 |
if (!$this->lastChild instanceof SassIfNode) {
|
129 |
throw new SassException('@else(if) directive must come after @(else)if', $child);
|
130 |
}
|
131 |
$this->lastChild->addElse($child);
|
132 |
-
}
|
133 |
-
else {
|
134 |
$this->children[] = $child;
|
135 |
$child->parent = $this;
|
136 |
$child->root = $this->root;
|
@@ -145,7 +153,8 @@ class SassNode {
|
|
145 |
* Returns a value indicating if this node has children
|
146 |
* @return boolean true if the node has children, false if not
|
147 |
*/
|
148 |
-
public function hasChildren()
|
|
|
149 |
return !empty($this->children);
|
150 |
}
|
151 |
|
@@ -153,7 +162,8 @@ class SassNode {
|
|
153 |
* Returns the node's children
|
154 |
* @return array the node's children
|
155 |
*/
|
156 |
-
public function getChildren()
|
|
|
157 |
return $this->children;
|
158 |
}
|
159 |
|
@@ -163,7 +173,8 @@ class SassNode {
|
|
163 |
* level than the passed node if is a child of it.
|
164 |
* @return boolean true if the node is a child of the passed node, false if not
|
165 |
*/
|
166 |
-
public function isChildOf($node)
|
|
|
167 |
return $this->level > $node->level;
|
168 |
}
|
169 |
|
@@ -171,7 +182,8 @@ class SassNode {
|
|
171 |
* Returns the last child node of this node.
|
172 |
* @return SassNode the last child node of this node
|
173 |
*/
|
174 |
-
public function getLastChild()
|
|
|
175 |
return $this->children[count($this->children) - 1];
|
176 |
}
|
177 |
|
@@ -179,7 +191,8 @@ class SassNode {
|
|
179 |
* Returns the level of this node.
|
180 |
* @return integer the level of this node
|
181 |
*/
|
182 |
-
public function getLevel()
|
|
|
183 |
return $this->token->level;
|
184 |
}
|
185 |
|
@@ -187,7 +200,8 @@ class SassNode {
|
|
187 |
* Returns the source for this node
|
188 |
* @return string the source for this node
|
189 |
*/
|
190 |
-
public function getSource()
|
|
|
191 |
return $this->token->source;
|
192 |
}
|
193 |
|
@@ -195,7 +209,8 @@ class SassNode {
|
|
195 |
* Returns the debug_info option setting for this node
|
196 |
* @return boolean the debug_info option setting for this node
|
197 |
*/
|
198 |
-
public function getDebug_info()
|
|
|
199 |
return $this->parser->debug_info;
|
200 |
}
|
201 |
|
@@ -203,7 +218,8 @@ class SassNode {
|
|
203 |
* Returns the line number for this node
|
204 |
* @return string the line number for this node
|
205 |
*/
|
206 |
-
public function getLine()
|
|
|
207 |
return $this->token->line;
|
208 |
}
|
209 |
|
@@ -211,7 +227,8 @@ class SassNode {
|
|
211 |
* Returns the line_numbers option setting for this node
|
212 |
* @return boolean the line_numbers option setting for this node
|
213 |
*/
|
214 |
-
public function getLine_numbers()
|
|
|
215 |
return $this->parser->line_numbers;
|
216 |
}
|
217 |
|
@@ -219,7 +236,8 @@ class SassNode {
|
|
219 |
* Returns the filename for this node
|
220 |
* @return string the filename for this node
|
221 |
*/
|
222 |
-
public function getFilename()
|
|
|
223 |
return $this->token->filename;
|
224 |
}
|
225 |
|
@@ -227,7 +245,8 @@ class SassNode {
|
|
227 |
* Returns the Sass parser.
|
228 |
* @return SassParser the Sass parser
|
229 |
*/
|
230 |
-
public function getParser()
|
|
|
231 |
return $this->root->parser;
|
232 |
}
|
233 |
|
@@ -235,7 +254,8 @@ class SassNode {
|
|
235 |
* Returns the property syntax being used.
|
236 |
* @return string the property syntax being used
|
237 |
*/
|
238 |
-
public function getPropertySyntax()
|
|
|
239 |
return $this->root->parser->propertySyntax;
|
240 |
}
|
241 |
|
@@ -243,7 +263,8 @@ class SassNode {
|
|
243 |
* Returns the SassScript parser.
|
244 |
* @return SassScriptParser the SassScript parser
|
245 |
*/
|
246 |
-
public function getScript()
|
|
|
247 |
return $this->root->script;
|
248 |
}
|
249 |
|
@@ -251,7 +272,8 @@ class SassNode {
|
|
251 |
* Returns the renderer.
|
252 |
* @return SassRenderer the renderer
|
253 |
*/
|
254 |
-
public function getRenderer()
|
|
|
255 |
return $this->root->renderer;
|
256 |
}
|
257 |
|
@@ -259,7 +281,8 @@ class SassNode {
|
|
259 |
* Returns the render style of the document tree.
|
260 |
* @return string the render style of the document tree
|
261 |
*/
|
262 |
-
public function getStyle()
|
|
|
263 |
return $this->root->parser->style;
|
264 |
}
|
265 |
|
@@ -267,7 +290,8 @@ class SassNode {
|
|
267 |
* Returns a value indicating whether this node is in a directive
|
268 |
* @param boolean true if the node is in a directive, false if not
|
269 |
*/
|
270 |
-
public function inDirective()
|
|
|
271 |
return $this->parent instanceof SassDirectiveNode ||
|
272 |
$this->parent instanceof SassDirectiveNode;
|
273 |
}
|
@@ -276,7 +300,8 @@ class SassNode {
|
|
276 |
* Returns a value indicating whether this node is in a SassScript directive
|
277 |
* @param boolean true if this node is in a SassScript directive, false if not
|
278 |
*/
|
279 |
-
public function inSassScriptDirective()
|
|
|
280 |
return $this->parent instanceof SassEachNode ||
|
281 |
$this->parent->parent instanceof SassEachNode ||
|
282 |
$this->parent instanceof SassForNode ||
|
@@ -293,8 +318,10 @@ class SassNode {
|
|
293 |
* @param SassContext the context in which the expression is evaluated
|
294 |
* @return SassLiteral value of parsed expression
|
295 |
*/
|
296 |
-
public function evaluate($expression, $context, $x=null)
|
|
|
297 |
$context->node = $this;
|
|
|
298 |
return $this->script->evaluate($expression, $context, $x);
|
299 |
}
|
300 |
|
@@ -304,8 +331,10 @@ class SassNode {
|
|
304 |
* @param SassContext the context in which the string is interpolated
|
305 |
* @return string the interpolated text
|
306 |
*/
|
307 |
-
public function interpolate($expression, $context)
|
|
|
308 |
$context->node = $this;
|
|
|
309 |
return $this->script->interpolate($expression, $context);
|
310 |
}
|
311 |
|
@@ -314,7 +343,8 @@ class SassNode {
|
|
314 |
* @param string warning message
|
315 |
* @param array line
|
316 |
*/
|
317 |
-
public function addWarning($message)
|
|
|
318 |
$warning = new SassDebugNode($this->token, $message);
|
319 |
$this->addChild($warning);
|
320 |
}
|
@@ -324,7 +354,8 @@ class SassNode {
|
|
324 |
* @param SassContext the context in which the children are parsed
|
325 |
* @return array the parsed child nodes
|
326 |
*/
|
327 |
-
public function parseChildren($context)
|
|
|
328 |
$children = array();
|
329 |
foreach ($this->children as $child) {
|
330 |
# child could be a SassLiteral /or/ SassNode
|
@@ -335,6 +366,7 @@ class SassNode {
|
|
335 |
}
|
336 |
$children = array_merge($children, $kid);
|
337 |
}
|
|
|
338 |
return $children;
|
339 |
}
|
340 |
|
@@ -343,7 +375,8 @@ class SassNode {
|
|
343 |
* @param object token
|
344 |
* @return boolean true if the token represents this type of node, false if not
|
345 |
*/
|
346 |
-
public static function isa($token)
|
|
|
347 |
throw new SassNodeException('Child classes must override this method');
|
348 |
}
|
349 |
|
9 |
* @subpackage Sass.tree
|
10 |
*/
|
11 |
|
12 |
+
require_once 'SassContext.php';
|
13 |
+
require_once 'SassCommentNode.php';
|
14 |
+
require_once 'SassDebugNode.php';
|
15 |
+
require_once 'SassDirectiveNode.php';
|
16 |
+
require_once 'SassImportNode.php';
|
17 |
+
require_once 'SassMixinNode.php';
|
18 |
+
require_once 'SassMixinDefinitionNode.php';
|
19 |
+
require_once 'SassPropertyNode.php';
|
20 |
+
require_once 'SassRootNode.php';
|
21 |
+
require_once 'SassRuleNode.php';
|
22 |
+
require_once 'SassVariableNode.php';
|
23 |
+
require_once 'SassExtendNode.php';
|
24 |
+
require_once 'SassEachNode.php';
|
25 |
+
require_once 'SassForNode.php';
|
26 |
+
require_once 'SassIfNode.php';
|
27 |
+
require_once 'SassElseNode.php';
|
28 |
+
require_once 'SassWhileNode.php';
|
29 |
+
require_once 'SassNodeExceptions.php';
|
30 |
+
|
31 |
+
require_once 'SassFunctionDefinitionNode.php';
|
32 |
+
require_once 'SassReturnNode.php';
|
33 |
+
require_once 'SassContentNode.php';
|
34 |
+
require_once 'SassWarnNode.php';
|
35 |
+
require_once 'SassMediaNode.php';
|
36 |
|
37 |
/**
|
38 |
* SassNode class.
|
40 |
* @package PHamlP
|
41 |
* @subpackage Sass.tree
|
42 |
*/
|
43 |
+
class SassNode
|
44 |
+
{
|
45 |
/**
|
46 |
* @var SassNode parent of this node
|
47 |
*/
|
64 |
* @param object source token
|
65 |
* @return SassNode
|
66 |
*/
|
67 |
+
public function __construct($token)
|
68 |
+
{
|
69 |
$this->token = $token;
|
70 |
}
|
71 |
|
74 |
* @param string name of property to get
|
75 |
* @return mixed return value of getter function
|
76 |
*/
|
77 |
+
public function __get($name)
|
78 |
+
{
|
79 |
$getter = 'get' . ucfirst($name);
|
80 |
if (method_exists($this, $getter)) {
|
81 |
return $this->$getter();
|
89 |
* @return mixed value of property
|
90 |
* @return SassNode this node
|
91 |
*/
|
92 |
+
public function __set($name, $value)
|
93 |
+
{
|
94 |
$setter = 'set' . ucfirst($name);
|
95 |
if (method_exists($this, $setter)) {
|
96 |
$this->$setter($value);
|
97 |
+
|
98 |
return $this;
|
99 |
}
|
100 |
throw new SassNodeException('No setter function for ' . $name, $this);
|
104 |
* Resets children when cloned
|
105 |
* @see parse
|
106 |
*/
|
107 |
+
public function __clone()
|
108 |
+
{
|
109 |
$this->children = array();
|
110 |
}
|
111 |
|
113 |
* Return a value indicating if this node has a parent
|
114 |
* @return array the node's parent
|
115 |
*/
|
116 |
+
public function hasParent()
|
117 |
+
{
|
118 |
return !empty($this->parent);
|
119 |
}
|
120 |
|
122 |
* Returns the node's parent
|
123 |
* @return array the node's parent
|
124 |
*/
|
125 |
+
public function getParent()
|
126 |
+
{
|
127 |
return $this->parent;
|
128 |
}
|
129 |
|
131 |
* Adds a child to this node.
|
132 |
* @return SassNode the child to add
|
133 |
*/
|
134 |
+
public function addChild($child)
|
135 |
+
{
|
136 |
if ($child instanceof SassElseNode) {
|
137 |
if (!$this->lastChild instanceof SassIfNode) {
|
138 |
throw new SassException('@else(if) directive must come after @(else)if', $child);
|
139 |
}
|
140 |
$this->lastChild->addElse($child);
|
141 |
+
} else {
|
|
|
142 |
$this->children[] = $child;
|
143 |
$child->parent = $this;
|
144 |
$child->root = $this->root;
|
153 |
* Returns a value indicating if this node has children
|
154 |
* @return boolean true if the node has children, false if not
|
155 |
*/
|
156 |
+
public function hasChildren()
|
157 |
+
{
|
158 |
return !empty($this->children);
|
159 |
}
|
160 |
|
162 |
* Returns the node's children
|
163 |
* @return array the node's children
|
164 |
*/
|
165 |
+
public function getChildren()
|
166 |
+
{
|
167 |
return $this->children;
|
168 |
}
|
169 |
|
173 |
* level than the passed node if is a child of it.
|
174 |
* @return boolean true if the node is a child of the passed node, false if not
|
175 |
*/
|
176 |
+
public function isChildOf($node)
|
177 |
+
{
|
178 |
return $this->level > $node->level;
|
179 |
}
|
180 |
|
182 |
* Returns the last child node of this node.
|
183 |
* @return SassNode the last child node of this node
|
184 |
*/
|
185 |
+
public function getLastChild()
|
186 |
+
{
|
187 |
return $this->children[count($this->children) - 1];
|
188 |
}
|
189 |
|
191 |
* Returns the level of this node.
|
192 |
* @return integer the level of this node
|
193 |
*/
|
194 |
+
public function getLevel()
|
195 |
+
{
|
196 |
return $this->token->level;
|
197 |
}
|
198 |
|
200 |
* Returns the source for this node
|
201 |
* @return string the source for this node
|
202 |
*/
|
203 |
+
public function getSource()
|
204 |
+
{
|
205 |
return $this->token->source;
|
206 |
}
|
207 |
|
209 |
* Returns the debug_info option setting for this node
|
210 |
* @return boolean the debug_info option setting for this node
|
211 |
*/
|
212 |
+
public function getDebug_info()
|
213 |
+
{
|
214 |
return $this->parser->debug_info;
|
215 |
}
|
216 |
|
218 |
* Returns the line number for this node
|
219 |
* @return string the line number for this node
|
220 |
*/
|
221 |
+
public function getLine()
|
222 |
+
{
|
223 |
return $this->token->line;
|
224 |
}
|
225 |
|
227 |
* Returns the line_numbers option setting for this node
|
228 |
* @return boolean the line_numbers option setting for this node
|
229 |
*/
|
230 |
+
public function getLine_numbers()
|
231 |
+
{
|
232 |
return $this->parser->line_numbers;
|
233 |
}
|
234 |
|
236 |
* Returns the filename for this node
|
237 |
* @return string the filename for this node
|
238 |
*/
|
239 |
+
public function getFilename()
|
240 |
+
{
|
241 |
return $this->token->filename;
|
242 |
}
|
243 |
|
245 |
* Returns the Sass parser.
|
246 |
* @return SassParser the Sass parser
|
247 |
*/
|
248 |
+
public function getParser()
|
249 |
+
{
|
250 |
return $this->root->parser;
|
251 |
}
|
252 |
|
254 |
* Returns the property syntax being used.
|
255 |
* @return string the property syntax being used
|
256 |
*/
|
257 |
+
public function getPropertySyntax()
|
258 |
+
{
|
259 |
return $this->root->parser->propertySyntax;
|
260 |
}
|
261 |
|
263 |
* Returns the SassScript parser.
|
264 |
* @return SassScriptParser the SassScript parser
|
265 |
*/
|
266 |
+
public function getScript()
|
267 |
+
{
|
268 |
return $this->root->script;
|
269 |
}
|
270 |
|
272 |
* Returns the renderer.
|
273 |
* @return SassRenderer the renderer
|
274 |
*/
|
275 |
+
public function getRenderer()
|
276 |
+
{
|
277 |
return $this->root->renderer;
|
278 |
}
|
279 |
|
281 |
* Returns the render style of the document tree.
|
282 |
* @return string the render style of the document tree
|
283 |
*/
|
284 |
+
public function getStyle()
|
285 |
+
{
|
286 |
return $this->root->parser->style;
|
287 |
}
|
288 |
|
290 |
* Returns a value indicating whether this node is in a directive
|
291 |
* @param boolean true if the node is in a directive, false if not
|
292 |
*/
|
293 |
+
public function inDirective()
|
294 |
+
{
|
295 |
return $this->parent instanceof SassDirectiveNode ||
|
296 |
$this->parent instanceof SassDirectiveNode;
|
297 |
}
|
300 |
* Returns a value indicating whether this node is in a SassScript directive
|
301 |
* @param boolean true if this node is in a SassScript directive, false if not
|
302 |
*/
|
303 |
+
public function inSassScriptDirective()
|
304 |
+
{
|
305 |
return $this->parent instanceof SassEachNode ||
|
306 |
$this->parent->parent instanceof SassEachNode ||
|
307 |
$this->parent instanceof SassForNode ||
|
318 |
* @param SassContext the context in which the expression is evaluated
|
319 |
* @return SassLiteral value of parsed expression
|
320 |
*/
|
321 |
+
public function evaluate($expression, $context, $x=null)
|
322 |
+
{
|
323 |
$context->node = $this;
|
324 |
+
|
325 |
return $this->script->evaluate($expression, $context, $x);
|
326 |
}
|
327 |
|
331 |
* @param SassContext the context in which the string is interpolated
|
332 |
* @return string the interpolated text
|
333 |
*/
|
334 |
+
public function interpolate($expression, $context)
|
335 |
+
{
|
336 |
$context->node = $this;
|
337 |
+
|
338 |
return $this->script->interpolate($expression, $context);
|
339 |
}
|
340 |
|
343 |
* @param string warning message
|
344 |
* @param array line
|
345 |
*/
|
346 |
+
public function addWarning($message)
|
347 |
+
{
|
348 |
$warning = new SassDebugNode($this->token, $message);
|
349 |
$this->addChild($warning);
|
350 |
}
|
354 |
* @param SassContext the context in which the children are parsed
|
355 |
* @return array the parsed child nodes
|
356 |
*/
|
357 |
+
public function parseChildren($context)
|
358 |
+
{
|
359 |
$children = array();
|
360 |
foreach ($this->children as $child) {
|
361 |
# child could be a SassLiteral /or/ SassNode
|
366 |
}
|
367 |
$children = array_merge($children, $kid);
|
368 |
}
|
369 |
+
|
370 |
return $children;
|
371 |
}
|
372 |
|
375 |
* @param object token
|
376 |
* @return boolean true if the token represents this type of node, false if not
|
377 |
*/
|
378 |
+
public static function isa($token)
|
379 |
+
{
|
380 |
throw new SassNodeException('Child classes must override this method');
|
381 |
}
|
382 |
|
lib/phpsass/tree/SassNodeExceptions.php
CHANGED
@@ -74,7 +74,6 @@ class SassForNodeException extends SassNodeException {}
|
|
74 |
*/
|
75 |
class SassFunctionDefinitionNodeException extends SassNodeException {}
|
76 |
|
77 |
-
|
78 |
/**
|
79 |
* SassIfNodeException class.
|
80 |
* @package PHamlP
|
74 |
*/
|
75 |
class SassFunctionDefinitionNodeException extends SassNodeException {}
|
76 |
|
|
|
77 |
/**
|
78 |
* SassIfNodeException class.
|
79 |
* @package PHamlP
|
lib/phpsass/tree/SassPropertyNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassPropertyNode extends SassNode
|
|
|
19 |
const MATCH_PROPERTY_SCSS = '/^([^\s=:"(\\\\:)]*)\s*(?:(= )|:)([^\:].*?)?(\s*!important.*)?$/';
|
20 |
const MATCH_PROPERTY_NEW = '/^([^\s=:"]+)\s*(?:(= )|:)([^\:].*?)?(\s*!important.*)?$/';
|
21 |
const MATCH_PROPERTY_OLD = '/^:([^\s=:]+)(?:\s*(=)\s*|\s+|$)(.*)(\s*!important.*)?/';
|
@@ -72,7 +73,6 @@ class SassPropertyNode extends SassNode {
|
|
72 |
*/
|
73 |
public $value;
|
74 |
|
75 |
-
|
76 |
/**
|
77 |
* @var boolean, wether the property is important
|
78 |
*/
|
@@ -84,14 +84,14 @@ class SassPropertyNode extends SassNode {
|
|
84 |
* @param string property syntax
|
85 |
* @return SassPropertyNode
|
86 |
*/
|
87 |
-
public function __construct($token, $syntax = 'new')
|
|
|
88 |
parent::__construct($token);
|
89 |
$matches = self::match($token, $syntax);
|
90 |
$this->name = @$matches[self::NAME];
|
91 |
if (!isset($matches[self::VALUE])) {
|
92 |
$this->value = '';
|
93 |
-
}
|
94 |
-
else {
|
95 |
$this->value = $matches[self::VALUE];
|
96 |
if ($matches[self::SCRIPT] === self::IS_SCRIPT) {
|
97 |
$this->addWarning('Setting CSS properties with "=" is deprecated; use "{name}: {value};"',
|
@@ -109,7 +109,8 @@ class SassPropertyNode extends SassNode {
|
|
109 |
* @param SassContext the context in which this node is parsed
|
110 |
* @return array the parsed node
|
111 |
*/
|
112 |
-
public function parse($context)
|
|
|
113 |
$return = array();
|
114 |
if ($this->value !== "") {
|
115 |
$node = clone $this;
|
@@ -123,6 +124,7 @@ class SassPropertyNode extends SassNode {
|
|
123 |
if ($this->children) {
|
124 |
$return = array_merge($return, $this->parseChildren($context));
|
125 |
}
|
|
|
126 |
return $return;
|
127 |
}
|
128 |
|
@@ -130,7 +132,8 @@ class SassPropertyNode extends SassNode {
|
|
130 |
* Render this node.
|
131 |
* @return string the rendered node
|
132 |
*/
|
133 |
-
public function render()
|
|
|
134 |
return $this->renderer->renderProperty($this);
|
135 |
}
|
136 |
|
@@ -138,7 +141,8 @@ class SassPropertyNode extends SassNode {
|
|
138 |
* Returns a value indicating if this node is in a namespace
|
139 |
* @return boolean true if this node is in a property namespace, false if not
|
140 |
*/
|
141 |
-
public function inNamespace()
|
|
|
142 |
$parent = $this->parent;
|
143 |
do {
|
144 |
if ($parent instanceof SassPropertyNode) {
|
@@ -146,6 +150,7 @@ class SassPropertyNode extends SassNode {
|
|
146 |
}
|
147 |
$parent = $parent->parent;
|
148 |
} while (is_object($parent));
|
|
|
149 |
return false;
|
150 |
}
|
151 |
|
@@ -153,7 +158,8 @@ class SassPropertyNode extends SassNode {
|
|
153 |
* Returns the namespace for this node
|
154 |
* @return string the namespace for this node
|
155 |
*/
|
156 |
-
public function getNamespace()
|
|
|
157 |
$namespace = array();
|
158 |
$parent = $this->parent;
|
159 |
do {
|
@@ -162,6 +168,7 @@ class SassPropertyNode extends SassNode {
|
|
162 |
}
|
163 |
$parent = $parent->parent;
|
164 |
} while (is_object($parent));
|
|
|
165 |
return join('-', array_reverse($namespace));
|
166 |
}
|
167 |
|
@@ -170,7 +177,8 @@ class SassPropertyNode extends SassNode {
|
|
170 |
* If the property is in a namespace the namespace is prepended
|
171 |
* @return string the name of this property
|
172 |
*/
|
173 |
-
public function getName()
|
|
|
174 |
return $this->name;
|
175 |
}
|
176 |
|
@@ -178,7 +186,8 @@ class SassPropertyNode extends SassNode {
|
|
178 |
* Returns the parsed value of this property.
|
179 |
* @return string the parsed value of this property
|
180 |
*/
|
181 |
-
public function getValue()
|
|
|
182 |
return $this->value;
|
183 |
}
|
184 |
|
@@ -188,11 +197,11 @@ class SassPropertyNode extends SassNode {
|
|
188 |
* @param string the property syntax being used
|
189 |
* @return boolean true if the token represents this type of node, false if not
|
190 |
*/
|
191 |
-
public static function isa($token)
|
192 |
-
|
|
|
193 |
$syntax = 'old';
|
194 |
-
}
|
195 |
-
else {
|
196 |
$syntax = $token['syntax'];
|
197 |
$token = $token['token'];
|
198 |
}
|
@@ -206,14 +215,13 @@ class SassPropertyNode extends SassNode {
|
|
206 |
if ($token->level === 0) {
|
207 |
# RL - if it's on the first level it's probably a false positive, not an error.
|
208 |
# even if it is a genuine error, no need to kill the compiler about it.
|
|
|
209 |
return false;
|
210 |
// throw new SassPropertyNodeException('Properties can not be assigned at root level', $token);
|
211 |
-
}
|
212 |
-
else {
|
213 |
return true;
|
214 |
}
|
215 |
-
}
|
216 |
-
else {
|
217 |
return false;
|
218 |
}
|
219 |
}
|
@@ -224,7 +232,8 @@ class SassPropertyNode extends SassNode {
|
|
224 |
* @param string the property syntax being used
|
225 |
* @return array matches
|
226 |
*/
|
227 |
-
public static function match($token, $syntax)
|
|
|
228 |
switch ($syntax) {
|
229 |
case 'scss':
|
230 |
preg_match(self::MATCH_PROPERTY_SCSS, $token->source, $matches);
|
@@ -241,6 +250,7 @@ class SassPropertyNode extends SassNode {
|
|
241 |
}
|
242 |
break;
|
243 |
}
|
|
|
244 |
return $matches;
|
245 |
}
|
246 |
|
@@ -255,8 +265,10 @@ class SassPropertyNode extends SassNode {
|
|
255 |
* @param string the string to test
|
256 |
* @return bool true if the string starts with a pseudo selector, false if not
|
257 |
*/
|
258 |
-
public static function isPseudoSelector($string)
|
|
|
259 |
preg_match(self::MATCH_PSUEDO_SELECTOR, $string, $matches);
|
|
|
260 |
return (isset($matches[0]) && in_array($matches[0], self::$psuedoSelectors)) ||
|
261 |
preg_match(self::MATCH_INTERPOLATION, $string) ||
|
262 |
preg_match(self::MATCH_PROPRIETARY_SELECTOR, $string);
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassPropertyNode extends SassNode
|
19 |
+
{
|
20 |
const MATCH_PROPERTY_SCSS = '/^([^\s=:"(\\\\:)]*)\s*(?:(= )|:)([^\:].*?)?(\s*!important.*)?$/';
|
21 |
const MATCH_PROPERTY_NEW = '/^([^\s=:"]+)\s*(?:(= )|:)([^\:].*?)?(\s*!important.*)?$/';
|
22 |
const MATCH_PROPERTY_OLD = '/^:([^\s=:]+)(?:\s*(=)\s*|\s+|$)(.*)(\s*!important.*)?/';
|
73 |
*/
|
74 |
public $value;
|
75 |
|
|
|
76 |
/**
|
77 |
* @var boolean, wether the property is important
|
78 |
*/
|
84 |
* @param string property syntax
|
85 |
* @return SassPropertyNode
|
86 |
*/
|
87 |
+
public function __construct($token, $syntax = 'new')
|
88 |
+
{
|
89 |
parent::__construct($token);
|
90 |
$matches = self::match($token, $syntax);
|
91 |
$this->name = @$matches[self::NAME];
|
92 |
if (!isset($matches[self::VALUE])) {
|
93 |
$this->value = '';
|
94 |
+
} else {
|
|
|
95 |
$this->value = $matches[self::VALUE];
|
96 |
if ($matches[self::SCRIPT] === self::IS_SCRIPT) {
|
97 |
$this->addWarning('Setting CSS properties with "=" is deprecated; use "{name}: {value};"',
|
109 |
* @param SassContext the context in which this node is parsed
|
110 |
* @return array the parsed node
|
111 |
*/
|
112 |
+
public function parse($context)
|
113 |
+
{
|
114 |
$return = array();
|
115 |
if ($this->value !== "") {
|
116 |
$node = clone $this;
|
124 |
if ($this->children) {
|
125 |
$return = array_merge($return, $this->parseChildren($context));
|
126 |
}
|
127 |
+
|
128 |
return $return;
|
129 |
}
|
130 |
|
132 |
* Render this node.
|
133 |
* @return string the rendered node
|
134 |
*/
|
135 |
+
public function render()
|
136 |
+
{
|
137 |
return $this->renderer->renderProperty($this);
|
138 |
}
|
139 |
|
141 |
* Returns a value indicating if this node is in a namespace
|
142 |
* @return boolean true if this node is in a property namespace, false if not
|
143 |
*/
|
144 |
+
public function inNamespace()
|
145 |
+
{
|
146 |
$parent = $this->parent;
|
147 |
do {
|
148 |
if ($parent instanceof SassPropertyNode) {
|
150 |
}
|
151 |
$parent = $parent->parent;
|
152 |
} while (is_object($parent));
|
153 |
+
|
154 |
return false;
|
155 |
}
|
156 |
|
158 |
* Returns the namespace for this node
|
159 |
* @return string the namespace for this node
|
160 |
*/
|
161 |
+
public function getNamespace()
|
162 |
+
{
|
163 |
$namespace = array();
|
164 |
$parent = $this->parent;
|
165 |
do {
|
168 |
}
|
169 |
$parent = $parent->parent;
|
170 |
} while (is_object($parent));
|
171 |
+
|
172 |
return join('-', array_reverse($namespace));
|
173 |
}
|
174 |
|
177 |
* If the property is in a namespace the namespace is prepended
|
178 |
* @return string the name of this property
|
179 |
*/
|
180 |
+
public function getName()
|
181 |
+
{
|
182 |
return $this->name;
|
183 |
}
|
184 |
|
186 |
* Returns the parsed value of this property.
|
187 |
* @return string the parsed value of this property
|
188 |
*/
|
189 |
+
public function getValue()
|
190 |
+
{
|
191 |
return $this->value;
|
192 |
}
|
193 |
|
197 |
* @param string the property syntax being used
|
198 |
* @return boolean true if the token represents this type of node, false if not
|
199 |
*/
|
200 |
+
public static function isa($token)
|
201 |
+
{
|
202 |
+
if (!is_array($token)) {
|
203 |
$syntax = 'old';
|
204 |
+
} else {
|
|
|
205 |
$syntax = $token['syntax'];
|
206 |
$token = $token['token'];
|
207 |
}
|
215 |
if ($token->level === 0) {
|
216 |
# RL - if it's on the first level it's probably a false positive, not an error.
|
217 |
# even if it is a genuine error, no need to kill the compiler about it.
|
218 |
+
|
219 |
return false;
|
220 |
// throw new SassPropertyNodeException('Properties can not be assigned at root level', $token);
|
221 |
+
} else {
|
|
|
222 |
return true;
|
223 |
}
|
224 |
+
} else {
|
|
|
225 |
return false;
|
226 |
}
|
227 |
}
|
232 |
* @param string the property syntax being used
|
233 |
* @return array matches
|
234 |
*/
|
235 |
+
public static function match($token, $syntax)
|
236 |
+
{
|
237 |
switch ($syntax) {
|
238 |
case 'scss':
|
239 |
preg_match(self::MATCH_PROPERTY_SCSS, $token->source, $matches);
|
250 |
}
|
251 |
break;
|
252 |
}
|
253 |
+
|
254 |
return $matches;
|
255 |
}
|
256 |
|
265 |
* @param string the string to test
|
266 |
* @return bool true if the string starts with a pseudo selector, false if not
|
267 |
*/
|
268 |
+
public static function isPseudoSelector($string)
|
269 |
+
{
|
270 |
preg_match(self::MATCH_PSUEDO_SELECTOR, $string, $matches);
|
271 |
+
|
272 |
return (isset($matches[0]) && in_array($matches[0], self::$psuedoSelectors)) ||
|
273 |
preg_match(self::MATCH_INTERPOLATION, $string) ||
|
274 |
preg_match(self::MATCH_PROPRIETARY_SELECTOR, $string);
|
lib/phpsass/tree/SassReturnNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassReturnNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = '+';
|
20 |
const MATCH = '/^(@return\s+)(.*)$/i';
|
21 |
const IDENTIFIER = 1;
|
@@ -31,10 +32,11 @@ class SassReturnNode extends SassNode {
|
|
31 |
* @param object source token
|
32 |
* @return SassReturnNode
|
33 |
*/
|
34 |
-
public function __construct($token)
|
|
|
35 |
parent::__construct($token);
|
36 |
preg_match(self::MATCH, $token->source, $matches);
|
37 |
-
|
38 |
if (empty($matches)) {
|
39 |
return new SassBoolean('false');
|
40 |
}
|
@@ -49,7 +51,8 @@ class SassReturnNode extends SassNode {
|
|
49 |
* @param SassContext the context in which this node is parsed
|
50 |
* @return array the parsed node
|
51 |
*/
|
52 |
-
public function parse($pcontext)
|
|
|
53 |
$return = $this;
|
54 |
$context = new SassContext($pcontext);
|
55 |
$statement = $this->statement;
|
@@ -59,7 +62,7 @@ class SassReturnNode extends SassNode {
|
|
59 |
$lexer = $script->lexer;
|
60 |
|
61 |
$result = $script->evaluate($statement, $context);
|
62 |
-
|
63 |
throw new SassReturn($result);
|
64 |
}
|
65 |
|
@@ -68,13 +71,16 @@ class SassReturnNode extends SassNode {
|
|
68 |
* @param object token
|
69 |
* @return boolean true if the token represents this type of node, false if not
|
70 |
*/
|
71 |
-
public static function isa($token)
|
|
|
72 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
73 |
}
|
74 |
}
|
75 |
|
76 |
-
class SassReturn extends Exception
|
77 |
-
|
|
|
|
|
78 |
$this->value = $value;
|
79 |
}
|
80 |
-
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassReturnNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = '+';
|
21 |
const MATCH = '/^(@return\s+)(.*)$/i';
|
22 |
const IDENTIFIER = 1;
|
32 |
* @param object source token
|
33 |
* @return SassReturnNode
|
34 |
*/
|
35 |
+
public function __construct($token)
|
36 |
+
{
|
37 |
parent::__construct($token);
|
38 |
preg_match(self::MATCH, $token->source, $matches);
|
39 |
+
|
40 |
if (empty($matches)) {
|
41 |
return new SassBoolean('false');
|
42 |
}
|
51 |
* @param SassContext the context in which this node is parsed
|
52 |
* @return array the parsed node
|
53 |
*/
|
54 |
+
public function parse($pcontext)
|
55 |
+
{
|
56 |
$return = $this;
|
57 |
$context = new SassContext($pcontext);
|
58 |
$statement = $this->statement;
|
62 |
$lexer = $script->lexer;
|
63 |
|
64 |
$result = $script->evaluate($statement, $context);
|
65 |
+
|
66 |
throw new SassReturn($result);
|
67 |
}
|
68 |
|
71 |
* @param object token
|
72 |
* @return boolean true if the token represents this type of node, false if not
|
73 |
*/
|
74 |
+
public static function isa($token)
|
75 |
+
{
|
76 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
77 |
}
|
78 |
}
|
79 |
|
80 |
+
class SassReturn extends Exception
|
81 |
+
{
|
82 |
+
public function __construct($value)
|
83 |
+
{
|
84 |
$this->value = $value;
|
85 |
}
|
86 |
+
}
|
lib/phpsass/tree/SassRootNode.php
CHANGED
@@ -18,7 +18,8 @@ require_once(dirname(__FILE__).'/../renderers/SassRenderer.php');
|
|
18 |
* @package PHamlP
|
19 |
* @subpackage Sass.tree
|
20 |
*/
|
21 |
-
class SassRootNode extends SassNode
|
|
|
22 |
/**
|
23 |
* @var SassScriptParser SassScript parser
|
24 |
*/
|
@@ -46,7 +47,8 @@ class SassRootNode extends SassNode {
|
|
46 |
* @param SassParser Sass parser
|
47 |
* @return SassNode
|
48 |
*/
|
49 |
-
public function __construct($parser)
|
|
|
50 |
parent::__construct((object) array(
|
51 |
'source' => '',
|
52 |
'level' => -1,
|
@@ -66,9 +68,11 @@ class SassRootNode extends SassNode {
|
|
66 |
* @param SassContext the context in which this node is parsed
|
67 |
* @return SassNode root node of the render tree
|
68 |
*/
|
69 |
-
public function parse($context)
|
|
|
70 |
$node = clone $this;
|
71 |
$node->children = $this->parseChildren($context);
|
|
|
72 |
return $node;
|
73 |
}
|
74 |
|
@@ -76,17 +80,20 @@ class SassRootNode extends SassNode {
|
|
76 |
* Render this node.
|
77 |
* @return string the rendered node
|
78 |
*/
|
79 |
-
public function render($context = null)
|
|
|
80 |
$context = new SassContext($context);
|
81 |
$node = $this->parse($context);
|
82 |
$output = '';
|
83 |
foreach ($node->children as $child) {
|
84 |
$output .= $child->render();
|
85 |
} // foreach
|
|
|
86 |
return $output;
|
87 |
}
|
88 |
|
89 |
-
public function extend($extendee, $selectors)
|
|
|
90 |
if ($this->extend_parent && method_exists($this->extend_parent, 'extend')) {
|
91 |
return $this->extend_parent->extend($extendee, $selectors);
|
92 |
}
|
@@ -94,10 +101,12 @@ class SassRootNode extends SassNode {
|
|
94 |
? array_merge($this->extenders[$extendee], $selectors) : $selectors);
|
95 |
}
|
96 |
|
97 |
-
public function getExtenders()
|
|
|
98 |
if ($this->extend_parent && method_exists($this->extend_parent, 'getExtenders')) {
|
99 |
return $this->extend_parent->getExtenders();
|
100 |
}
|
|
|
101 |
return $this->extenders;
|
102 |
}
|
103 |
|
@@ -106,7 +115,8 @@ class SassRootNode extends SassNode {
|
|
106 |
* Child classes must override this method.
|
107 |
* @throws SassNodeException if not overriden
|
108 |
*/
|
109 |
-
public static function isa($line)
|
|
|
110 |
throw new SassNodeException('Child classes must override this method');
|
111 |
}
|
112 |
}
|
18 |
* @package PHamlP
|
19 |
* @subpackage Sass.tree
|
20 |
*/
|
21 |
+
class SassRootNode extends SassNode
|
22 |
+
{
|
23 |
/**
|
24 |
* @var SassScriptParser SassScript parser
|
25 |
*/
|
47 |
* @param SassParser Sass parser
|
48 |
* @return SassNode
|
49 |
*/
|
50 |
+
public function __construct($parser)
|
51 |
+
{
|
52 |
parent::__construct((object) array(
|
53 |
'source' => '',
|
54 |
'level' => -1,
|
68 |
* @param SassContext the context in which this node is parsed
|
69 |
* @return SassNode root node of the render tree
|
70 |
*/
|
71 |
+
public function parse($context)
|
72 |
+
{
|
73 |
$node = clone $this;
|
74 |
$node->children = $this->parseChildren($context);
|
75 |
+
|
76 |
return $node;
|
77 |
}
|
78 |
|
80 |
* Render this node.
|
81 |
* @return string the rendered node
|
82 |
*/
|
83 |
+
public function render($context = null)
|
84 |
+
{
|
85 |
$context = new SassContext($context);
|
86 |
$node = $this->parse($context);
|
87 |
$output = '';
|
88 |
foreach ($node->children as $child) {
|
89 |
$output .= $child->render();
|
90 |
} // foreach
|
91 |
+
|
92 |
return $output;
|
93 |
}
|
94 |
|
95 |
+
public function extend($extendee, $selectors)
|
96 |
+
{
|
97 |
if ($this->extend_parent && method_exists($this->extend_parent, 'extend')) {
|
98 |
return $this->extend_parent->extend($extendee, $selectors);
|
99 |
}
|
101 |
? array_merge($this->extenders[$extendee], $selectors) : $selectors);
|
102 |
}
|
103 |
|
104 |
+
public function getExtenders()
|
105 |
+
{
|
106 |
if ($this->extend_parent && method_exists($this->extend_parent, 'getExtenders')) {
|
107 |
return $this->extend_parent->getExtenders();
|
108 |
}
|
109 |
+
|
110 |
return $this->extenders;
|
111 |
}
|
112 |
|
115 |
* Child classes must override this method.
|
116 |
* @throws SassNodeException if not overriden
|
117 |
*/
|
118 |
+
public static function isa($line)
|
119 |
+
{
|
120 |
throw new SassNodeException('Child classes must override this method');
|
121 |
}
|
122 |
}
|
lib/phpsass/tree/SassRuleNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassRuleNode extends SassNode
|
|
|
19 |
const MATCH = '/^(.+?)(?:\s*\{)?$/';
|
20 |
const SELECTOR = 1;
|
21 |
const CONTINUED = ',';
|
@@ -51,7 +52,8 @@ class SassRuleNode extends SassNode {
|
|
51 |
* @param string rule selector
|
52 |
* @return SassRuleNode
|
53 |
*/
|
54 |
-
public function __construct($token)
|
|
|
55 |
parent::__construct($token);
|
56 |
preg_match(self::MATCH, $token->source, $matches);
|
57 |
$this->addSelectors($matches[SassRuleNode::SELECTOR]);
|
@@ -62,7 +64,8 @@ class SassRuleNode extends SassNode {
|
|
62 |
* If the selectors are to continue for the rule the selector must end in a comma
|
63 |
* @param string selector
|
64 |
*/
|
65 |
-
public function addSelectors($selectors, $explode = true)
|
|
|
66 |
$this->isContinued = substr($selectors, -1) === self::CONTINUED;
|
67 |
$this->selectors = array_merge($this->selectors, $explode ? $this->explode($selectors) : $selectors);
|
68 |
}
|
@@ -72,7 +75,8 @@ class SassRuleNode extends SassNode {
|
|
72 |
* @param boolean true if the selectors for this rule are to be continued,
|
73 |
* false if not
|
74 |
*/
|
75 |
-
public function getIsContinued()
|
|
|
76 |
return $this->isContinued;
|
77 |
}
|
78 |
|
@@ -81,10 +85,12 @@ class SassRuleNode extends SassNode {
|
|
81 |
* @param SassContext the context in which this node is parsed
|
82 |
* @return array the parsed node and its children
|
83 |
*/
|
84 |
-
public function parse($context)
|
|
|
85 |
$node = clone $this;
|
86 |
$node->selectors = $this->resolveSelectors($context);
|
87 |
$node->children = $this->parseChildren($context);
|
|
|
88 |
return array($node);
|
89 |
}
|
90 |
|
@@ -92,7 +98,8 @@ class SassRuleNode extends SassNode {
|
|
92 |
* Render this node and its children to CSS.
|
93 |
* @return string the rendered node
|
94 |
*/
|
95 |
-
public function render()
|
|
|
96 |
$this->extend();
|
97 |
$rules = '';
|
98 |
$properties = array();
|
@@ -101,8 +108,7 @@ class SassRuleNode extends SassNode {
|
|
101 |
$child->parent = $this;
|
102 |
if ($child instanceof SassRuleNode) {
|
103 |
$rules .= $child->render();
|
104 |
-
}
|
105 |
-
else {
|
106 |
$properties[] = $child->render();
|
107 |
}
|
108 |
}
|
@@ -116,13 +122,13 @@ class SassRuleNode extends SassNode {
|
|
116 |
* $extender is the selector that contains the @extend directive
|
117 |
* $selector a selector or selector sequence that is to be extended
|
118 |
*/
|
119 |
-
public function extend()
|
|
|
120 |
foreach ($this->root->getExtenders() as $extendee => $extenders) {
|
121 |
if ($this->isPsuedo($extendee)) {
|
122 |
$extendee = explode(':', $extendee);
|
123 |
$pattern = preg_quote($extendee[0]).'((\.[-\w]+)*):'.preg_quote($extendee[1]);
|
124 |
-
}
|
125 |
-
else {
|
126 |
$pattern = preg_quote($extendee);
|
127 |
}
|
128 |
|
@@ -138,11 +144,9 @@ class SassRuleNode extends SassNode {
|
|
138 |
}
|
139 |
if (is_array($extendee)) {
|
140 |
$this->selectors[] = preg_replace('/(.*?)'.$pattern.'([^a-zA-Z0-9_-]|$)/', '$1' . $extender . '$2', $selector);
|
141 |
-
}
|
142 |
-
elseif ($this->isSequence($extender) || $this->isSequence($selector)) {
|
143 |
$this->selectors = array_merge($this->selectors, $this->mergeSequence($extender, $extendee, $selector));
|
144 |
-
}
|
145 |
-
else {
|
146 |
$this->selectors[] = str_replace($extendee, $extender, $selector);
|
147 |
}
|
148 |
}
|
@@ -156,7 +160,8 @@ class SassRuleNode extends SassNode {
|
|
156 |
* @param string selector to test
|
157 |
* @return boolean true if the selector is a psuedo selector, false if not
|
158 |
*/
|
159 |
-
private function isPsuedo($selector)
|
|
|
160 |
return strpos($selector, ':') !== false;
|
161 |
}
|
162 |
|
@@ -165,11 +170,13 @@ class SassRuleNode extends SassNode {
|
|
165 |
* @param string selector to test
|
166 |
* @return boolean true if the selector is a sequence selector, false if not
|
167 |
*/
|
168 |
-
private function isSequence($selector)
|
|
|
169 |
return strpos($selector, ' ') !== false;
|
170 |
}
|
171 |
|
172 |
-
public function isPlaceholder($selector)
|
|
|
173 |
return strpos($selector, '%') !== false;
|
174 |
}
|
175 |
|
@@ -179,7 +186,8 @@ class SassRuleNode extends SassNode {
|
|
179 |
* @param string selector to extend
|
180 |
* @return array the merged sequences
|
181 |
*/
|
182 |
-
private function mergeSequence($extender, $extendee, $selector)
|
|
|
183 |
// if it's a placeholder, be lazy. Needs tests.
|
184 |
if ($extendee[0] == '%') {
|
185 |
// need to stop things like a%foo accepting div { @extend %foo }
|
@@ -193,7 +201,7 @@ class SassRuleNode extends SassNode {
|
|
193 |
|
194 |
$common = array();
|
195 |
if (count($extender) && count($selector)) {
|
196 |
-
while(trim($extender[0]) === trim($selector[0])) {
|
197 |
$common[] = array_shift($selector);
|
198 |
array_shift($extender);
|
199 |
if (!count($extender)) {
|
@@ -207,6 +215,7 @@ class SassRuleNode extends SassNode {
|
|
207 |
# Richard Lyon - 2011-10-25 - removes duplicates by uniquing and trimming.
|
208 |
# regex removes whitespace from start and and end of string as well as removing
|
209 |
# whitespace following whitespace. slightly quicker than a trim and simpler replace
|
|
|
210 |
return array_unique(array(
|
211 |
preg_replace('/(^\s+|(\s)\s+|\s+$)/', '$2', $beginning.join(' ', $selector).' '.join(' ', $extender). ' ' . $end),
|
212 |
preg_replace('/(^\s+|(\s)\s+|\s+$)/', '$2', $beginning.join(' ', $extender).' '.join(' ', $selector). ' ' . $end)
|
@@ -217,7 +226,8 @@ class SassRuleNode extends SassNode {
|
|
217 |
* Returns the selectors
|
218 |
* @return array selectors
|
219 |
*/
|
220 |
-
public function getSelectors()
|
|
|
221 |
return $this->selectors;
|
222 |
}
|
223 |
|
@@ -229,7 +239,8 @@ class SassRuleNode extends SassNode {
|
|
229 |
*
|
230 |
* Change: 7/Dec/11 - change to make selector ordering conform to Ruby compiler.
|
231 |
*/
|
232 |
-
public function resolveSelectors($context)
|
|
|
233 |
$resolvedSelectors = $normalSelectors = array();
|
234 |
$this->parentSelectors = $this->getParentSelectors($context);
|
235 |
|
@@ -241,8 +252,7 @@ class SassRuleNode extends SassNode {
|
|
241 |
$selector = trim($selector, ' \'"'); // strip whitespace and quotes, just-in-case.
|
242 |
if ($this->hasParentReference($selector)) {
|
243 |
$resolvedSelectors = array_merge($resolvedSelectors, $this->resolveParentReferences($selector, $context));
|
244 |
-
}
|
245 |
-
else {
|
246 |
$normalSelectors[] = $selector;
|
247 |
}
|
248 |
}
|
@@ -269,7 +279,8 @@ class SassRuleNode extends SassNode {
|
|
269 |
* This in an empty array if there is no parent selector.
|
270 |
* @return array the parent selector for this node
|
271 |
*/
|
272 |
-
protected function getParentSelectors($context)
|
|
|
273 |
$ancestor = $this->parent;
|
274 |
while (!$ancestor instanceof SassRuleNode && $ancestor->hasParent()) {
|
275 |
$ancestor = $ancestor->parent;
|
@@ -278,6 +289,7 @@ class SassRuleNode extends SassNode {
|
|
278 |
if ($ancestor instanceof SassRuleNode) {
|
279 |
return $ancestor->resolveSelectors($context);
|
280 |
}
|
|
|
281 |
return array();
|
282 |
}
|
283 |
|
@@ -291,20 +303,20 @@ class SassRuleNode extends SassNode {
|
|
291 |
* @return mixed integer: position of the the first parent reference,
|
292 |
* boolean: false if there is no parent reference.
|
293 |
*/
|
294 |
-
private function parentReferencePos($selector)
|
|
|
295 |
$inString = '';
|
296 |
for ($i = 0, $l = strlen($selector); $i < $l; $i++) {
|
297 |
$c = $selector[$i];
|
298 |
if ($c === self::PARENT_REFERENCE && empty($inString)) {
|
299 |
return $i;
|
300 |
-
}
|
301 |
-
elseif (empty($inString) && ($c === '"' || $c === "'")) {
|
302 |
$inString = $c;
|
303 |
-
}
|
304 |
-
elseif ($c === $inString) {
|
305 |
$inString = '';
|
306 |
}
|
307 |
}
|
|
|
308 |
return false;
|
309 |
}
|
310 |
|
@@ -313,7 +325,8 @@ class SassRuleNode extends SassNode {
|
|
313 |
* @param string selector
|
314 |
* @return boolean true if there is a parent reference in the selector
|
315 |
*/
|
316 |
-
private function hasParentReference($selector)
|
|
|
317 |
return $this->parentReferencePos($selector) !== false;
|
318 |
}
|
319 |
|
@@ -322,7 +335,8 @@ class SassRuleNode extends SassNode {
|
|
322 |
* @param string selector
|
323 |
* @return string selector with parent references resolved
|
324 |
*/
|
325 |
-
private function resolveParentReferences($selector, $context)
|
|
|
326 |
$resolvedReferences = array();
|
327 |
if (!count($this->parentSelectors)) {
|
328 |
throw new SassRuleNodeException('Can not use parent selector (' . self::PARENT_REFERENCE . ') when no parent selectors', $this);
|
@@ -330,6 +344,7 @@ class SassRuleNode extends SassNode {
|
|
330 |
foreach ($this->getParentSelectors($context) as $parentSelector) {
|
331 |
$resolvedReferences[] = str_replace(self::PARENT_REFERENCE, $parentSelector, $selector);
|
332 |
}
|
|
|
333 |
return $resolvedReferences;
|
334 |
}
|
335 |
|
@@ -340,7 +355,8 @@ class SassRuleNode extends SassNode {
|
|
340 |
* @param string selectors
|
341 |
* @return array selectors
|
342 |
*/
|
343 |
-
private function explode($string)
|
|
|
344 |
$selectors = array();
|
345 |
$inString = false;
|
346 |
$interpolate = false;
|
@@ -351,16 +367,14 @@ class SassRuleNode extends SassNode {
|
|
351 |
if ($c === self::CONTINUED && !$inString && !$interpolate) {
|
352 |
$selectors[] = trim($selector);
|
353 |
$selector = '';
|
354 |
-
}
|
355 |
-
else {
|
356 |
$selector .= $c;
|
357 |
if ($c === '"' || $c === "'") {
|
358 |
do {
|
359 |
$_c = $string[++$i];
|
360 |
$selector .= $_c;
|
361 |
} while ($_c !== $c && isset($string[$i+1]));
|
362 |
-
}
|
363 |
-
elseif ($c === '#' && $string[$i+1] === '{') {
|
364 |
do {
|
365 |
$c = $string[++$i];
|
366 |
$selector .= $c;
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassRuleNode extends SassNode
|
19 |
+
{
|
20 |
const MATCH = '/^(.+?)(?:\s*\{)?$/';
|
21 |
const SELECTOR = 1;
|
22 |
const CONTINUED = ',';
|
52 |
* @param string rule selector
|
53 |
* @return SassRuleNode
|
54 |
*/
|
55 |
+
public function __construct($token)
|
56 |
+
{
|
57 |
parent::__construct($token);
|
58 |
preg_match(self::MATCH, $token->source, $matches);
|
59 |
$this->addSelectors($matches[SassRuleNode::SELECTOR]);
|
64 |
* If the selectors are to continue for the rule the selector must end in a comma
|
65 |
* @param string selector
|
66 |
*/
|
67 |
+
public function addSelectors($selectors, $explode = true)
|
68 |
+
{
|
69 |
$this->isContinued = substr($selectors, -1) === self::CONTINUED;
|
70 |
$this->selectors = array_merge($this->selectors, $explode ? $this->explode($selectors) : $selectors);
|
71 |
}
|
75 |
* @param boolean true if the selectors for this rule are to be continued,
|
76 |
* false if not
|
77 |
*/
|
78 |
+
public function getIsContinued()
|
79 |
+
{
|
80 |
return $this->isContinued;
|
81 |
}
|
82 |
|
85 |
* @param SassContext the context in which this node is parsed
|
86 |
* @return array the parsed node and its children
|
87 |
*/
|
88 |
+
public function parse($context)
|
89 |
+
{
|
90 |
$node = clone $this;
|
91 |
$node->selectors = $this->resolveSelectors($context);
|
92 |
$node->children = $this->parseChildren($context);
|
93 |
+
|
94 |
return array($node);
|
95 |
}
|
96 |
|
98 |
* Render this node and its children to CSS.
|
99 |
* @return string the rendered node
|
100 |
*/
|
101 |
+
public function render()
|
102 |
+
{
|
103 |
$this->extend();
|
104 |
$rules = '';
|
105 |
$properties = array();
|
108 |
$child->parent = $this;
|
109 |
if ($child instanceof SassRuleNode) {
|
110 |
$rules .= $child->render();
|
111 |
+
} else {
|
|
|
112 |
$properties[] = $child->render();
|
113 |
}
|
114 |
}
|
122 |
* $extender is the selector that contains the @extend directive
|
123 |
* $selector a selector or selector sequence that is to be extended
|
124 |
*/
|
125 |
+
public function extend()
|
126 |
+
{
|
127 |
foreach ($this->root->getExtenders() as $extendee => $extenders) {
|
128 |
if ($this->isPsuedo($extendee)) {
|
129 |
$extendee = explode(':', $extendee);
|
130 |
$pattern = preg_quote($extendee[0]).'((\.[-\w]+)*):'.preg_quote($extendee[1]);
|
131 |
+
} else {
|
|
|
132 |
$pattern = preg_quote($extendee);
|
133 |
}
|
134 |
|
144 |
}
|
145 |
if (is_array($extendee)) {
|
146 |
$this->selectors[] = preg_replace('/(.*?)'.$pattern.'([^a-zA-Z0-9_-]|$)/', '$1' . $extender . '$2', $selector);
|
147 |
+
} elseif ($this->isSequence($extender) || $this->isSequence($selector)) {
|
|
|
148 |
$this->selectors = array_merge($this->selectors, $this->mergeSequence($extender, $extendee, $selector));
|
149 |
+
} else {
|
|
|
150 |
$this->selectors[] = str_replace($extendee, $extender, $selector);
|
151 |
}
|
152 |
}
|
160 |
* @param string selector to test
|
161 |
* @return boolean true if the selector is a psuedo selector, false if not
|
162 |
*/
|
163 |
+
private function isPsuedo($selector)
|
164 |
+
{
|
165 |
return strpos($selector, ':') !== false;
|
166 |
}
|
167 |
|
170 |
* @param string selector to test
|
171 |
* @return boolean true if the selector is a sequence selector, false if not
|
172 |
*/
|
173 |
+
private function isSequence($selector)
|
174 |
+
{
|
175 |
return strpos($selector, ' ') !== false;
|
176 |
}
|
177 |
|
178 |
+
public function isPlaceholder($selector)
|
179 |
+
{
|
180 |
return strpos($selector, '%') !== false;
|
181 |
}
|
182 |
|
186 |
* @param string selector to extend
|
187 |
* @return array the merged sequences
|
188 |
*/
|
189 |
+
private function mergeSequence($extender, $extendee, $selector)
|
190 |
+
{
|
191 |
// if it's a placeholder, be lazy. Needs tests.
|
192 |
if ($extendee[0] == '%') {
|
193 |
// need to stop things like a%foo accepting div { @extend %foo }
|
201 |
|
202 |
$common = array();
|
203 |
if (count($extender) && count($selector)) {
|
204 |
+
while (trim($extender[0]) === trim($selector[0])) {
|
205 |
$common[] = array_shift($selector);
|
206 |
array_shift($extender);
|
207 |
if (!count($extender)) {
|
215 |
# Richard Lyon - 2011-10-25 - removes duplicates by uniquing and trimming.
|
216 |
# regex removes whitespace from start and and end of string as well as removing
|
217 |
# whitespace following whitespace. slightly quicker than a trim and simpler replace
|
218 |
+
|
219 |
return array_unique(array(
|
220 |
preg_replace('/(^\s+|(\s)\s+|\s+$)/', '$2', $beginning.join(' ', $selector).' '.join(' ', $extender). ' ' . $end),
|
221 |
preg_replace('/(^\s+|(\s)\s+|\s+$)/', '$2', $beginning.join(' ', $extender).' '.join(' ', $selector). ' ' . $end)
|
226 |
* Returns the selectors
|
227 |
* @return array selectors
|
228 |
*/
|
229 |
+
public function getSelectors()
|
230 |
+
{
|
231 |
return $this->selectors;
|
232 |
}
|
233 |
|
239 |
*
|
240 |
* Change: 7/Dec/11 - change to make selector ordering conform to Ruby compiler.
|
241 |
*/
|
242 |
+
public function resolveSelectors($context)
|
243 |
+
{
|
244 |
$resolvedSelectors = $normalSelectors = array();
|
245 |
$this->parentSelectors = $this->getParentSelectors($context);
|
246 |
|
252 |
$selector = trim($selector, ' \'"'); // strip whitespace and quotes, just-in-case.
|
253 |
if ($this->hasParentReference($selector)) {
|
254 |
$resolvedSelectors = array_merge($resolvedSelectors, $this->resolveParentReferences($selector, $context));
|
255 |
+
} else {
|
|
|
256 |
$normalSelectors[] = $selector;
|
257 |
}
|
258 |
}
|
279 |
* This in an empty array if there is no parent selector.
|
280 |
* @return array the parent selector for this node
|
281 |
*/
|
282 |
+
protected function getParentSelectors($context)
|
283 |
+
{
|
284 |
$ancestor = $this->parent;
|
285 |
while (!$ancestor instanceof SassRuleNode && $ancestor->hasParent()) {
|
286 |
$ancestor = $ancestor->parent;
|
289 |
if ($ancestor instanceof SassRuleNode) {
|
290 |
return $ancestor->resolveSelectors($context);
|
291 |
}
|
292 |
+
|
293 |
return array();
|
294 |
}
|
295 |
|
303 |
* @return mixed integer: position of the the first parent reference,
|
304 |
* boolean: false if there is no parent reference.
|
305 |
*/
|
306 |
+
private function parentReferencePos($selector)
|
307 |
+
{
|
308 |
$inString = '';
|
309 |
for ($i = 0, $l = strlen($selector); $i < $l; $i++) {
|
310 |
$c = $selector[$i];
|
311 |
if ($c === self::PARENT_REFERENCE && empty($inString)) {
|
312 |
return $i;
|
313 |
+
} elseif (empty($inString) && ($c === '"' || $c === "'")) {
|
|
|
314 |
$inString = $c;
|
315 |
+
} elseif ($c === $inString) {
|
|
|
316 |
$inString = '';
|
317 |
}
|
318 |
}
|
319 |
+
|
320 |
return false;
|
321 |
}
|
322 |
|
325 |
* @param string selector
|
326 |
* @return boolean true if there is a parent reference in the selector
|
327 |
*/
|
328 |
+
private function hasParentReference($selector)
|
329 |
+
{
|
330 |
return $this->parentReferencePos($selector) !== false;
|
331 |
}
|
332 |
|
335 |
* @param string selector
|
336 |
* @return string selector with parent references resolved
|
337 |
*/
|
338 |
+
private function resolveParentReferences($selector, $context)
|
339 |
+
{
|
340 |
$resolvedReferences = array();
|
341 |
if (!count($this->parentSelectors)) {
|
342 |
throw new SassRuleNodeException('Can not use parent selector (' . self::PARENT_REFERENCE . ') when no parent selectors', $this);
|
344 |
foreach ($this->getParentSelectors($context) as $parentSelector) {
|
345 |
$resolvedReferences[] = str_replace(self::PARENT_REFERENCE, $parentSelector, $selector);
|
346 |
}
|
347 |
+
|
348 |
return $resolvedReferences;
|
349 |
}
|
350 |
|
355 |
* @param string selectors
|
356 |
* @return array selectors
|
357 |
*/
|
358 |
+
private function explode($string)
|
359 |
+
{
|
360 |
$selectors = array();
|
361 |
$inString = false;
|
362 |
$interpolate = false;
|
367 |
if ($c === self::CONTINUED && !$inString && !$interpolate) {
|
368 |
$selectors[] = trim($selector);
|
369 |
$selector = '';
|
370 |
+
} else {
|
|
|
371 |
$selector .= $c;
|
372 |
if ($c === '"' || $c === "'") {
|
373 |
do {
|
374 |
$_c = $string[++$i];
|
375 |
$selector .= $_c;
|
376 |
} while ($_c !== $c && isset($string[$i+1]));
|
377 |
+
} elseif ($c === '#' && $string[$i+1] === '{') {
|
|
|
378 |
do {
|
379 |
$c = $string[++$i];
|
380 |
$selector .= $c;
|
lib/phpsass/tree/SassVariableNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassVariableNode extends SassNode
|
|
|
19 |
const MATCH = '/^([!$])([\w-]+)\s*:?\s*((\|\|)?=)?\s*(.+?)\s*(!default)?;?$/i';
|
20 |
const IDENTIFIER = 1;
|
21 |
const NAME = 2;
|
@@ -44,7 +45,8 @@ class SassVariableNode extends SassNode {
|
|
44 |
* @param object source token
|
45 |
* @return SassVariableNode
|
46 |
*/
|
47 |
-
public function __construct($token)
|
|
|
48 |
parent::__construct($token);
|
49 |
preg_match(self::MATCH, $token->source, $matches);
|
50 |
if (empty($matches[self::NAME]) || ($matches[self::VALUE] === '')) {
|
@@ -70,13 +72,15 @@ class SassVariableNode extends SassNode {
|
|
70 |
* @param SassContext the context in which this node is parsed
|
71 |
* @return array the parsed node - an empty array
|
72 |
*/
|
73 |
-
public function parse($context)
|
|
|
74 |
if (!$this->isDefault || !$context->hasVariable($this->name)) {
|
75 |
$context->setVariable(
|
76 |
$this->name, $this->evaluate($this->value, $context)
|
77 |
);
|
78 |
}
|
79 |
$this->parseChildren($context); // Parse any warnings
|
|
|
80 |
return array();
|
81 |
}
|
82 |
|
@@ -85,7 +89,8 @@ class SassVariableNode extends SassNode {
|
|
85 |
* @param object token
|
86 |
* @return boolean true if the token represents this type of node, false if not
|
87 |
*/
|
88 |
-
public static function isa($token)
|
|
|
89 |
return $token->source[0] === self::SASS_IDENTIFIER || $token->source[0] === self::SCSS_IDENTIFIER;
|
90 |
}
|
91 |
-
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassVariableNode extends SassNode
|
19 |
+
{
|
20 |
const MATCH = '/^([!$])([\w-]+)\s*:?\s*((\|\|)?=)?\s*(.+?)\s*(!default)?;?$/i';
|
21 |
const IDENTIFIER = 1;
|
22 |
const NAME = 2;
|
45 |
* @param object source token
|
46 |
* @return SassVariableNode
|
47 |
*/
|
48 |
+
public function __construct($token)
|
49 |
+
{
|
50 |
parent::__construct($token);
|
51 |
preg_match(self::MATCH, $token->source, $matches);
|
52 |
if (empty($matches[self::NAME]) || ($matches[self::VALUE] === '')) {
|
72 |
* @param SassContext the context in which this node is parsed
|
73 |
* @return array the parsed node - an empty array
|
74 |
*/
|
75 |
+
public function parse($context)
|
76 |
+
{
|
77 |
if (!$this->isDefault || !$context->hasVariable($this->name)) {
|
78 |
$context->setVariable(
|
79 |
$this->name, $this->evaluate($this->value, $context)
|
80 |
);
|
81 |
}
|
82 |
$this->parseChildren($context); // Parse any warnings
|
83 |
+
|
84 |
return array();
|
85 |
}
|
86 |
|
89 |
* @param object token
|
90 |
* @return boolean true if the token represents this type of node, false if not
|
91 |
*/
|
92 |
+
public static function isa($token)
|
93 |
+
{
|
94 |
return $token->source[0] === self::SASS_IDENTIFIER || $token->source[0] === self::SCSS_IDENTIFIER;
|
95 |
}
|
96 |
+
}
|
lib/phpsass/tree/SassWarnNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassWarnNode extends SassNode
|
|
|
19 |
const NODE_IDENTIFIER = '+';
|
20 |
const MATCH = '/^(@warn\s+)(["\']?)(.*?)(["\']?)$/i';
|
21 |
const IDENTIFIER = 1;
|
@@ -31,7 +32,8 @@ class SassWarnNode extends SassNode {
|
|
31 |
* @param object source token
|
32 |
* @return SassReturnNode
|
33 |
*/
|
34 |
-
public function __construct($token)
|
|
|
35 |
parent::__construct($token);
|
36 |
preg_match(self::MATCH, $token->source, $matches);
|
37 |
|
@@ -49,14 +51,14 @@ class SassWarnNode extends SassNode {
|
|
49 |
* @param SassContext the context in which this node is parsed
|
50 |
* @return array the parsed node
|
51 |
*/
|
52 |
-
public function parse($pcontext)
|
|
|
53 |
$context = new SassContext($pcontext);
|
54 |
$statement = $this->statement;
|
55 |
|
56 |
try {
|
57 |
$statement = $this->evaluate($this->statement, $context)->toString();
|
58 |
-
}
|
59 |
-
catch (Exception $e) {}
|
60 |
|
61 |
if (SassParser::$instance->options['callbacks']['warn']) {
|
62 |
call_user_func(SassParser::$instance->options['callbacks']['warn'], $statement, $context);
|
@@ -64,8 +66,7 @@ class SassWarnNode extends SassNode {
|
|
64 |
|
65 |
if (SassParser::$instance->getQuiet()) {
|
66 |
return array(new SassString(''));
|
67 |
-
}
|
68 |
-
else {
|
69 |
return array(new SassString('/* @warn: ' . str_replace('*/', '', $statement) . ' */'));
|
70 |
}
|
71 |
}
|
@@ -75,7 +76,8 @@ class SassWarnNode extends SassNode {
|
|
75 |
* @param object token
|
76 |
* @return boolean true if the token represents this type of node, false if not
|
77 |
*/
|
78 |
-
public static function isa($token)
|
|
|
79 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
80 |
}
|
81 |
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassWarnNode extends SassNode
|
19 |
+
{
|
20 |
const NODE_IDENTIFIER = '+';
|
21 |
const MATCH = '/^(@warn\s+)(["\']?)(.*?)(["\']?)$/i';
|
22 |
const IDENTIFIER = 1;
|
32 |
* @param object source token
|
33 |
* @return SassReturnNode
|
34 |
*/
|
35 |
+
public function __construct($token)
|
36 |
+
{
|
37 |
parent::__construct($token);
|
38 |
preg_match(self::MATCH, $token->source, $matches);
|
39 |
|
51 |
* @param SassContext the context in which this node is parsed
|
52 |
* @return array the parsed node
|
53 |
*/
|
54 |
+
public function parse($pcontext)
|
55 |
+
{
|
56 |
$context = new SassContext($pcontext);
|
57 |
$statement = $this->statement;
|
58 |
|
59 |
try {
|
60 |
$statement = $this->evaluate($this->statement, $context)->toString();
|
61 |
+
} catch (Exception $e) {}
|
|
|
62 |
|
63 |
if (SassParser::$instance->options['callbacks']['warn']) {
|
64 |
call_user_func(SassParser::$instance->options['callbacks']['warn'], $statement, $context);
|
66 |
|
67 |
if (SassParser::$instance->getQuiet()) {
|
68 |
return array(new SassString(''));
|
69 |
+
} else {
|
|
|
70 |
return array(new SassString('/* @warn: ' . str_replace('*/', '', $statement) . ' */'));
|
71 |
}
|
72 |
}
|
76 |
* @param object token
|
77 |
* @return boolean true if the token represents this type of node, false if not
|
78 |
*/
|
79 |
+
public static function isa($token)
|
80 |
+
{
|
81 |
return $token->source[0] === self::NODE_IDENTIFIER;
|
82 |
}
|
83 |
}
|
lib/phpsass/tree/SassWhileNode.php
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
-
class SassWhileNode extends SassNode
|
|
|
19 |
const MATCH = '/^@(do|while)\s+(.+)$/i';
|
20 |
const LOOP = 1;
|
21 |
const EXPRESSION = 2;
|
@@ -35,7 +36,8 @@ class SassWhileNode extends SassNode {
|
|
35 |
* @param object source token
|
36 |
* @return SassWhileNode
|
37 |
*/
|
38 |
-
public function __construct($token)
|
|
|
39 |
parent::__construct($token);
|
40 |
preg_match(self::MATCH, $token->source, $matches);
|
41 |
$this->expression = $matches[self::EXPRESSION];
|
@@ -47,18 +49,19 @@ class SassWhileNode extends SassNode {
|
|
47 |
* @param SassContext the context in which this node is parsed
|
48 |
* @return array the parsed child nodes
|
49 |
*/
|
50 |
-
public function parse($context)
|
|
|
51 |
$children = array();
|
52 |
if ($this->isDo) {
|
53 |
do {
|
54 |
$children = array_merge($children, $this->parseChildren($context));
|
55 |
} while ($this->evaluate($this->expression, $context)->toBoolean());
|
56 |
-
}
|
57 |
-
else {
|
58 |
while ($this->evaluate($this->expression, $context)->toBoolean()) {
|
59 |
$children = array_merge($children, $this->parseChildren($context));
|
60 |
}
|
61 |
}
|
|
|
62 |
return $children;
|
63 |
}
|
64 |
-
}
|
15 |
* @package PHamlP
|
16 |
* @subpackage Sass.tree
|
17 |
*/
|
18 |
+
class SassWhileNode extends SassNode
|
19 |
+
{
|
20 |
const MATCH = '/^@(do|while)\s+(.+)$/i';
|
21 |
const LOOP = 1;
|
22 |
const EXPRESSION = 2;
|
36 |
* @param object source token
|
37 |
* @return SassWhileNode
|
38 |
*/
|
39 |
+
public function __construct($token)
|
40 |
+
{
|
41 |
parent::__construct($token);
|
42 |
preg_match(self::MATCH, $token->source, $matches);
|
43 |
$this->expression = $matches[self::EXPRESSION];
|
49 |
* @param SassContext the context in which this node is parsed
|
50 |
* @return array the parsed child nodes
|
51 |
*/
|
52 |
+
public function parse($context)
|
53 |
+
{
|
54 |
$children = array();
|
55 |
if ($this->isDo) {
|
56 |
do {
|
57 |
$children = array_merge($children, $this->parseChildren($context));
|
58 |
} while ($this->evaluate($this->expression, $context)->toBoolean());
|
59 |
+
} else {
|
|
|
60 |
while ($this->evaluate($this->expression, $context)->toBoolean()) {
|
61 |
$children = array_merge($children, $this->parseChildren($context));
|
62 |
}
|
63 |
}
|
64 |
+
|
65 |
return $children;
|
66 |
}
|
67 |
+
}
|
package.xml
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Sass</name>
|
4 |
-
<version>1.1.
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
|
7 |
<channel>community</channel>
|
@@ -12,11 +12,12 @@
|
|
12 |
You just need to create you sass file and add it to your layout like default css file.
|
13 |

|
14 |
This extension will then convert it to css file using phpSass or sass in command line if available</description>
|
15 |
-
<notes>
|
|
|
16 |
<authors><author><name>Laurent Clouet</name><user>laurent35240</user><email>laurent35240@gmail.com</email></author></authors>
|
17 |
-
<date>2013-
|
18 |
-
<time>
|
19 |
-
<contents><target name="magecommunity"><dir name="Laurent"><dir name="Sass"><dir name="Helper"><file name="Data.php" hash="9c43132dba73d4b3f37ccfb91f0d5dbe"/></dir><dir name="Model"><dir name="Config"><file name="Style.php" hash="413571124dcf58d950200499a144420d"/></dir><dir name="Design"><file name="Package.php" hash="3c83af4c43fd94359541b7242852ca06"/></dir></dir><dir name="etc"><file name="config.xml" hash="1e99b16cb4ca540ae8cd207825f9a269"/><file name="system.xml" hash="a2db1af0d9bae017b46805a80aedb442"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Laurent_Sass.xml" hash="4ad004de851457681610553228973c30"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Laurent_Sass.csv" hash="d9e8c184cbe72e810c7da9154581e1e4"/></dir><dir name="fr_FR"><file name="Laurent_Sass.csv" hash="676b2c597fe0b829fb2c48c1428c295f"/></dir></target><target name="magelib"><dir name="phpsass"><dir name="Extensions"><dir name="Compass"><file name="Compass.php" hash="3bc8aaa37ae61b7bce0dc5fc0f16112e"/><dir name="stylesheets"><file name="_compass.scss" hash="bc769e7b7e94a717f9f4439978543900"/><file name="_lemonade.scss" hash="92e7ec85f14f46cf399a64115707dfe1"/><dir name="compass"><file name="_css3.scss" hash="7688063612bb668fffd22c32b95a2f5c"/><file name="_layout.scss" hash="d7445d578d56b5f0d6482d5df0b28a7b"/><file name="_reset-legacy.scss" hash="322b2e4617c8bf9e6c1ad02bef42ac18"/><file name="_reset.scss" hash="b3d1130413650cdc98b24777bf15afff"/><file name="_support.scss" hash="200db7d3bd7cd633b35c73c7d724a275"/><file name="_typography.scss" hash="73c901f7f8afd26c65dbadedffb87c1a"/><file name="_utilities.scss" hash="adb9de208e608e5bdd25189b4d4790a6"/><dir name="css3"><file name="_appearance.scss" hash="b624212e8f27e260b89e7aa84e598432"/><file name="_background-clip.scss" hash="9eab5a21f351b22e565278af805382b3"/><file name="_background-origin.scss" hash="57e96581316421882118c0d155a4a74f"/><file name="_background-size.scss" hash="674b66cc99bf60400b44f130d0c9d00d"/><file name="_border-radius.scss" hash="02749463ff3b0d0e68e42c76e6c18b66"/><file name="_box-shadow.scss" hash="13cb3d1733c1f7a60c542c44e639af55"/><file name="_box-sizing.scss" hash="5bc8b4f482fb878518d28a18dd453df9"/><file name="_box.scss" hash="ca45bf6d49507d042e5928cf1058909c"/><file name="_columns.scss" hash="b809552667f5876e115881ece27cbc8e"/><file name="_filter.scss" hash="ddc12210cb1d9cdcaad890e9d02601de"/><file name="_font-face.scss" hash="dfc84cb70f83cdbcde9dd3e51789363b"/><file name="_hyphenation.scss" hash="d3cf84dec3da60b4259fe2a9276421b5"/><file name="_images.scss" hash="c4d2fc1c4a1c78a68952de2694939fd2"/><file name="_inline-block.scss" hash="0ddfde10e192213f01dfa122d15bf473"/><file name="_opacity.scss" hash="36a24354a3b62b9b9c82690d1c008963"/><file name="_pie.scss" hash="8ec8261b6cdfef171774d6ad294dbcb7"/><file name="_regions.scss" hash="84db6e13237909b8c05e60c5735f43cc"/><file name="_shared.scss" hash="2a19ef6064fadd0c7bc1213878172ca2"/><file name="_text-shadow.scss" hash="b8dda78c05f393266e002b85885737af"/><file name="_transform-legacy.scss" hash="8d7c4ab98d1a165271ba64e859454c9f"/><file name="_transform.scss" hash="63d14c83ad4ebe0a25fe62b2e9b3a840"/><file name="_transition.scss" hash="ae7b441207aede5e831fd58d13d09103"/><file name="_user-interface.scss" hash="4293d8e1b99b864b6f1a1e341d281fbb"/></dir><dir name="layout"><file name="_grid-background.scss" hash="ebbb0813eeb27f1b102396275cd35e2b"/><file name="_sticky-footer.scss" hash="c10c67d6ebe9ca67709c982bbfed7178"/><file name="_stretching.scss" hash="3f59f9138e25943e4a7def3aa22704e5"/></dir><dir name="reset"><file name="_utilities-legacy.scss" hash="b3a4fd8ac50ace1aa1e607d4d926be45"/><file name="_utilities.scss" hash="c84668ad95fd7c53b77bd015452dd416"/></dir><dir name="typography"><file name="_links.scss" hash="862a5096f3a03597aab1be4e9dc76c64"/><file name="_lists.scss" hash="0e8662119de52a98ac3e601e086bbf53"/><file name="_text.scss" hash="4d3e129baa58fb176ded67c97bbf5b0a"/><file name="_vertical_rhythm.scss" hash="80869e4543f6f4e7ec93e52419d9a6e9"/><dir name="links"><file name="_hover-link.scss" hash="329c8ea4f1460cadf695e8d830c33a80"/><file name="_link-colors.scss" hash="9a4a09d3f9121c10f403a1fa333725dc"/><file name="_unstyled-link.scss" hash="3439d86d2f28c345864a7337c99db069"/></dir><dir name="lists"><file name="_bullets.scss" hash="9d733d179b5dcc005ef07535c16abe2a"/><file name="_horizontal-list.scss" hash="14a893eaa879be04e2ed636ab524b8f7"/><file name="_inline-block-list.scss" hash="f96c6c754473084d0af9d07b6d85cf44"/><file name="_inline-list.scss" hash="898ffa6ae6c13c5df2730172d618dece"/></dir><dir name="text"><file name="_ellipsis.scss" hash="a4765ddc9555f114ff59ae1a582f3caa"/><file name="_force-wrap.scss" hash="def5a5579399a9d35d845d3133338e3c"/><file name="_nowrap.scss" hash="e2cf48586ed5a33ab90a09e346020afc"/><file name="_replacement.scss" hash="e20cb6a854d0a9adb9bd7a879cb257a3"/></dir></dir><dir name="utilities"><file name="_color.scss" hash="4f6252c899a6f25c57ec1b4e9052e55b"/><file name="_general.scss" hash="7a90acc34a01d65ccc38f6dd6225229a"/><file name="_print.scss" hash="eb1d910e8aea90d23b76adf27323abe8"/><file name="_sprites.scss" hash="5f57e9b3f79df0ed70b7321aa55a1a2d"/><file name="_tables.scss" hash="836327d928e513dc737897356d7ba15b"/><dir name="color"><file name="_contrast.scss" hash="735478c5e04e31030afca1e36bf8e398"/></dir><dir name="general"><file name="_clearfix.scss" hash="58fd0d07999140b25bddb4e5c1d49a17"/><file name="_float.scss" hash="5c273f43ca3a3d409c08151ac4f86786"/><file name="_hacks.scss" hash="98ede0f56175f5fb08b3ecd982c27309"/><file name="_min.scss" hash="26a0f6fdad1f7ff71f40ff92eda4f56c"/><file name="_tabs.scss" hash="68b329da9893e34099c7d8ad5cb9c940"/><file name="_tag-cloud.scss" hash="ae7c8c97b4b3142eac7d3c279a5a729c"/></dir><dir name="sprites"><file name="_base.scss" hash="cc4f45b711e8d7fc11aaecd5a54f3744"/><file name="_sprite-img.scss" hash="2deeab732747a9da12f965e133fd795f"/></dir><dir name="tables"><file name="_alternating-rows-and-columns.scss" hash="aa6884db2666742519eb7a4c399767b3"/><file name="_borders.scss" hash="2ac334630de78ae00941857bcbf098d5"/><file name="_scaffolding.scss" hash="4144e427ff1f2a6a9ffdfd3bd641e477"/></dir></dir></dir></dir></dir><file name="ExtensionInterface.php" hash="f02f77afac08968fca0ca8f7cd750456"/><dir name="Own"><file name="Own.php" hash="b8e662147759f28279b575ec753c4eb5"/><dir name="css"><dir name="test"><dir name="test2"><file name="test.scss" hash="b406241e81f4cbd2509a3a7daa50ba6e"/></dir></dir></dir></dir><file name="README.md" hash="0adcca717d8c0113986c95cfa6fa341f"/><dir name="Susy"><file name="Susy.php" hash="5e3068256f5b17c32ac5cc544137ac80"/><dir name="stylesheets"><file name="_susy.scss" hash="e60bb0cc5234c86628f4e0345bd2d48a"/><dir name="susy"><file name="_background.scss" hash="e7125e6d00deae7955c61ef9ce5b7557"/><file name="_functions.scss" hash="33d52f0bb6a333da77ac8c4482a1d862"/><file name="_grid.scss" hash="687c942dcaba8b87dac49db2d734e594"/><file name="_isolation.scss" hash="8e097d991625106869a96101bdc2bde4"/><file name="_margin.scss" hash="cb03e121a2800a47d569b456f247a0e4"/><file name="_media.scss" hash="89c7da945f0159b5e97ce705e8d06ae6"/><file name="_padding.scss" hash="b775d9b8f5465ae985da128e31818342"/><file name="_settings.scss" hash="e9942cc79f66826c45c525705aca4c5b"/><file name="_support.scss" hash="7c51df6bd18e85e6954b46e37b47db48"/><file name="_units.scss" hash="fea6309f28d01dc5cbf3fa8503f6bfae"/></dir></dir></dir><file name="example.php" hash="1b0d47697d1a85bbfb92cff187a51c4d"/><file name="example.scss" hash="1c36b8695ac3d22afa9caa72a5e0a96f"/><file name="theme.scss" hash="7210d729d56c93a23b91d4d280570e17"/></dir><file name="README.md" hash="f680aedff15c35475551bf0e0652be57"/><file name="SassException.php" hash="ae7482e7d574a36156671b4575d8c0b9"/><file name="SassFile.php" hash="61671ca2d00c771a031372243b9ad7b1"/><file name="SassParser.php" hash="de29cac49e715943a4b6a9590a4600ef"/><file name="VERSION" hash="989e91af7fc25340430a23b0cafe3f1d"/><file name="compile-apache.php" hash="7a95ffbe3baf88cd27260645e51d326d"/><file name="composer.json" hash="fb5dad84d70d71d3ad3ea36e06238c21"/><dir name="renderers"><file name="SassCompactRenderer.php" hash="d06cc6830ab426eacb6758b6b7e60db8"/><file name="SassCompressedRenderer.php" hash="ebbb33ce5f0c205fe96f80d452cdc75e"/><file name="SassExpandedRenderer.php" hash="f7d4dfa1a46748a50f212ab1b4c39cf9"/><file name="SassNestedRenderer.php" hash="ae57a3b8da86ae7c8560f71fc7cf69c4"/><file name="SassRenderer.php" hash="2f9059ce82c1d73f3a386ba005457bde"/></dir><dir name="script"><file name="SassScriptFunction.php" hash="8097a8a37e561a1f119f623dfdf73610"/><file name="SassScriptFunctions.php" hash="99b290ce879e50b9414de4dd6187c1b0"/><file name="SassScriptLexer.php" hash="8e5a0180f4b24e5008223816a5855fd2"/><file name="SassScriptOperation.php" hash="0ed86bf58330c6d407d7fe73a3d72ee8"/><file name="SassScriptParser.php" hash="3d99f5d850767c11be70189ff33bb4e2"/><file name="SassScriptParserExceptions.php" hash="7adc8cdc2f8a343213de10fa9c89a9fb"/><file name="SassScriptVariable.php" hash="49a4b8e3d3d5d358e3361684d6717439"/><dir name="literals"><file name="SassBoolean.php" hash="b456eafe96ef49e55e4256787539a37a"/><file name="SassColour.php" hash="b8ff0c00e202a25c411b653de7df8db4"/><file name="SassList.php" hash="19f4efc813eb12b557f306d3a427ec74"/><file name="SassLiteral.php" hash="d4403c33ca7bac07035832e009df5df8"/><file name="SassLiteralExceptions.php" hash="37841fc5e291f83b053b46dff8fabb1d"/><file name="SassNumber.php" hash="c3881b5a953b2207b15dc446867f6fba"/><file name="SassString.php" hash="4403e9ba0973e3fd04acf2eba5657496"/></dir></dir><file name="test.css" hash="1655ffa4e91349bbe84d9e9f87b5ae39"/><file name="test.php" hash="811210b59e0b2b0e243a53c7328f9d26"/><dir name="tests"><file name="_imported_charset_ibm866.sass" hash="92b1d97a137e4219bb7796d7751aa847"/><file name="_imported_charset_utf8.sass" hash="51489125c07d0e8f2b055295d40d2549"/><file name="_imported_content.sass" hash="aafd4b9ba2de82e4f977e04934f204d7"/><file name="_partial.sass" hash="529fb954d7e0f6b42c484c869e60fbcf"/><file name="alt.css" hash="d33475aa3b976be630eb419996866ee6"/><file name="alt.sass" hash="66be58fb872cd96be90fb95425a0aadf"/><file name="alt.scss" hash="ec1074aaba9b4a1ef3933d091c547c63"/><file name="basic.css" hash="22c341ec6e41dba84606032a40ea21c3"/><file name="basic.sass" hash="450faf5ca8e4bacefd01a74509ae135c"/><file name="bork1.sass" hash="0608533ebc4c4a16ddff507f818a709e"/><file name="bork2.sass" hash="036c6e0bcebc36908f9093d1b536ceb1"/><file name="bork3.sass" hash="ad06e4551ead8422ac443ae0cad7994b"/><file name="bork4.sass" hash="0bd4b0aed58208f5abf4418eb9672ef9"/><file name="bork5.sass" hash="e467427a1e928d1d72ef8db10482e262"/><file name="colour-nth.css" hash="8e457058415890dd4aac86f75a6e39e4"/><file name="colour-nth.scss" hash="3de860789a01fa9b5cf2d9a74a85dba7"/><file name="comments.css" hash="0ca95a61ccc49717e465173fb0c2e6c6"/><file name="comments.sass" hash="41bb5d2d2e14e3dd16c8b0296608a00e"/><file name="compact.css" hash="96105d0147b6881651b723eabe303f65"/><file name="compact.sass" hash="d51cfe7db78fe0d81793c7e24cb32e46"/><file name="complex.css" hash="3ffea6ccf80b24cc136bb102b3b41a67"/><file name="complex.sass" hash="b1426382fb915456b5efc0877ae7072d"/><file name="compressed.css" hash="1975f89cc758e39302d317578fdfdedb"/><file name="compressed.sass" hash="d51cfe7db78fe0d81793c7e24cb32e46"/><file name="content.css" hash="0c0892c48d74761fee54e09ccba6e662"/><file name="content.scss" hash="e624a12355435c147c0772f9fd1fe065"/><file name="css3.css" hash="8b2a0df29de7f2158baa3e97e76d91f2"/><file name="css3.scss" hash="819f570dae1e0c8c77007a03a2642158"/><file name="default.css" hash="8296f416c47ae4b66fa6bdf3259b1015"/><file name="default.sass" hash="90e19da7fd8144eeab4d93e5d3adb3bd"/><file name="default_imported.sass" hash="dbea23754dce7bc6c0f7ff69863c05c5"/><file name="each.css" hash="3f84fdb19433d6c2fb0e63c60c06d072"/><file name="each.scss" hash="9661d8222338cfdd6ba8ff771f1c881c"/><file name="expanded.css" hash="88ee2a16c4d88965bcbcf573a2d7c0fa"/><file name="expanded.sass" hash="66dbccbf13e56c23c9b12401ef4edb2d"/><file name="extend.css" hash="c4e9ba7d8748202d2c1351d5b69e3353"/><file name="extend.sass" hash="f34bd79d09364600631ea4889232ad64"/><file name="extend_included.css" hash="3c3e70c49794a7ff76aeb9a3402cf7bc"/><file name="extend_included.scss" hash="be61d8166e45b16c08e49087985ed1fb"/><file name="extend_placeholders.css" hash="369b772056769bece364221f3c069a8e"/><file name="extend_placeholders.scss" hash="4af5f1ee5888e7cd6cf6c6de45dbfc17"/><file name="filters.css" hash="f37ab5406ea00310513ce2e114cf6f07"/><file name="filters.scss" hash="ea989dd11a1d2a147b72d748b3a9c8c9"/><file name="functions.css" hash="a9da72a84bba8729e82dac08190a79d2"/><file name="functions.scss" hash="c9669b01b11b3abe4d82f701180ac2b0"/><file name="holmes.css" hash="07772c914ace61121cba53beb6ad8ca6"/><file name="holmes.sass" hash="e2199b90032b5f14a4dfc5233a915223"/><file name="hsl-functions.css" hash="b90a44e5919a286a8a62040f211b3580"/><file name="hsl-functions.scss" hash="fa055c7d603b5436613ecac898351cae"/><file name="if.css" hash="82391ad41348b41fc209cca5412ed740"/><file name="if.sass" hash="c3a27a421eb7e3d463918e189195b573"/><file name="if_parentheses.css" hash="7f5bc7f906a7cd678c9598c2e5650833"/><file name="if_parentheses.scss" hash="5140ac11b185061d3c5f7dc238e8ee86"/><file name="import.css" hash="3c8abb5481ee0c0002916b49681af2a5"/><file name="import.sass" hash="4d43389aa785393a47d57734724dad2f"/><file name="import_content.css" hash="4b78a566882b2768336f603d54f73fa4"/><file name="import_content.sass" hash="2db9b7a5b9a581e9f44256b6c8dbedd1"/><file name="importee.sass" hash="606678a5d48f7653f6d8e2e327109310"/><file name="interpolation.css" hash="ef048c83424f05a9c0882007ba0f4958"/><file name="interpolation.scss" hash="ce66433664f7f37277a8d4726a39556c"/><file name="introspection.css" hash="0d9f0e64e263388ec0e87eadef41193e"/><file name="introspection.scss" hash="9d57f03789f7a947ce62d6ab0320f886"/><file name="line_numbers.css" hash="802e2285df194c362503f849647a1380"/><file name="line_numbers.sass" hash="4770a812ab401d2bd35b352408623a17"/><file name="list.css" hash="4dd913d85cf2a28cb12d8af0f622ce03"/><file name="list.scss" hash="24f96a097c84d0da64cb3e753e2439ee"/><file name="list_empty.css" hash="c2fae66e0a28506f1733ac469a1c95ec"/><file name="list_empty.scss" hash="25d245b57859102ba6b36c12e89f3e7e"/><file name="list_variable.css" hash="d10df2dc91b4221bbfe4c3464bd34d5b"/><file name="list_variable.scss" hash="17a541748f730b9da21275a75852cf4e"/><file name="media.css" hash="409f2c0c468598dc19067376a796828f"/><file name="media.scss" hash="1fadbcd19113ff5855d1137be0693799"/><file name="media_in_for.css" hash="fd8292f715cc999ba7b64f8224c40a8a"/><file name="media_in_for.scss" hash="ad7702a6b95e121da52b93d69d782683"/><file name="media_in_mixin.css" hash="8c2bd3f961ab4336c55a5249f78e6bf4"/><file name="media_in_mixin.scss" hash="084e6f0edd3da537020a43d7ce8dbac4"/><file name="media_in_mixin_in_mixin.css" hash="8adc138ca27531ac5693c7e2274fdf9f"/><file name="media_in_mixin_in_mixin.scss" hash="049301e720820f076ceec6cc08037ede"/><file name="misc-functions.css" hash="7da15f26cab9b6df784ce1e37e9a30f1"/><file name="misc-functions.scss" hash="b133df9bb8cf346a3e6d3b3612c1de64"/><file name="misc.css" hash="a05a0a6b49ddbfdd803e92c5abe97594"/><file name="misc.scss" hash="36b58121127544b6a8179ae8a0c90a35"/><file name="mixin-content.css" hash="1b2490ce75d60d2b0c495a5db87a9f49"/><file name="mixin-content.sass" hash="41fa6bbd93b8d0b4ea8826fdd5585381"/><file name="mixin-content.scss" hash="f3252f583aac7dd5bbb7017fbd5654df"/><file name="mixin-ja1.css" hash="c551c8ffd0723e1c9e5795708d5dbda5"/><file name="mixin-ja1.sass" hash="90d3f2653ccbccbc00a9009bd31f8071"/><file name="mixin-list-params.css" hash="47064a4d242dfec9debba53326e529f3"/><file name="mixin-list-params.scss" hash="34478559346aec44c56c867a6b898af3"/><file name="mixin-params.css" hash="1a1f609e66c1dbe24383fe6855e95526"/><file name="mixin-params.scss" hash="a874ab4cacc02475acc827c956275cfe"/><file name="mixin-rgba-param.css" hash="bc5dc6caac3c74b37b82b1ed3cc2e553"/><file name="mixin-rgba-param.scss" hash="961219de858ecf7c17f2f7df24cf68cb"/><file name="mixin_bork.sass" hash="259fd0cca5a94583c0d406646b3217eb"/><file name="mixin_in_mixin.css" hash="46690de92ec525f39d5568bc2e46ee54"/><file name="mixin_in_mixin.scss" hash="0a6bef40d3215b63bb9f972896784a89"/><file name="mixin_setvar.css" hash="757520a01eca279c109d494d7fb4cd02"/><file name="mixin_setvar.scss" hash="12cd65c514056b3c0df1e4e92640a808"/><file name="mixins.css" hash="76ea6005844a4339745b1afe66274c74"/><file name="mixins.sass" hash="55fb1a104a59d6e5411987447af96b55"/><file name="multiline.css" hash="4a3d9bfe75a3b98c52ed95f3d785b079"/><file name="multiline.sass" hash="2f4ff6cfefa20eece2830170e29ea25e"/><file name="nested-media.css" hash="4fc2c8503b918fe9add9fcb230215fe2"/><file name="nested-media.scss" hash="2ee9901f1413f1f0839cfdc9b2ea00af"/><file name="nested.css" hash="26bd112a486652342cbfd55060552576"/><file name="nested.sass" hash="0bdc5d64efc02766544553f968bb82fd"/><file name="nested_bork1.sass" hash="56fa9072b6cc553909bfbd18f571a11d"/><file name="nested_bork2.sass" hash="999ae47bdbc6190972f0f52958870130"/><file name="nested_bork3.sass" hash="ccb998041d90cfe54a39f01afc4c4cc0"/><file name="nested_bork4.sass" hash="eed6453ea8564978c35d60f26a9bbb25"/><file name="nested_bork5.sass" hash="d6de98aee6d80aaecc1aa97311136003"/><file name="nested_import.css" hash="de8bc2a3cd89496c22ff564e65c2b046"/><file name="nested_import.sass" hash="b4493203dae52b5757ca91e17dd42e42"/><file name="nested_media.css" hash="d910a2026928133ce7235e8e1143a425"/><file name="nested_media.scss" hash="6e2dceddb572a0caa6f3959e00d332f4"/><file name="nested_mixin_bork.sass" hash="d9f57da9545e6c9a54d89bebe2f750b9"/><file name="nested_pseudo.css" hash="435b969153bc5030ceb8c251d241d358"/><file name="nested_pseudo.scss" hash="145d425a42541236d8952ea9f5e68ae7"/><file name="number.css" hash="000ca28603c30a49647d53bc5aabed94"/><file name="number.scss" hash="c585efaf419263809a1c91b76d8a0799"/><file name="opacity.css" hash="f54a7fbecddad66df7a6dae52bea4c21"/><file name="opacity.scss" hash="3a20a779e1becfcfaba90758d907c05e"/><file name="other-color.css" hash="45d9e1061d0e71b1c55362c2974b7bdf"/><file name="other-color.scss" hash="e2b8b86016461cbcdae6365ee14b0a5d"/><file name="parent_ref.css" hash="cbecced10861e9c060fa05187f94ee5f"/><file name="parent_ref.sass" hash="b5a3fe6fd3384b0853211e3515427796"/><file name="phpSassTest.php" hash="ce7206b374b0d65762851a6e3423658d"/><file name="phpunit.xml.dist" hash="3f11a2a97eb3d9b8bb48f60915daefda"/><file name="proprietary-selector.css" hash="6da7ab22184ed10ec679065835fc0f5f"/><file name="proprietary-selector.scss" hash="a7fa95fad2ae9aa0b93d8b49101eaf5f"/><file name="rgb-functions.css" hash="24177c2bc7b35526bf06334ea4174e27"/><file name="rgb-functions.scss" hash="7ad824885f782f15738ef67bbf00ae2a"/><file name="scss_import.css" hash="9eeec339e1ce59cbf3f2d29efab1382b"/><file name="scss_import.scss" hash="7ae409e52a06ad89582fe89063cf6bdd"/><file name="scss_importee.css" hash="7cad5194c7f7bb18e50f1ca093597033"/><file name="scss_importee.scss" hash="20c55fb516c7b137eadc6462f74cfa94"/><file name="splats.css" hash="3d11bc1d58858e4967ed498a3d75d008"/><file name="splats.scss" hash="4fab47d7391ff72a2e8d6de13c5e1b80"/><file name="string.css" hash="9f1482fe5b4964e96d24c00765c2503d"/><file name="string.scss" hash="f89f2aad48738bb1fa33a67f733e2e90"/><dir name="subdir"><dir name="nested_subdir"><file name="_nested_partial.sass" hash="24985866e9414ee4ef69621b738833ee"/><file name="nested_subdir.css" hash="759df6872a88c4174a39c32fe7d95a04"/><file name="nested_subdir.sass" hash="9e5e623f6765e28d5bec3bb2d3944eac"/></dir><file name="subdir.css" hash="ddd9dd41c2b72164a7ba634e359c2872"/><file name="subdir.sass" hash="acde24bd965d15ae3f19bf74b1f1c2a8"/></dir><file name="units.css" hash="ebc7390d227439bf2694a3ce29c54a6d"/><file name="units.sass" hash="040de247b027e6368c7edbc57d6e331f"/><file name="warn.css" hash="31c098880201803dc33c8785ecf3de26"/><file name="warn.sass" hash="47c7543a6a374523514669e108249f41"/><file name="warn_imported.sass" hash="2b7455acd686bf2511fce0b710874b01"/></dir><dir name="tree"><file name="SassCommentNode.php" hash="642f1a815d0e7dfc1106a518e8d87b31"/><file name="SassContentNode.php" hash="9e89188216cfe645bc0550e40027051b"/><file name="SassContext.php" hash="20760243da06e897f9c21d7ba1672fd4"/><file name="SassDebugNode.php" hash="9acd25b3581aa8d18313f3ac3d9e6e9a"/><file name="SassDirectiveNode.php" hash="039a39f8662e2131b2c0018a80337fde"/><file name="SassEachNode.php" hash="63aa2d6a2ade5a9a966f45edc70fabec"/><file name="SassElseNode.php" hash="6a6426a9d34047ac81eed7add893a179"/><file name="SassExtendNode.php" hash="02252a9b29559a959348fb87bb586d0e"/><file name="SassForNode.php" hash="0322a55c38b6f7fa0d4382f7e3972f4d"/><file name="SassFunctionDefinitionNode.php" hash="97b6440a715ce30922f1d3fafb7cfc3a"/><file name="SassIfNode.php" hash="af42d33a38ed91a5f5181b2458a2fa60"/><file name="SassImportNode.php" hash="a0b2c5b200cff2262e66327458054878"/><file name="SassMediaNode.php" hash="824aedfdb70bb658cbdb19e7e8fec1e1"/><file name="SassMixinDefinitionNode.php" hash="40763d3f0db2bcccd24e26262b2cc244"/><file name="SassMixinNode.php" hash="058bf4b74bcd7e99be00ff7890081881"/><file name="SassNode.php" hash="89f8a631e0381b736770c5b0da126f41"/><file name="SassNodeExceptions.php" hash="c8acde883ff1f08c56aaea36d3878c69"/><file name="SassPropertyNode.php" hash="388d56d83ab2e05909e8d04d849d786c"/><file name="SassReturnNode.php" hash="c951be13c91fad525b69fc09764e45ee"/><file name="SassRootNode.php" hash="423c2c19d8ad01638b42bf81b19a88fc"/><file name="SassRuleNode.php" hash="0828b0d29742e5e62f006a18961caa48"/><file name="SassVariableNode.php" hash="e4ab9cc2baab946a5b3cfc561baaf5cf"/><file name="SassWarnNode.php" hash="ba0da120f75efd07c57d040adf96a95d"/><file name="SassWhileNode.php" hash="b2c1328c15a28b4e37fed4d998d60dc9"/></dir><file name=".travis.yml" hash="d0ac6ce1cf8465183941fa3ac326a54e"/></dir></target></contents>
|
20 |
<compatible/>
|
21 |
-
<dependencies><required><php><min>5.
|
22 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Sass</name>
|
4 |
+
<version>1.1.4</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
|
7 |
<channel>community</channel>
|
12 |
You just need to create you sass file and add it to your layout like default css file.
|
13 |

|
14 |
This extension will then convert it to css file using phpSass or sass in command line if available</description>
|
15 |
+
<notes>Support of Magento CE 1.8
|
16 |
+
phpsass library updated.</notes>
|
17 |
<authors><author><name>Laurent Clouet</name><user>laurent35240</user><email>laurent35240@gmail.com</email></author></authors>
|
18 |
+
<date>2013-11-17</date>
|
19 |
+
<time>14:00:12</time>
|
20 |
+
<contents><target name="magecommunity"><dir name="Laurent"><dir name="Sass"><dir name="Helper"><file name="Data.php" hash="9c43132dba73d4b3f37ccfb91f0d5dbe"/></dir><dir name="Model"><dir name="Config"><file name="Style.php" hash="413571124dcf58d950200499a144420d"/></dir><dir name="Design"><file name="Package.php" hash="3c83af4c43fd94359541b7242852ca06"/></dir></dir><dir name="etc"><file name="config.xml" hash="e3f9875a014b5ed2f229b0d88a1654d1"/><file name="system.xml" hash="a2db1af0d9bae017b46805a80aedb442"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Laurent_Sass.xml" hash="4ad004de851457681610553228973c30"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Laurent_Sass.csv" hash="d9e8c184cbe72e810c7da9154581e1e4"/></dir><dir name="fr_FR"><file name="Laurent_Sass.csv" hash="676b2c597fe0b829fb2c48c1428c295f"/></dir></target><target name="magelib"><dir name="phpsass"><dir name="Extensions"><dir name="Compass"><file name="Compass.php" hash="ebb4044bcf18ec93da6c5a1d088304b6"/><dir name="stylesheets"><file name="_compass.scss" hash="bc769e7b7e94a717f9f4439978543900"/><file name="_lemonade.scss" hash="92e7ec85f14f46cf399a64115707dfe1"/><dir name="compass"><file name="_css3.scss" hash="7688063612bb668fffd22c32b95a2f5c"/><file name="_layout.scss" hash="d7445d578d56b5f0d6482d5df0b28a7b"/><file name="_reset-legacy.scss" hash="322b2e4617c8bf9e6c1ad02bef42ac18"/><file name="_reset.scss" hash="b3d1130413650cdc98b24777bf15afff"/><file name="_support.scss" hash="200db7d3bd7cd633b35c73c7d724a275"/><file name="_typography.scss" hash="73c901f7f8afd26c65dbadedffb87c1a"/><file name="_utilities.scss" hash="adb9de208e608e5bdd25189b4d4790a6"/><dir name="css3"><file name="_appearance.scss" hash="b624212e8f27e260b89e7aa84e598432"/><file name="_background-clip.scss" hash="9eab5a21f351b22e565278af805382b3"/><file name="_background-origin.scss" hash="57e96581316421882118c0d155a4a74f"/><file name="_background-size.scss" hash="674b66cc99bf60400b44f130d0c9d00d"/><file name="_border-radius.scss" hash="02749463ff3b0d0e68e42c76e6c18b66"/><file name="_box-shadow.scss" hash="13cb3d1733c1f7a60c542c44e639af55"/><file name="_box-sizing.scss" hash="5bc8b4f482fb878518d28a18dd453df9"/><file name="_box.scss" hash="ca45bf6d49507d042e5928cf1058909c"/><file name="_columns.scss" hash="b809552667f5876e115881ece27cbc8e"/><file name="_filter.scss" hash="ddc12210cb1d9cdcaad890e9d02601de"/><file name="_font-face.scss" hash="dfc84cb70f83cdbcde9dd3e51789363b"/><file name="_hyphenation.scss" hash="d3cf84dec3da60b4259fe2a9276421b5"/><file name="_images.scss" hash="c4d2fc1c4a1c78a68952de2694939fd2"/><file name="_inline-block.scss" hash="0ddfde10e192213f01dfa122d15bf473"/><file name="_opacity.scss" hash="36a24354a3b62b9b9c82690d1c008963"/><file name="_pie.scss" hash="8ec8261b6cdfef171774d6ad294dbcb7"/><file name="_regions.scss" hash="84db6e13237909b8c05e60c5735f43cc"/><file name="_shared.scss" hash="2a19ef6064fadd0c7bc1213878172ca2"/><file name="_text-shadow.scss" hash="b8dda78c05f393266e002b85885737af"/><file name="_transform-legacy.scss" hash="8d7c4ab98d1a165271ba64e859454c9f"/><file name="_transform.scss" hash="63d14c83ad4ebe0a25fe62b2e9b3a840"/><file name="_transition.scss" hash="ae7b441207aede5e831fd58d13d09103"/><file name="_user-interface.scss" hash="4293d8e1b99b864b6f1a1e341d281fbb"/></dir><dir name="layout"><file name="_grid-background.scss" hash="ebbb0813eeb27f1b102396275cd35e2b"/><file name="_sticky-footer.scss" hash="c10c67d6ebe9ca67709c982bbfed7178"/><file name="_stretching.scss" hash="3f59f9138e25943e4a7def3aa22704e5"/></dir><dir name="reset"><file name="_utilities-legacy.scss" hash="b3a4fd8ac50ace1aa1e607d4d926be45"/><file name="_utilities.scss" hash="c84668ad95fd7c53b77bd015452dd416"/></dir><dir name="typography"><file name="_links.scss" hash="862a5096f3a03597aab1be4e9dc76c64"/><file name="_lists.scss" hash="0e8662119de52a98ac3e601e086bbf53"/><file name="_text.scss" hash="4d3e129baa58fb176ded67c97bbf5b0a"/><file name="_vertical_rhythm.scss" hash="80869e4543f6f4e7ec93e52419d9a6e9"/><dir name="links"><file name="_hover-link.scss" hash="329c8ea4f1460cadf695e8d830c33a80"/><file name="_link-colors.scss" hash="9a4a09d3f9121c10f403a1fa333725dc"/><file name="_unstyled-link.scss" hash="3439d86d2f28c345864a7337c99db069"/></dir><dir name="lists"><file name="_bullets.scss" hash="9d733d179b5dcc005ef07535c16abe2a"/><file name="_horizontal-list.scss" hash="14a893eaa879be04e2ed636ab524b8f7"/><file name="_inline-block-list.scss" hash="f96c6c754473084d0af9d07b6d85cf44"/><file name="_inline-list.scss" hash="898ffa6ae6c13c5df2730172d618dece"/></dir><dir name="text"><file name="_ellipsis.scss" hash="a4765ddc9555f114ff59ae1a582f3caa"/><file name="_force-wrap.scss" hash="def5a5579399a9d35d845d3133338e3c"/><file name="_nowrap.scss" hash="e2cf48586ed5a33ab90a09e346020afc"/><file name="_replacement.scss" hash="e20cb6a854d0a9adb9bd7a879cb257a3"/></dir></dir><dir name="utilities"><file name="_color.scss" hash="4f6252c899a6f25c57ec1b4e9052e55b"/><file name="_general.scss" hash="7a90acc34a01d65ccc38f6dd6225229a"/><file name="_print.scss" hash="eb1d910e8aea90d23b76adf27323abe8"/><file name="_sprites.scss" hash="5f57e9b3f79df0ed70b7321aa55a1a2d"/><file name="_tables.scss" hash="836327d928e513dc737897356d7ba15b"/><dir name="color"><file name="_contrast.scss" hash="735478c5e04e31030afca1e36bf8e398"/></dir><dir name="general"><file name="_clearfix.scss" hash="58fd0d07999140b25bddb4e5c1d49a17"/><file name="_float.scss" hash="5c273f43ca3a3d409c08151ac4f86786"/><file name="_hacks.scss" hash="98ede0f56175f5fb08b3ecd982c27309"/><file name="_min.scss" hash="26a0f6fdad1f7ff71f40ff92eda4f56c"/><file name="_tabs.scss" hash="68b329da9893e34099c7d8ad5cb9c940"/><file name="_tag-cloud.scss" hash="ae7c8c97b4b3142eac7d3c279a5a729c"/></dir><dir name="sprites"><file name="_base.scss" hash="cc4f45b711e8d7fc11aaecd5a54f3744"/><file name="_sprite-img.scss" hash="2deeab732747a9da12f965e133fd795f"/></dir><dir name="tables"><file name="_alternating-rows-and-columns.scss" hash="aa6884db2666742519eb7a4c399767b3"/><file name="_borders.scss" hash="2ac334630de78ae00941857bcbf098d5"/><file name="_scaffolding.scss" hash="4144e427ff1f2a6a9ffdfd3bd641e477"/></dir></dir></dir></dir></dir><file name="ExtensionInterface.php" hash="f02f77afac08968fca0ca8f7cd750456"/><dir name="Own"><file name="Own.php" hash="fb185a20331ce4f185d7fdc318bf0b50"/><dir name="css"><dir name="test"><dir name="test2"><file name="test.scss" hash="b406241e81f4cbd2509a3a7daa50ba6e"/></dir></dir></dir></dir><file name="README.md" hash="0adcca717d8c0113986c95cfa6fa341f"/><dir name="Susy"><file name="Susy.php" hash="36a66b10b093bfa6d09e10f84f5c7d18"/><dir name="stylesheets"><file name="_susy.scss" hash="e60bb0cc5234c86628f4e0345bd2d48a"/><dir name="susy"><file name="_background.scss" hash="e7125e6d00deae7955c61ef9ce5b7557"/><file name="_functions.scss" hash="33d52f0bb6a333da77ac8c4482a1d862"/><file name="_grid.scss" hash="687c942dcaba8b87dac49db2d734e594"/><file name="_isolation.scss" hash="8e097d991625106869a96101bdc2bde4"/><file name="_margin.scss" hash="cb03e121a2800a47d569b456f247a0e4"/><file name="_media.scss" hash="89c7da945f0159b5e97ce705e8d06ae6"/><file name="_padding.scss" hash="b775d9b8f5465ae985da128e31818342"/><file name="_settings.scss" hash="e9942cc79f66826c45c525705aca4c5b"/><file name="_support.scss" hash="7c51df6bd18e85e6954b46e37b47db48"/><file name="_units.scss" hash="fea6309f28d01dc5cbf3fa8503f6bfae"/></dir></dir></dir><file name="example.php" hash="909400c241ad5d58484d600b7d0c4c92"/><file name="example.scss" hash="1c36b8695ac3d22afa9caa72a5e0a96f"/><file name="theme.scss" hash="7210d729d56c93a23b91d4d280570e17"/></dir><file name="README.md" hash="f680aedff15c35475551bf0e0652be57"/><file name="SassException.php" hash="1b481a8b5ddaa54b372ada4eb8598bb5"/><file name="SassFile.php" hash="76ba06279ded72bb92388ec51c32b560"/><file name="SassParser.php" hash="538f2a5a5795d7dfd065d9b80b9aaf1d"/><file name="VERSION" hash="fc3abbf04899a7be14a6aef73d83c120"/><file name="compile-apache.php" hash="7a95ffbe3baf88cd27260645e51d326d"/><file name="composer.json" hash="fb5dad84d70d71d3ad3ea36e06238c21"/><dir name="renderers"><file name="SassCompactRenderer.php" hash="efa3e80cb179be28b933c674cd06d70b"/><file name="SassCompressedRenderer.php" hash="a76e47ecc939efb39ad3bd091d90cc52"/><file name="SassExpandedRenderer.php" hash="938e703678e01367f8bfbfc0af2c9aca"/><file name="SassNestedRenderer.php" hash="963cade34043342728476d4b80a8f66d"/><file name="SassRenderer.php" hash="cba7988395cfc8ceba91dd1ae5777abd"/></dir><dir name="script"><file name="SassScriptFunction.php" hash="1682579a7b1fe57ba5ae30d52e7effc2"/><file name="SassScriptFunctions.php" hash="d423c2837d5c72443ed37926b1e0b4e4"/><file name="SassScriptLexer.php" hash="888286d5b2542bcf57f292966953f3ad"/><file name="SassScriptOperation.php" hash="b4f2eabeedd761157c378d4b36272b65"/><file name="SassScriptParser.php" hash="122201f80fb07cb78b5a1d32f4ec2a78"/><file name="SassScriptParserExceptions.php" hash="b24e0948e0e07f38bcfded7ddd0220ce"/><file name="SassScriptVariable.php" hash="b7450d09a86722cb89755fdc259820dd"/><dir name="literals"><file name="SassBoolean.php" hash="09644008ffd1b31bd13d4191fbcbdfa1"/><file name="SassColour.php" hash="05e81b7dfc201eeebecec47a96269055"/><file name="SassList.php" hash="9c1a851b068515b08d7c0bdb0c01d355"/><file name="SassLiteral.php" hash="77cf2a7af40aeaea5f27a2f055949aad"/><file name="SassLiteralExceptions.php" hash="dee1ed83e9fbbb173c2d1ae8a3cd5ba8"/><file name="SassNumber.php" hash="953e230977d422496526cc6cbc64e829"/><file name="SassString.php" hash="3a6350304d07995a93c68824628bcd3a"/></dir></dir><file name="test.css" hash="1655ffa4e91349bbe84d9e9f87b5ae39"/><file name="test.php" hash="811210b59e0b2b0e243a53c7328f9d26"/><dir name="tests"><file name="_imported_charset_ibm866.sass" hash="92b1d97a137e4219bb7796d7751aa847"/><file name="_imported_charset_utf8.sass" hash="51489125c07d0e8f2b055295d40d2549"/><file name="_imported_content.sass" hash="aafd4b9ba2de82e4f977e04934f204d7"/><file name="_partial.sass" hash="529fb954d7e0f6b42c484c869e60fbcf"/><file name="alt.css" hash="d48efc67765cb14b1c532b36b036a064"/><file name="alt.sass" hash="66be58fb872cd96be90fb95425a0aadf"/><file name="alt.scss" hash="ec1074aaba9b4a1ef3933d091c547c63"/><file name="basic.css" hash="22c341ec6e41dba84606032a40ea21c3"/><file name="basic.sass" hash="450faf5ca8e4bacefd01a74509ae135c"/><file name="bork1.sass" hash="0608533ebc4c4a16ddff507f818a709e"/><file name="bork2.sass" hash="036c6e0bcebc36908f9093d1b536ceb1"/><file name="bork3.sass" hash="ad06e4551ead8422ac443ae0cad7994b"/><file name="bork4.sass" hash="0bd4b0aed58208f5abf4418eb9672ef9"/><file name="bork5.sass" hash="e467427a1e928d1d72ef8db10482e262"/><file name="colour-nth.css" hash="8e457058415890dd4aac86f75a6e39e4"/><file name="colour-nth.scss" hash="3de860789a01fa9b5cf2d9a74a85dba7"/><file name="comments.css" hash="0ca95a61ccc49717e465173fb0c2e6c6"/><file name="comments.sass" hash="41bb5d2d2e14e3dd16c8b0296608a00e"/><file name="compact.css" hash="96105d0147b6881651b723eabe303f65"/><file name="compact.sass" hash="d51cfe7db78fe0d81793c7e24cb32e46"/><file name="complex.css" hash="3ffea6ccf80b24cc136bb102b3b41a67"/><file name="complex.sass" hash="b1426382fb915456b5efc0877ae7072d"/><file name="compressed.css" hash="1975f89cc758e39302d317578fdfdedb"/><file name="compressed.sass" hash="d51cfe7db78fe0d81793c7e24cb32e46"/><file name="content.css" hash="0c0892c48d74761fee54e09ccba6e662"/><file name="content.scss" hash="e624a12355435c147c0772f9fd1fe065"/><file name="css3.css" hash="8b2a0df29de7f2158baa3e97e76d91f2"/><file name="css3.scss" hash="819f570dae1e0c8c77007a03a2642158"/><file name="default.css" hash="8296f416c47ae4b66fa6bdf3259b1015"/><file name="default.sass" hash="90e19da7fd8144eeab4d93e5d3adb3bd"/><file name="default_imported.sass" hash="dbea23754dce7bc6c0f7ff69863c05c5"/><file name="each.css" hash="3f84fdb19433d6c2fb0e63c60c06d072"/><file name="each.scss" hash="9661d8222338cfdd6ba8ff771f1c881c"/><file name="expanded.css" hash="88ee2a16c4d88965bcbcf573a2d7c0fa"/><file name="expanded.sass" hash="66dbccbf13e56c23c9b12401ef4edb2d"/><file name="extend.css" hash="c4e9ba7d8748202d2c1351d5b69e3353"/><file name="extend.sass" hash="f34bd79d09364600631ea4889232ad64"/><file name="extend_included.scss" hash="be61d8166e45b16c08e49087985ed1fb"/><file name="extend_placeholders.css" hash="369b772056769bece364221f3c069a8e"/><file name="extend_placeholders.scss" hash="4af5f1ee5888e7cd6cf6c6de45dbfc17"/><file name="filters.css" hash="f37ab5406ea00310513ce2e114cf6f07"/><file name="filters.scss" hash="ea989dd11a1d2a147b72d748b3a9c8c9"/><file name="functions.css" hash="0a039fdec50d756df0ca5430fdc25a0a"/><file name="functions.scss" hash="c9669b01b11b3abe4d82f701180ac2b0"/><file name="holmes.css" hash="07772c914ace61121cba53beb6ad8ca6"/><file name="holmes.sass" hash="e2199b90032b5f14a4dfc5233a915223"/><file name="hsl-functions.css" hash="b90a44e5919a286a8a62040f211b3580"/><file name="hsl-functions.scss" hash="fa055c7d603b5436613ecac898351cae"/><file name="if.css" hash="82391ad41348b41fc209cca5412ed740"/><file name="if.sass" hash="c3a27a421eb7e3d463918e189195b573"/><file name="if_parentheses.css" hash="7f5bc7f906a7cd678c9598c2e5650833"/><file name="if_parentheses.scss" hash="5140ac11b185061d3c5f7dc238e8ee86"/><file name="import.css" hash="3c8abb5481ee0c0002916b49681af2a5"/><file name="import.sass" hash="4d43389aa785393a47d57734724dad2f"/><file name="import_content.css" hash="4b78a566882b2768336f603d54f73fa4"/><file name="import_content.sass" hash="2db9b7a5b9a581e9f44256b6c8dbedd1"/><file name="importee.sass" hash="606678a5d48f7653f6d8e2e327109310"/><file name="interpolation.css" hash="ef048c83424f05a9c0882007ba0f4958"/><file name="interpolation.scss" hash="ce66433664f7f37277a8d4726a39556c"/><file name="introspection.css" hash="0d9f0e64e263388ec0e87eadef41193e"/><file name="introspection.scss" hash="9d57f03789f7a947ce62d6ab0320f886"/><file name="line_numbers.css" hash="802e2285df194c362503f849647a1380"/><file name="line_numbers.sass" hash="4770a812ab401d2bd35b352408623a17"/><file name="list.css" hash="4dd913d85cf2a28cb12d8af0f622ce03"/><file name="list.scss" hash="24f96a097c84d0da64cb3e753e2439ee"/><file name="list_empty.css" hash="c2fae66e0a28506f1733ac469a1c95ec"/><file name="list_empty.scss" hash="25d245b57859102ba6b36c12e89f3e7e"/><file name="list_variable.css" hash="d10df2dc91b4221bbfe4c3464bd34d5b"/><file name="list_variable.scss" hash="17a541748f730b9da21275a75852cf4e"/><file name="media.css" hash="409f2c0c468598dc19067376a796828f"/><file name="media.scss" hash="1fadbcd19113ff5855d1137be0693799"/><file name="media_in_for.css" hash="fd8292f715cc999ba7b64f8224c40a8a"/><file name="media_in_for.scss" hash="ad7702a6b95e121da52b93d69d782683"/><file name="media_in_mixin.css" hash="8c2bd3f961ab4336c55a5249f78e6bf4"/><file name="media_in_mixin.scss" hash="084e6f0edd3da537020a43d7ce8dbac4"/><file name="media_in_mixin_in_mixin.css" hash="8adc138ca27531ac5693c7e2274fdf9f"/><file name="media_in_mixin_in_mixin.scss" hash="049301e720820f076ceec6cc08037ede"/><file name="misc-functions.css" hash="7da15f26cab9b6df784ce1e37e9a30f1"/><file name="misc-functions.scss" hash="b133df9bb8cf346a3e6d3b3612c1de64"/><file name="misc.css" hash="a05a0a6b49ddbfdd803e92c5abe97594"/><file name="misc.scss" hash="36b58121127544b6a8179ae8a0c90a35"/><file name="mixin-content.css" hash="1b2490ce75d60d2b0c495a5db87a9f49"/><file name="mixin-content.sass" hash="41fa6bbd93b8d0b4ea8826fdd5585381"/><file name="mixin-content.scss" hash="f3252f583aac7dd5bbb7017fbd5654df"/><file name="mixin-ja1.css" hash="c551c8ffd0723e1c9e5795708d5dbda5"/><file name="mixin-ja1.sass" hash="90d3f2653ccbccbc00a9009bd31f8071"/><file name="mixin-list-params.css" hash="47064a4d242dfec9debba53326e529f3"/><file name="mixin-list-params.scss" hash="34478559346aec44c56c867a6b898af3"/><file name="mixin-params.css" hash="1a1f609e66c1dbe24383fe6855e95526"/><file name="mixin-params.scss" hash="a874ab4cacc02475acc827c956275cfe"/><file name="mixin-rgba-param.css" hash="bc5dc6caac3c74b37b82b1ed3cc2e553"/><file name="mixin-rgba-param.scss" hash="961219de858ecf7c17f2f7df24cf68cb"/><file name="mixin_bork.sass" hash="259fd0cca5a94583c0d406646b3217eb"/><file name="mixin_in_mixin.css" hash="46690de92ec525f39d5568bc2e46ee54"/><file name="mixin_in_mixin.scss" hash="0a6bef40d3215b63bb9f972896784a89"/><file name="mixin_setvar.css" hash="757520a01eca279c109d494d7fb4cd02"/><file name="mixin_setvar.scss" hash="12cd65c514056b3c0df1e4e92640a808"/><file name="mixins.css" hash="76ea6005844a4339745b1afe66274c74"/><file name="mixins.sass" hash="55fb1a104a59d6e5411987447af96b55"/><file name="multiline.css" hash="4a3d9bfe75a3b98c52ed95f3d785b079"/><file name="multiline.sass" hash="2f4ff6cfefa20eece2830170e29ea25e"/><file name="nested-media.css" hash="4fc2c8503b918fe9add9fcb230215fe2"/><file name="nested-media.scss" hash="2ee9901f1413f1f0839cfdc9b2ea00af"/><file name="nested.css" hash="26bd112a486652342cbfd55060552576"/><file name="nested.sass" hash="0bdc5d64efc02766544553f968bb82fd"/><file name="nested_bork1.sass" hash="56fa9072b6cc553909bfbd18f571a11d"/><file name="nested_bork2.sass" hash="999ae47bdbc6190972f0f52958870130"/><file name="nested_bork3.sass" hash="ccb998041d90cfe54a39f01afc4c4cc0"/><file name="nested_bork4.sass" hash="eed6453ea8564978c35d60f26a9bbb25"/><file name="nested_bork5.sass" hash="d6de98aee6d80aaecc1aa97311136003"/><file name="nested_import.css" hash="de8bc2a3cd89496c22ff564e65c2b046"/><file name="nested_import.sass" hash="b4493203dae52b5757ca91e17dd42e42"/><file name="nested_media.css" hash="d910a2026928133ce7235e8e1143a425"/><file name="nested_media.scss" hash="6e2dceddb572a0caa6f3959e00d332f4"/><file name="nested_mixin_bork.sass" hash="d9f57da9545e6c9a54d89bebe2f750b9"/><file name="nested_pseudo.css" hash="435b969153bc5030ceb8c251d241d358"/><file name="nested_pseudo.scss" hash="145d425a42541236d8952ea9f5e68ae7"/><file name="number.css" hash="000ca28603c30a49647d53bc5aabed94"/><file name="number.scss" hash="c585efaf419263809a1c91b76d8a0799"/><file name="opacity.css" hash="f54a7fbecddad66df7a6dae52bea4c21"/><file name="opacity.scss" hash="3a20a779e1becfcfaba90758d907c05e"/><file name="other-color.css" hash="45d9e1061d0e71b1c55362c2974b7bdf"/><file name="other-color.scss" hash="e2b8b86016461cbcdae6365ee14b0a5d"/><file name="parent_ref.css" hash="cbecced10861e9c060fa05187f94ee5f"/><file name="parent_ref.sass" hash="b5a3fe6fd3384b0853211e3515427796"/><file name="phpSassTest.php" hash="85b1d8fa19f923311ad45c00672a3a26"/><file name="phpunit.xml.dist" hash="3f11a2a97eb3d9b8bb48f60915daefda"/><file name="proprietary-selector.css" hash="6da7ab22184ed10ec679065835fc0f5f"/><file name="proprietary-selector.scss" hash="a7fa95fad2ae9aa0b93d8b49101eaf5f"/><file name="rgb-functions.css" hash="24177c2bc7b35526bf06334ea4174e27"/><file name="rgb-functions.scss" hash="7ad824885f782f15738ef67bbf00ae2a"/><file name="scss_import.css" hash="9eeec339e1ce59cbf3f2d29efab1382b"/><file name="scss_import.scss" hash="7ae409e52a06ad89582fe89063cf6bdd"/><file name="scss_importee.css" hash="7cad5194c7f7bb18e50f1ca093597033"/><file name="scss_importee.scss" hash="20c55fb516c7b137eadc6462f74cfa94"/><file name="splats.css" hash="3d11bc1d58858e4967ed498a3d75d008"/><file name="splats.scss" hash="4fab47d7391ff72a2e8d6de13c5e1b80"/><file name="string.css" hash="9f1482fe5b4964e96d24c00765c2503d"/><file name="string.scss" hash="f89f2aad48738bb1fa33a67f733e2e90"/><dir name="subdir"><dir name="nested_subdir"><file name="_nested_partial.sass" hash="24985866e9414ee4ef69621b738833ee"/><file name="nested_subdir.css" hash="759df6872a88c4174a39c32fe7d95a04"/><file name="nested_subdir.sass" hash="9e5e623f6765e28d5bec3bb2d3944eac"/></dir><file name="subdir.css" hash="ddd9dd41c2b72164a7ba634e359c2872"/><file name="subdir.sass" hash="acde24bd965d15ae3f19bf74b1f1c2a8"/></dir><file name="units.css" hash="ebc7390d227439bf2694a3ce29c54a6d"/><file name="units.sass" hash="040de247b027e6368c7edbc57d6e331f"/><file name="warn.css" hash="31c098880201803dc33c8785ecf3de26"/><file name="warn.sass" hash="47c7543a6a374523514669e108249f41"/><file name="warn_imported.sass" hash="2b7455acd686bf2511fce0b710874b01"/></dir><dir name="tree"><file name="SassCommentNode.php" hash="807249e546eb578d6087ed95e2f4e305"/><file name="SassContentNode.php" hash="2a20a58b2e1e43b82cac4cff908aa241"/><file name="SassContext.php" hash="4b7dc36ef0866a3678a0c53c5bb5a4b6"/><file name="SassDebugNode.php" hash="07c197af56822312088191a73e3225ff"/><file name="SassDirectiveNode.php" hash="813e62abcd27a49bbb2062e5a3e54acf"/><file name="SassEachNode.php" hash="c514b6b558faf12a5c56b233a9f4b01a"/><file name="SassElseNode.php" hash="1b5e603ccf2de0edfda2f7075e642dd2"/><file name="SassExtendNode.php" hash="d415ada9c7974775cc00de239ad8d8a2"/><file name="SassForNode.php" hash="9fc5364ce7a8c9557e26d62bd0aaeb59"/><file name="SassFunctionDefinitionNode.php" hash="67a5bf31c0e8f0225161f9ecdd61084e"/><file name="SassIfNode.php" hash="586e0ac2339af4e0836ee15168398801"/><file name="SassImportNode.php" hash="ea27128d9923cd0af8b7dae8b49edd69"/><file name="SassMediaNode.php" hash="8f88befb058bdb6f02c9f66bbca54b7a"/><file name="SassMixinDefinitionNode.php" hash="27fb3a6e0b141b8413ea657986950dcb"/><file name="SassMixinNode.php" hash="0112bd92ca1ddb3a180b28797bc8395b"/><file name="SassNode.php" hash="218a90269cb7f32ff47f94dee2af8b59"/><file name="SassNodeExceptions.php" hash="be582689b346f1ff54eba30d3e6550f5"/><file name="SassPropertyNode.php" hash="33312fdc1b87e96454363b3197f5ca9d"/><file name="SassReturnNode.php" hash="8218ceb0ed55b37c901d31952330d9c5"/><file name="SassRootNode.php" hash="5330f46536b9a7c8212b51516b35490a"/><file name="SassRuleNode.php" hash="3f3d01641155acdddd1322f3043b20dd"/><file name="SassVariableNode.php" hash="d15e503dd71000ae9100b473d1436f43"/><file name="SassWarnNode.php" hash="70875fe1e5d4e806def3d9b4984bb855"/><file name="SassWhileNode.php" hash="809afdba4213c5549dc7923125dbe10a"/></dir><file name=".travis.yml" hash="d0ac6ce1cf8465183941fa3ac326a54e"/></dir></target></contents>
|
21 |
<compatible/>
|
22 |
+
<dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
|
23 |
</package>
|