Skip to content

Commit 474666f

Browse files
committed
Improved handling of Origin specific CSS
1 parent aa92000 commit 474666f

File tree

5 files changed

+199
-18
lines changed

5 files changed

+199
-18
lines changed

CSSParser.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ private function parseAtRule() {
9898
}
9999
}
100100

101+
/**
102+
* This has been modified to allow for Origin functions as identifiers
103+
*/
101104
private function parseIdentifier($bAllowFunctions = true) {
102105
$sResult = $this->parseCharacter(true);
103106
if($sResult === null) {
@@ -228,6 +231,17 @@ private function parseRuleSet($oRuleSet) {
228231
}
229232

230233
private function parseRule() {
234+
// A rule can also be an origin function
235+
if($this->comes('@')){
236+
$this->consume('@');
237+
$fName = $this->parseIdentifier(false);
238+
$this->consume('(');
239+
$result = new CSSOriginFunction($fName, $this->parseValue(array('=', ',')));
240+
$this->consume(')');
241+
if($this->comes(';')) $this->consume(';');
242+
return $result;
243+
}
244+
231245
$oRule = new CSSRule($this->parseIdentifier());
232246
$this->consumeWhiteSpace();
233247
$this->consume(':');

lib/CSSList.php

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,32 @@ protected function allValues($oElement, &$aResult, $sSearchString = null, $bSear
6969
$aResult[] = $oElement;
7070
}
7171
}
72-
72+
73+
protected function allOriginFunctions($oElement, &$aResult, $sSearchString = null, $bSearchInFunctionArguments = true) {
74+
if($oElement instanceof CSSList) {
75+
foreach($oElement->getContents() as $oContent) {
76+
$this->allOriginFunctions($oContent, $aResult, $sSearchString, $bSearchInFunctionArguments);
77+
}
78+
} else if($oElement instanceof CSSRuleSet) {
79+
foreach($oElement->getRules($sSearchString) as $oRule) {
80+
$this->allOriginFunctions($oRule, $aResult, $sSearchString, $bSearchInFunctionArguments);
81+
}
82+
} else if($oElement instanceof CSSRule) {
83+
$this->allOriginFunctions($oElement->getValue(), $aResult, $sSearchString, $bSearchInFunctionArguments);
84+
} else if($oElement instanceof CSSValueList) {
85+
if($bSearchInFunctionArguments || !($oElement instanceof CSSFunction)) {
86+
foreach($oElement->getListComponents() as $mComponent) {
87+
$this->allOriginFunctions($mComponent, $aResult, $sSearchString, $bSearchInFunctionArguments);
88+
}
89+
}
90+
}
91+
92+
// We want origin functions
93+
if($oElement instanceof CSSOriginFunction){
94+
$aResult[] = $oElement;
95+
}
96+
}
97+
7398
protected function allSelectors(&$aResult, $sSpecificitySearch = null) {
7499
foreach($this->getAllDeclarationBlocks() as $oBlock) {
75100
foreach($oBlock->getSelectors() as $oSelector) {
@@ -133,6 +158,19 @@ public function getAllValues($mElement = null, $bSearchInFunctionArguments = fal
133158
$this->allValues($mElement, $aResult, $sSearchString, $bSearchInFunctionArguments);
134159
return $aResult;
135160
}
161+
162+
public function getAllOriginFunctions($mElement = null, $bSearchInFunctionArguments = true){
163+
$sSearchString = null;
164+
if($mElement === null) {
165+
$mElement = $this;
166+
} else if(is_string($mElement)) {
167+
$sSearchString = $mElement;
168+
$mElement = $this;
169+
}
170+
$aResult = array();
171+
$this->allOriginFunctions($mElement, $aResult, $sSearchString, $bSearchInFunctionArguments);
172+
return $aResult;
173+
}
136174

137175
/**
138176
* Returns all CSSSelector objects found recursively in the tree.
@@ -167,18 +205,72 @@ public function createShorthands() {
167205
}
168206
}
169207

208+
/**
209+
* Creates additional CSS rules to support all browsers
210+
*/
211+
public function createCss3BrowserSupport() {
212+
213+
}
214+
170215
/**
171216
* Inserts values and executes functions defined by the executor.
172217
*/
173218
public function originProcess($values, $executor){
219+
// Start by swapping out variables for their known values
220+
foreach($this->getAllValues(null, true) as $value){
221+
if($value instanceof CSSOriginVariable){
222+
$value->substitute($values);
223+
}
224+
}
225+
226+
// Now we need to process all the functions
227+
foreach($this->getAllOriginFunctions() as $function){
228+
$function->execute($executor);
229+
}
230+
}
231+
232+
/**
233+
* Sets the Javascript mode on all contained Origin objects
234+
*/
235+
public function originSetJSMode($mode){
236+
foreach($this->getAllValues(null, true) as $value)
237+
if($value instanceof CSSOriginVariable) $value->setJSMode($mode);
238+
foreach($this->getAllOriginFunctions() as $function) $function->setJSMode($mode);
239+
}
240+
241+
/**
242+
*
243+
*/
244+
public function originJavascriptFunction(){
245+
$this->originSetJSMode(true);
246+
$js = 'var originGenerateCss = function(v, e){ return "'.$this->__toString().'" };';
247+
$this->originSetJSMode(false);
174248

249+
return $js;
175250
}
176251

177252
/**
178253
* @return array() Which origin variables affect which rules
179254
*/
180-
public function originGetRules(){
255+
public function originGetEffects(){
256+
// We need to find out which deceleration blocks are affected by which origin variables
257+
$effects = array();
258+
foreach($this->getAllDeclarationBlocks() as $block){
259+
$selectors = array();
260+
foreach($block->getSelectors() as $s){
261+
$selectors[] = $s->getSelector();
262+
}
263+
264+
foreach($this->getAllValues($block, true) as $value){
265+
if($value instanceof CSSOriginVariable){
266+
list($s, $n) = explode('->', $value->getVariable());
267+
if(empty($effects[$s][$n])) @$effects[$s][$n] = array();
268+
$effects[$s][$n] = array_unique(array_merge($effects[$s][$n], $selectors));
269+
}
270+
}
271+
}
181272

273+
return $effects;
182274
}
183275
}
184276

lib/CSSRuleSet.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ public function __construct() {
1111
$this->aRules = array();
1212
}
1313

14-
public function addRule(CSSRule $oRule) {
15-
$this->aRules[$oRule->getRule()] = $oRule;
14+
public function addRule($oRule) {
15+
//$this->aRules[$oRule->getRule()] = $oRule;
16+
// TODO check that this allows repeated rules
17+
$this->aRules[] = $oRule;
1618
}
1719

1820
/**

lib/CSSValue.php

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,32 +112,58 @@ public function __toString() {
112112
* An Origin framework style variable.
113113
*/
114114
class CSSOriginVariable extends CSSPrimitiveValue {
115-
private $v;
115+
/**
116+
* @var The value
117+
*/
118+
private $variable;
116119

117120
/**
118121
* @var string The proccessed variable
119122
*/
120-
private $pr;
123+
private $processed = null;
121124

122125
public function __construct($v){
123-
$this->v = $v;
124-
$this->p = null;
126+
$this->variable = $v;
125127
}
126128

127-
public function getVar(){
128-
return $this->v;
129+
/**
130+
* Get the current value.
131+
*/
132+
public function getValue(){
133+
if(empty($this->processed)) return $this->processed;
134+
else return $this->variable;
135+
}
136+
137+
/**
138+
* Get the name of the variable
139+
*/
140+
public function getVariable(){
141+
return $this->variable;
129142
}
130143

131144
/**
132145
* Substitutes values from the values array.
133146
*
134147
* @para array $values The values
135148
*/
136-
public function process($values){
137-
149+
public function substitute($values){
150+
list($v, $m) = explode('->', $this->variable);
151+
if(empty($m)) $this->processed = $values[$v];
152+
else $this->processed = $values[$v][$m];
153+
}
154+
155+
/**
156+
* @param bool $mode If set to true, __toString() will return Javascript code.
157+
*/
158+
public function setJSMode($jsmode = true){
159+
$this->jsmode = $jsmode;
138160
}
139161

140162
public function __toString() {
141-
return $this->p;
163+
if($this->jsmode) {
164+
list($v, $m) = explode('->', $this->variable);
165+
return "v['{$v}']['$m']";
166+
}
167+
else return (string) $this->processed;
142168
}
143169
}

lib/CSSValueList.php

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,40 @@ public function getColorDescription() {
9090
}
9191

9292
class CSSOriginFunction extends CSSValueList {
93-
private $sName;
94-
public function __construct($sName, $aArguments) {
95-
$this->sName = $sName;
93+
private $function;
94+
95+
private $output = null;
96+
97+
/**
98+
* The result of executing the function
99+
*/
100+
private $result;
101+
102+
/**
103+
* @var bool JavaScript mode.
104+
*/
105+
private $jsmode;
106+
107+
private $exitString = true;
108+
109+
public function __construct($function, $aArguments) {
110+
$this->function = $function;
96111
parent::__construct($aArguments);
97112
}
98113

99114
/**
100115
* Executes an origin function
101116
*/
102117
public function execute($executor) {
118+
if(!method_exists($executor, $this->function))
119+
throw new Exception('Invalid executor function. Could not find '.(is_string($executor) ? $executor : get_class($executor)).'::'.$this->sName);
120+
121+
$args = array();
122+
foreach($this->aComponents as $component){
123+
$args[] = (string) $component;
124+
}
103125

126+
$this->output = call_user_func_array(array($executor, $this->function), $args);
104127
}
105128

106129
public function getName() {
@@ -114,10 +137,34 @@ public function setName($sName) {
114137
public function getArguments() {
115138
return $this->aComponents;
116139
}
140+
141+
/**
142+
* Makes the function not exit from a string when we're creating the javascript code.
143+
*/
144+
public function noExitString(){
145+
$this->exitString = false;
146+
}
147+
148+
/**
149+
* @param bool $mode If set to true, __toString() will return Javascript code.
150+
*/
151+
public function setJSMode($jsmode = true){
152+
$this->jsmode = $jsmode;
153+
foreach($this->aComponents as $c){
154+
if($c instanceof CSSOriginFunction) $c->noExitString();
155+
}
156+
}
117157

118158
public function __toString() {
119-
$aArguments = parent::__toString();
120-
return "{$this->sName}({$aArguments})";
159+
if($this->jsmode){
160+
$aArguments = parent::__toString();
161+
$return = '';
162+
if($this->exitString) $return .= '" + ';
163+
$return .= "e['{$this->function}']({$aArguments})";
164+
if($this->exitString) $return .= ' + "';
165+
return $return;
166+
}
167+
else return (string) $this->output;
121168
}
122169
}
123170

0 commit comments

Comments
 (0)