<?php
/*
* css_parser.php
*
* @(#) $Id: css_parser.php,v 1.13 2009/08/21 05:02:26 mlemos Exp $
*
*/
/*
{metadocument}<?xml version="1.0" encoding="ISO-8859-1" ?>
<class>
<package>net.manuellemos.cssparser</package>
<version>@(#) $Id: css_parser.php,v 1.13 2009/08/21 05:02:26 mlemos Exp $</version>
<copyright>Copyright © (C) Manuel Lemos 2009</copyright>
<title>CSS parser</title>
<author>Manuel Lemos</author>
<authoraddress>mlemos-at-acm.org</authoraddress>
<documentation>
<idiom>en</idiom>
<purpose>.</purpose>
<usage>.</usage>
</documentation>
{/metadocument}
*/
class css_parser_class
{
/*
{metadocument}
<variable>
<name>error</name>
<type>STRING</type>
<value></value>
<documentation>
<purpose>Store the message that is returned when an error
occurs.</purpose>
<usage>Check this variable to understand what happened when a call to
any of the class functions has failed.<paragraphbreak />
This class uses cumulative error handling. This means that if one
class functions that may fail is called and this variable was
already set to an error message due to a failure in a previous call
to the same or other function, the function will also fail and does
not do anything.<paragraphbreak />
This allows programs using this class to safely call several
functions that may fail and only check the failure condition after
the last function call.<paragraphbreak />
Just set this variable to an empty string to clear the error
condition.</usage>
</documentation>
</variable>
{/metadocument}
*/
var $error = '';
/*
{metadocument}
<variable>
<name>error_position</name>
<type>INTEGER</type>
<value>-1</value>
<documentation>
<purpose>Point to the position of the markup data or file that
refers to the last error that occurred.</purpose>
<usage>Check this variable to determine the relevant position of the
document when a parsing error occurs.</usage>
</documentation>
</variable>
{/metadocument}
*/
var $error_position = -1;
/*
{metadocument}
<variable>
<name>ignore_syntax_errors</name>
<type>BOOLEAN</type>
<value>1</value>
<documentation>
<purpose>Specify whether the class should ignore syntax errors in
malformed documents.</purpose>
<usage>Set this variable to <booleanvalue>0</booleanvalue> if it is
necessary to verify whether markup data may be corrupted due to
to eventual bugs in the program that generated the
document.<paragraphbreak />
Currently the class only ignores some types of syntax errors.
Other syntax errors may still cause the
<functionlink>Parse</functionlink> to fail.</usage>
</documentation>
</variable>
{/metadocument}
*/
var $ignore_syntax_errors=1;
/*
{metadocument}
<variable>
<name>warnings</name>
<type>HASH</type>
<value></value>
<documentation>
<purpose>Return a list of positions of the original document that
contain syntax errors.</purpose>
<usage>Check this variable to retrieve eventual document syntax
errors that were ignored when the
<variablelink>ignore_syntax_errors</variablelink> is set to
<booleanvalue>1</booleanvalue>.<paragraphbreak />
The indexes of this array are the positions of the errors. The
array values are the corresponding syntax error messages.</usage>
</documentation>
</variable>
{/metadocument}
*/
var $warnings=array();
/*
{metadocument}
<variable>
<name>store_positions</name>
<type>BOOLEAN</type>
<value>1</value>
<documentation>
<purpose>.</purpose>
<usage>.</usage>
</documentation>
</variable>
{/metadocument}
*/
var $store_positions = 1;
/*
{metadocument}
<variable>
<name>track_lines</name>
<type>BOOLEAN</type>
<value>0</value>
<documentation>
<purpose>.</purpose>
<usage>.</usage>
</documentation>
</variable>
{/metadocument}
*/
var $track_lines = 0;
/* Private variables */
var $lines = array();
var $line_offset = 0;
var $last_line = 1;
var $last_carriage_return = 0;
/* Private functions */
Function SetError($error)
{
$this->error = $error;
return(0);
}
Function SetPositionedError($error, $position)
{
$this->error_position = $position;
return($this->SetError($error));
}
Function SetPositionedWarning($error, $position)
{
if(!$this->ignore_syntax_errors)
return($this->SetPositionedError($error, $position));
$this->warnings[$position]=$error;
return(1);
}
Function TrackLines($data)
{
$length = strlen($data);
if($this->track_lines
&& $length)
{
$line = $this->last_line;
$position = 0;
if($this->last_carriage_return)
{
if($data[0] == "\n")
++$position;
$this->lines[++$line] = $this->line_offset + $position;
$this->last_carriage_return = 0;
}
while($position < $length)
{
$position += strcspn($data, "\r\n", $position) ;
if($position >= $length)
break;
if($data[$position] == "\r")
{
++$position;
if($position >= $length)
{
$this->last_carriage_return = 1;
break;
}
if($data[$position] == "\n")
++$position;
$this->lines[++$line] = $this->line_offset + $position;
}
else
{
++$position;
$this->lines[++$line] = $this->line_offset + $position;
}
}
$this->last_line = $line;
$this->line_offset += $length;
}
}
Function DecodeCharacters(&$p, $e, $length, &$decoded)
{
$v = $this->v;
$decoded = '';
$t = $p;
for($d = 0; ($length == 0 || $d < $length) && $t < $e; ++$d)
{
$c = $v[$t];
if($c == '\\'
&& $p + 1 < $e)
{
$h = min(strspn($v, '0123456789abcdefABCDEF', $t + 1), 6);
if($h)
{
$x = HexDec($hex = substr($v, $t + 1, $h));
if($x <= 255)
$decoded .= Chr($x);
else
$decoded .= '\\'.$hex;
$t += $h + 1;
continue;
}
}
$decoded .= $c;
++$t;
}
$p = $t;
return(1);
}
Function DecodeCharacter(&$p, $one = 1)
{
$v = $this->v;
$l = strlen($v);
if($p >= $l)
return('');
if($this->v[$p] !== '\\'
|| !$this->DecodeCharacters($p, $l, 1, $d))
return($one ? $v[$p++] : '');
return($d);
}
Function SkipWhiteSpace(&$p)
{
$v = $this->v;
$l = strlen($v);
for(;$p<$l; ++$p)
{
switch($v[$p])
{
case ' ':
case "\n":
case "\r":
case "\t":
case "\xC":
break;
default:
return(1);
}
}
return(1);
}
Function ParseNMStart(&$p, &$start)
{
$start = null;
$s = $p;
$d = $this->DecodeCharacter($s, 0);
if(!preg_match("/^([_a-z]|[^\\0-\\177]|(\\\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\\f])?|\\\\[^\n\r\\f0-9a-f]))/i", $d !== '' ? $d : substr($this->v, $p), $m))
return(1);
$start = $m[1];
$p = ($d === '' ? $p + strlen($start) : $s);
return(1);
}
Function ParseNMChar(&$p, &$char)
{
$char = null;
$s = $p;
$d = $this->DecodeCharacter($s, 0);
if(!preg_match("/^([_a-z0-9-]|[^\\0-\\177]|(\\\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\\f])?|\\[^\n\r\\f0-9a-f]))/i", $d !== '' ? $d : substr($this->v, $p), $m))
return(1);
$char = $m[1];
$p = ($d === '' ? $p + strlen($char) : $s);
return(1);
}
Function ParseIdent(&$p, &$ident)
{
$ident = null;
$v = $this->v;
$l = strlen($v);
if($p >= $l)
return(1);
$i = $p;
if(!strcmp($v[$i], '-'))
{
++$i;
$value = '-';
}
else
$value = '';
if(!$this->ParseNMStart($i, $start))
return(0);
if(!IsSet($start))
return(1);
$value .= $start;
for(;;)
{
if(!$this->ParseNMChar($i, $char))
return(0);
if(!IsSet($char))
{
$p = $i;
$ident = $value;
return(1);
}
$value .= $char;
}
}
Function ParseFunction(&$p, &$function)
{
$function = null;
$f = $p;
if(!$this->ParseIdent($f, $ident))
return(0);
if(!IsSet($ident))
return(1);
$v = $this->v;
$l = strlen($v);
if($f < $l)
{
$d = $this->DecodeCharacter($f);
if($d === '(')
{
$function = $ident;
$p = $f;
}
}
return(1);
}
Function ParseString(&$p, &$string)
{
$string = null;
$v = $this->v;
$l = strlen($v);
if($p >= $l)
return(1);
switch($q = $v[$p])
{
case '"':
case "'":
$s = $p + 1;
break;
default:
return(1);
}
if(!preg_match("#^(([^\n\r\\f".$q."]|\\\\(\n|\r\n|\r|\\f)|((\\\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\\f])?)|\\\\[^\r\n\\f0-9a-f]))*)#i", substr($this->v, $s), $m))
return($this->SetPositionedError('invalid quoted string', $s));
$e = $s + strlen($m[1]);
if($e >= $l
|| strcmp($v[$e], $q))
return($this->SetPositionedError('unfinished quoted string', $e));
if(!$this->DecodeCharacters($s, $e, 0, $string))
return(0);
$p = $e + 1;
return(1);
}
Function ParseNumber(&$p, &$number)
{
$number = null;
$s = $p;
$d = $this->DecodeCharacter($s);
if(strspn($d, $match = '0123456789.') < 1)
return(1);
for($number = $d;;)
{
if($d[0] === '.')
$match = '0123456789';
$n = $s;
$d = $this->DecodeCharacter($s);
if(strspn($d, $match) < 1)
{
$p = $n;
return(1);
}
$number .= $d;
}
}
Function ParseDimension(&$p, &$value, &$unit)
{
$value = $unit = null;
$d = $p;
if(!$this->ParseNumber($d, $number))
return(0);
if(!IsSet($number))
return(1);
if(!$this->ParseIdent($d, $unit))
return(0);
if(!IsSet($unit))
return(1);
switch(strtolower($unit))
{
case 'in':
case 'cm':
case 'mm':
case 'em':
case 'ex':
case 'pt':
case 'pc':
case 'px':
$value = $number;
$p = $d;
break;
}
return(1);
}
Function ParsePercentage(&$p, &$percentage)
{
$value = $unit = null;
$d = $p;
if(!$this->ParseNumber($d, $number))
return(0);
if(!IsSet($number))
return(1);
if($d >= strlen($this->v)
|| strcmp($this->v[$d], '%'))
return(1);
$percentage = $number;
$p = $d + 1;
return(1);
}
Function ParseURI(&$p, &$uri)
{
$uri = null;
$v = $this->v;
$l = strlen($v);
$u = $p;
$start = 'url(';
if(!$this->DecodeCharacters($u, $l, 4, $d))
return(1);
if(strcmp($d, $start))
return(1);
if(!$this->SkipWhiteSpace($u))
return(0);
if(!$this->ParseString($u, $string))
return(0);
if(!IsSet($string))
{
if(!preg_match("/^(([!#\$%&*-~]|[^\\0-\\177]|(\\\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\\f])?|\\\\[^\n\r\\f0-9a-f]))*)/i", substr($v, $u), $m))
return($this->SetPositionedError('URL syntax error', $u));
$string = $m[1];
$u += strlen($string);
}
if(!$this->SkipWhiteSpace($u))
return(0);
$end = ')';
if(!$this->DecodeCharacters($u, $l, 1, $d))
return(1);
if(strcmp($d, $end))
return($this->SetPositionedError('URL syntax error', $u));
$uri = $string;
$p = $u;
return(1);
}
Function ParseName(&$p, &$name)
{
$name = null;
$v = $this->v;
$l = strlen($v);
$n = $p;
if(!$this->ParseNMChar($n, $char))
return(0);
if(!IsSet($char))
return(1);
for($p = $n, $name = $char;;)
{
if(!$this->ParseNMChar($p, $char))
return(0);
if(!IsSet($char))
return(1);
$name .= $char;
}
}
Function ParseHash(&$p, &$hash)
{
$hash = null;
$v = $this->v;
$l = strlen($v);
$h = $p;
if($p >= $l
|| strcmp($v[$h], '#'))
return(1);
++$h;
if(!$this->ParseName($h, $name))
return(0);
if(!IsSet($name))
return(1);
$hash = $name;
$p = $h;
return(1);
}
Function ParseAny(&$p, &$any)
{
$any = null;
$v = $this->v;
$l = strlen($v);
$s = $p;
if(!IsSet($any))
{
if(!$this->ParseURI($p, $uri))
return(0);
if(IsSet($uri))
{
$any = array(
'Type'=>'uri',
'URI'=>$uri
);
}
}
if(!IsSet($any))
{
if(!$this->ParseHash($p, $hash))
return(0);
if(IsSet($hash))
{
$any = array(
'Type'=>'hash',
'Hash'=>$hash
);
}
}
if(!IsSet($any))
{
if(!$this->ParseDimension($p, $value, $unit))
return(0);
if(IsSet($value))
{
$any = array(
'Type'=>'dimension',
'Value'=>$value,
'Unit'=>$unit
);
}
}
if(!IsSet($any))
{
if(!$this->ParsePercentage($p, $percentage))
return(0);
if(IsSet($percentage))
{
$any = array(
'Type'=>'percentage',
'Percentage'=>$percentage,
);
}
}
if(!IsSet($any))
{
if(!$this->ParseNumber($p, $number))
return(0);
if(IsSet($number))
{
$any = array(
'Type'=>'number',
'Number'=>$number
);
}
}
if(!IsSet($any))
{
$f = $p;
if(!$this->ParseFunction($f, $function))
return(0);
if(IsSet($function))
{
if(!$this->SkipWhiteSpace($f))
return(0);
$parameters = array();
for(;;)
{
if(!$this->ParseAny($f, $parameter))
return(0);
if(!IsSet($parameter))
break;
$parameters[] = $parameter;
}
if($f < $l
&& $this->DecodeCharacter($f) === ')')
{
$any = array(
'Type'=>'function',
'Function'=>$function,
'Parameters'=>$parameters
);
$p = $f;
}
}
}
if(!IsSet($any))
{
if(!$this->ParseString($p, $string))
return(0);
if(IsSet($string))
{
$any = array(
'Type'=>'string',
'String'=>$string
);
}
}
if(!IsSet($any))
{
if(!$this->ParseIdent($p, $ident))
return(0);
if(IsSet($ident))
{
$any = array(
'Type'=>'identifier',
'Identifier'=>$ident
);
}
}
if(!IsSet($any))
{
if($p < $l)
{
$a = $p;
switch($c = $this->DecodeCharacter($a))
{
case '"':
case "'":
case '{':
case '}':
case '(':
case ')':
case ';':
case '[':
case ']':
case ' ':
case "\n":
case "\r":
case "\t":
case "\xC":
break;
default:
$any = array(
'Type'=>'delimiter',
'Delimiter'=>$c
);
$p = $a;
break;
}
}
}
if(IsSet($any))
{
if(!$this->SkipWhiteSpace($p))
return(0);
if($this->store_positions)
$any['Position'] = $s;
}
return(1);
}
Function ParseProperty(&$p, &$property)
{
return($this->ParseIdent($p, $property));
}
Function ParseExpression(&$p, &$expression)
{
$expression = null;
$a = $p;
for($e = array();;)
{
if(!$this->ParseAny($a, $any))
return(0);
if(!IsSet($any))
break;
$e[] = $any;
}
if(count($e))
{
$expression = $e;
$p = $a;
return(1);
}
return(0);
}
Function ParsePriority(&$p, &$priority)
{
$priority = null;
return(1);
}
Function ParseDeclaration(&$p, &$declaration)
{
$declaration = null;
$v = $this->v;
$l = strlen($v);
$d = $p;
if(!$this->ParseProperty($d, $property))
return(0);
if(!IsSet($property)
|| $d >= $l
|| strcmp($v[$d], ':'))
return(1);
++$d;
if(!$this->SkipWhiteSpace($d))
return(0);
if(!$this->ParseExpression($d, $value))
return(0);
if(!IsSet($value))
return($this->SetPositionedWarning('invalid expression for property '.$property, $d));
if(!$this->ParsePriority($d, $priority))
return(0);
$declaration = array(
'Property'=>$property,
'Value'=>$value
);
if(IsSet($priority))
$declaration['Priority'] = 1;
if($this->store_positions)
$declaration['Position'] = $value[0]['Position'];
$p = $d;
return(1);
}
Function ParseProperties(&$p, &$properties)
{
$properties = null;
$v = $this->v;
$l = strlen($v);
if(!$this->SkipWhiteSpace($p))
return(0);
if(!$this->ParseDeclaration($p, $property))
return(0);
if(!IsSet($property))
return($this->SetPositionedError('it was not specified a valid property', $p));
$properties = array($property);
while($p < $l)
{
if(strcmp($v[$p], ';'))
return(1);
++$p;
if(!$this->SkipWhiteSpace($p))
return(0);
if($p >= $l)
break;
if(!$this->ParseDeclaration($p, $property))
return(0);
if(!IsSet($property))
return($this->SetPositionedError('it was not specified a valid style property after semi-colon', $p));
$properties[] = $property;
}
return(1);
}
Function ParseSelector(&$p, &$selector)
{
$selector = null;
$v = $this->v;
$l = strlen($v);
if(!$this->ParseAny($p, $any))
return(0);
if(!IsSet($any))
return(1);
$selector = array($any);
for(;;)
{
if(!$this->ParseAny($p, $any))
return(0);
if(!IsSet($any))
return(1);
$selector[] = $any;
}
return(1);
}
Function ParseRuleSet(&$p, &$ruleset)
{
$ruleset = null;
$v = $this->v;
$l = strlen($v);
$s = $p;
if(!$this->ParseSelector($s, $selector))
return(0);
if(!IsSet($selector)
|| $s >= $l
|| strcmp($v[$s], '{'))
return(1);
++$s;
if(!$this->SkipWhiteSpace($s))
return(0);
if(!$this->ParseDeclaration($s, $declaration))
return(0);
if(!IsSet($declaration))
return(1);
$properties = array($declaration);
for(;;)
{
if($s >= $l
|| strcmp($v[$s], ';'))
break;
++$s;
if(!$this->SkipWhiteSpace($s))
return(0);
$d = $s;
if(!$this->ParseDeclaration($d, $declaration))
return(0);
if(!IsSet($declaration))
break;
$properties[] = $declaration;
$s = $d;
}
if($s >= $l
|| strcmp($v[$s], '}'))
return(1);
++$s;
if(!$this->SkipWhiteSpace($s))
return(0);
$ruleset = array(
'Selector'=>$selector,
'Properties'=>$properties
);
if($this->store_positions)
$ruleset['Position'] = $p;
$p = $s;
return(1);
}
Function RewriteExpression($expression, &$rewrite)
{
$rewrite = '';
$te = count($expression);
for($e = 0; $e < $te; ++$e)
{
$position = (IsSet($expression[$e]['Position']) ? $expression[$e]['Position'] : -1);
switch($expression[$e]['Type'])
{
case 'delimiter':
$rewrite .= $expression[$e]['Delimiter'];
break;
case 'dimension':
$rewrite .= $expression[$e]['Value'].$expression[$e]['Unit'];
break;
case 'function':
if(!$this->RewriteExpression($expression[$e]['Parameters'], $parameters))
return(0);
$rewrite .= $expression[$e]['Function'].'('.$parameters.')';
break;
case 'hash':
$rewrite .= '#'.$expression[$e]['Hash'];
break;
case 'identifier':
$rewrite .= $expression[$e]['Identifier'];
break;
case 'number':
$rewrite .= $expression[$e]['Number'];
break;
case 'percentage':
$rewrite .= $expression[$e]['Percentage'].'%';
break;
case 'string':
$rewrite .= '"'.$expression[$e]['String'].'"';
break;
case 'uri':
$rewrite .= 'url('.$expression[$e]['URI'].')';
break;
default:
return($this->SetPositionedError('rewriting styles expressions of type '.$expression[$e]['Type'].' is not yet supported', $position));
}
}
return(1);
}
Function RewriteProperty($property, &$rewrite)
{
if(!$this->RewriteExpression($property['Value'], $value))
return(0);
$rewrite = $property['Property'].': '.$value;
return(1);
}
/* Public functions */
/*
{metadocument}
<function>
<name>GetPositionLine</name>
<type>BOOLEAN</type>
<documentation>
<purpose>.</purpose>
<usage>.</usage>
<returnvalue>.</returnvalue>
</documentation>
<argument>
<name>position</name>
<type>INTEGER</type>
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<argument>
<name>line</name>
<type>INTEGER</type>
<out />
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<argument>
<name>column</name>
<type>INTEGER</type>
<out />
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<do>
{/metadocument}
*/
Function GetPositionLine($position, &$line, &$column)
{
if(!$this->track_lines)
return($this->SetPositionedError('line positions are not being tracked', $position));
$bottom = 0;
$top = count($this->lines) - 1;
if($position < 0)
return($this->SetPositionedError('it was not specified a valid position', $position));
for(;;)
{
$line = intval(($bottom + $top) / 2);
$current = $this->lines[$line];
if($current < $position)
$bottom = $line + 1;
elseif($current > $position)
$top = $line - 1;
else
break;
if($top < $bottom)
{
$line = $top;
break;
}
}
$column = $position - $this->lines[$line] + 1;
++$line;
return(1);
}
/*
{metadocument}
</do>
</function>
{/metadocument}
*/
/*
{metadocument}
<function>
<name>ParseStyleProperties</name>
<type>BOOLEAN</type>
<documentation>
<purpose>Parse and extract style properties eventually from style
definition sections in HTML pages.</purpose>
<usage>.</usage>
<returnvalue>.</returnvalue>
</documentation>
<argument>
<name>value</name>
<type>STRING</type>
<documentation>
<purpose>String with the style properties to parse.</purpose>
</documentation>
</argument>
<argument>
<name>properties</name>
<type>ARRAY</type>
<out />
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<do>
{/metadocument}
*/
Function ParseStyleProperties($value, &$properties)
{
$this->error = '';
$this->warnings = array();
$this->v = $v = $value;
$p = 0;
if(!$this->ParseProperties($p, $properties))
return(0);
$l = strlen($v);
if($p < $l)
{
if(strcmp($v[$p], ';'))
return($this->SetPositionedError('invalid style property', $p));
++$p;
if(!$this->SkipWhiteSpace($p))
return(0);
if($p < $l)
return($this->SetPositionedError('it was not specified a valid style property after semi-colon', $p));
}
return(1);
}
/*
{metadocument}
</do>
</function>
{/metadocument}
*/
/*
{metadocument}
<function>
<name>ParseStylesheet</name>
<type>BOOLEAN</type>
<documentation>
<purpose>Parse and extract stylesheets eventually from stylesheet
files or sections in HTML pages.</purpose>
<usage>.</usage>
<returnvalue>.</returnvalue>
</documentation>
<argument>
<name>stylesheet</name>
<type>STRING</type>
<documentation>
<purpose>String with the stylesheet to parse.</purpose>
</documentation>
</argument>
<argument>
<name>properties</name>
<type>ARRAY</type>
<out />
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<do>
{/metadocument}
*/
Function ParseStylesheet($stylesheet, &$styles)
{
$this->error = '';
$this->warnings = array();
if($this->track_lines)
{
$this->lines = array();
$this->line_offset = 0;
$this->last_line = 1;
$this->last_carriage_return = 0;
$this->TrackLines($stylesheet);
}
$this->v = $stylesheet;
$l = strlen($this->v);
for($p = 0, $s = array();$p < $l;)
{
if(!$this->SkipWhiteSpace($p))
return(0);
if($p >= $l)
break;
if(!$this->ParseRuleSet($p, $ruleset))
return(0);
if(!IsSet($ruleset))
return($this->SetPositionedError('stylesheet syntax error', $p));
$ts = count($s);
$s[$ts] = array(
'Type'=>'ruleset',
'RuleSet'=>$ruleset
);
if($this->store_positions)
$s[$ts]['Position'] = $ruleset['Position'];
}
$styles = $s;
return(1);
}
/*
{metadocument}
</do>
</function>
{/metadocument}
*/
/*
{metadocument}
<function>
<name>RewriteStyleProperties</name>
<type>BOOLEAN</type>
<documentation>
<purpose>.</purpose>
<usage>.</usage>
<returnvalue>.</returnvalue>
</documentation>
<argument>
<name>properties</name>
<type>ARRAY</type>
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<argument>
<name>rewrite</name>
<type>STRING</type>
<out />
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<do>
{/metadocument}
*/
Function RewriteStyleProperties($properties, &$rewrite, $position = -1)
{
$rewrite = '';
$tp = count($properties);
for(Reset($properties), $p = 0; $p < $tp; Next($properties), ++$p)
{
if($p > 0)
$rewrite .= '; ';
if(!$this->RewriteProperty($properties[Key($properties)], $property))
return(0);
$rewrite .= $property;
}
return(1);
}
/*
{metadocument}
</do>
</function>
{/metadocument}
*/
/*
{metadocument}
<function>
<name>RewriteStyle</name>
<type>BOOLEAN</type>
<documentation>
<purpose>.</purpose>
<usage>.</usage>
<returnvalue>.</returnvalue>
</documentation>
<argument>
<name>style</name>
<type>HASH</type>
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<argument>
<name>rewrite</name>
<type>STRING</type>
<out />
<documentation>
<purpose>.</purpose>
</documentation>
</argument>
<do>
{/metadocument}
*/
Function RewriteStyle($style, &$rewrite)
{
$rewrite = '';
$position = (IsSet($style['Position']) ? $style['Position'] : -1);
switch($style['Type'])
{
case 'ruleset':
if(!$this->RewriteExpression($style['RuleSet']['Selector'], $selector))
return(0);
$rewrite .= $selector.' { ';
$properties = $style['RuleSet']['Properties'];
if(!$this->RewriteStyleProperties($properties, $properties_rewrite))
return(0);
$rewrite .= $properties_rewrite." }\n";
break;
default:
return($this->SetPositionedError('rewriting styles of type '.$style['Type'].' is not yet supported', $position));
}
return(1);
}
/*
{metadocument}
</do>
</function>
{/metadocument}
*/
};
/*
{metadocument}
</class>
{/metadocument}
*/
?>