Skip to content

Commit e44e52b

Browse files
committed
Begin selector parsing impl
1 parent 19dbbd8 commit e44e52b

15 files changed

+285
-4
lines changed

lib/Sabberworm/CSS/OutputFormat.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ class OutputFormat {
3838
// This is what’s printed before and after the comma if a declaration block contains multiple selectors.
3939
public $sSpaceBeforeSelectorSeparator = '';
4040
public $sSpaceAfterSelectorSeparator = ' ';
41+
42+
// This is what’s printed before and after combinators in selectors
43+
public $sSpaceBeforeSelectorCombinator = ' ';
44+
public $sSpaceAfterSelectorCombinator = ' ';
45+
4146
// This is what’s printed after the comma of value lists
4247
public $sSpaceBeforeListArgumentSeparator = '';
4348
public $sSpaceAfterListArgumentSeparator = '';
@@ -147,11 +152,22 @@ public static function create() {
147152
}
148153

149154
public static function createCompact() {
150-
return self::create()->set('Space*Rules', "")->set('Space*Blocks', "")->setSpaceAfterRuleName('')->setSpaceBeforeOpeningBrace('')->setSpaceAfterSelectorSeparator('');
155+
return self::create()
156+
->set('Space*Rules', "")
157+
->set('Space*Blocks', "")
158+
->setSpaceAfterRuleName('')
159+
->setSpaceBeforeOpeningBrace('')
160+
->setSpaceAfterSelectorSeparator('')
161+
->setSpaceBeforeSelectorCombinator('')
162+
->setSpaceAfterSelectorCombinator('');
151163
}
152164

153165
public static function createPretty() {
154-
return self::create()->set('Space*Rules', "\n")->set('Space*Blocks', "\n")->setSpaceBetweenBlocks("\n\n")->set('SpaceAfterListArgumentSeparator', array('default' => '', ',' => ' '));
166+
return self::create()
167+
->set('Space*Rules', "\n")
168+
->set('Space*Blocks', "\n")
169+
->setSpaceBetweenBlocks("\n\n")
170+
->set('SpaceAfterListArgumentSeparator', array('default' => '', ',' => ' '));
155171
}
156172
}
157173

@@ -211,6 +227,14 @@ public function spaceAfterSelectorSeparator() {
211227
return $this->space('AfterSelectorSeparator');
212228
}
213229

230+
public function spaceBeforeSelectorCombinator() {
231+
return $this->space('AfterSelectorSeparator');
232+
}
233+
234+
public function spaceAfterSelectorCombinator() {
235+
return $this->space('AfterSelectorSeparator');
236+
}
237+
214238
public function spaceBeforeListArgumentSeparator($sSeparator) {
215239
return $this->space('BeforeListArgumentSeparator', $sSeparator);
216240
}

lib/Sabberworm/CSS/Property/Selector.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace Sabberworm\CSS\Property;
44

5+
use Sabberworm\CSS\Renderable;
6+
use Sabberworm\CSS\Parsing\ParserState;
7+
58
/**
69
* Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this class.
710
*/
8-
class Selector {
11+
class Selector implements Renderable {
912

1013
//Regexes for specificity calculations
1114
const NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX = '/
@@ -37,14 +40,20 @@ class Selector {
3740

3841
private $sSelector;
3942
private $iSpecificity;
43+
private $iLineNo;
4044

41-
public function __construct($sSelector, $bCalculateSpecificity = false) {
45+
public function __construct($sSelector, $bCalculateSpecificity = false, $iLineNo = 0) {
4246
$this->setSelector($sSelector);
47+
$this->iLineNo = $iLineNo;
4348
if ($bCalculateSpecificity) {
4449
$this->getSpecificity();
4550
}
4651
}
4752

53+
public static function parse(ParserState $oParserState, $aExpectedEnd = array('{', ',')) {
54+
55+
}
56+
4857
public function getSelector() {
4958
return $this->sSelector;
5059
}
@@ -58,6 +67,10 @@ public function __toString() {
5867
return $this->getSelector();
5968
}
6069

70+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
71+
return $this->getSelector();
72+
}
73+
6174
public function getSpecificity() {
6275
if ($this->iSpecificity === null) {
6376
$a = 0;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
abstract class AdjacentSiblingCombinator extends SelectorPart {
6+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
7+
return $oOutputFormat->spaceBeforeSelectorCombinator().'+'.$oOutputFormat->spaceAfterSelectorCombinator();
8+
}
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
WIP
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
abstract class ChildCombinator extends SelectorPart {
6+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
7+
return $oOutputFormat->spaceBeforeSelectorCombinator().'>'.$oOutputFormat->spaceAfterSelectorCombinator();
8+
}
9+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\Renderable;
6+
7+
abstract class ClassSelector extends SelectorPart {
8+
private $sClassName;
9+
10+
public function __construct($sClassName = false, $iLineNo = 0) {
11+
parent::__construct($iLineNo);
12+
$this->sClassName = $sClassName;
13+
}
14+
15+
public function getClassName() {
16+
return $this->sClassName;
17+
}
18+
19+
public function setClassName($sClassName) {
20+
$this->sClassName = $sClassName;
21+
}
22+
23+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
24+
return '.' . $this->sClassName;
25+
}
26+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
abstract class DescendantCombinator extends SelectorPart {
6+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
7+
return ' ';
8+
}
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
abstract class GeneralSiblingCombinator extends SelectorPart {
6+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
7+
return $oOutputFormat->spaceBeforeSelectorCombinator().'~'.$oOutputFormat->spaceAfterSelectorCombinator();
8+
}
9+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\Renderable;
6+
7+
abstract class IDSelector extends SelectorPart {
8+
private $sId;
9+
10+
public function __construct($sId = false, $iLineNo = 0) {
11+
parent::__construct($iLineNo);
12+
$this->sId = $sId;
13+
}
14+
15+
public function getId() {
16+
return $this->sId;
17+
}
18+
19+
public function setId($sId) {
20+
$this->sId = $sId;
21+
}
22+
23+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
24+
return '#' . $this->sId;
25+
}
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
WIP
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\Property\Selector;
6+
7+
abstract class Negation extends SelectorPart {
8+
private $oNegated;
9+
10+
public function __construct(Selector $oNegated, $iLineNo = 0) {
11+
parent::__construct($iLineNo);
12+
$this->oNegated = $oNegated;
13+
}
14+
15+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
16+
return ':not('.$this->oNegated->render($oOutputFormat).')';
17+
}
18+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\Renderable;
6+
7+
abstract class PseudoSelector extends SelectorPart {
8+
private $mValue;
9+
private $bIsPseudoElement;
10+
11+
public function __construct($mValue, $bIsPseudoElement = false, $iLineNo = 0) {
12+
parent::__construct($iLineNo);
13+
$this->mValue = $mValue;
14+
$this->bIsPseudoElement = $bIsPseudoElement;
15+
}
16+
17+
public function getValue() {
18+
return $this->mValue;
19+
}
20+
21+
public function setValue($mValue) {
22+
$this->mValue = $mValue;
23+
}
24+
25+
public function isPseudoFunction() {
26+
return $this->mValue instanceof CSSFunction;
27+
}
28+
29+
public function isPseudoElement() {
30+
return $bIsPseudoElement;
31+
}
32+
33+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
34+
$sValue = $this->mValue;
35+
if($sValue instanceof Renderable) {
36+
$sValue = $sValue->render($oOutputFormat);
37+
}
38+
return ':' . ($this->bIsPseudoElement ? ':' : '') . $sValue;
39+
}
40+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\OutputFormat;
6+
use Sabberworm\CSS\Renderable;
7+
use Sabberworm\CSS\Parsing\ParserState;
8+
use Sabberworm\CSS\Value\Value;
9+
10+
abstract class SelectorPart implements Renderable {
11+
private $iLineNo;
12+
13+
public function __construct($iLineNo = 0) {
14+
$this->iLineNo = $iLineNo;
15+
}
16+
17+
public static function parse(ParserState $oParserState) {
18+
if($oParserState->comes('*')) {
19+
$oParserState->consume('*');
20+
return new UniversalSelector($oParserState->currentLine());
21+
}
22+
if($oParserState->comes('.')) {
23+
$oParserState->consume('.');
24+
return new ClassSelector($oParserState->parseIdentifier(false), $oParserState->currentLine());
25+
}
26+
if($oParserState->comes('#')) {
27+
$oParserState->consume('#');
28+
return new IDSelector($oParserState->parseIdentifier(false), $oParserState->currentLine());
29+
}
30+
if($oParserState->comes(':')) {
31+
$oParserState->consume(':');
32+
$bIsElement = $oParserState->comes(':');
33+
if($bIsElement) {
34+
$oParserState->consume(':');
35+
}
36+
return new PseudoSelector(Value::parseIdentifierOrFunction($oParserState), $bIsElement, $oParserState->currentLine());
37+
}
38+
if($oParserState->comes('+')) {
39+
$oParserState->consume('+');
40+
return new AdjacentSiblingCombinator($oParserState->currentLine());
41+
}
42+
if($oParserState->comes('~')) {
43+
$oParserState->consume('~');
44+
return new GeneralSiblingCombinator($oParserState->currentLine());
45+
}
46+
if($oParserState->comes('>')) {
47+
$oParserState->consume('>');
48+
return new ChildCombinator($oParserState->currentLine());
49+
}
50+
}
51+
52+
public function __toString() {
53+
return $this->render(new OutputFormat());
54+
}
55+
56+
public function getLineNo() {
57+
return $this->iLineNo;
58+
}
59+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\Renderable;
6+
7+
abstract class TypeSelector extends SelectorPart {
8+
private $sType;
9+
10+
public function __construct($sType = false, $iLineNo = 0) {
11+
parent::__construct($iLineNo);
12+
$this->sType = $sType;
13+
}
14+
15+
public function getType() {
16+
return $this->sType;
17+
}
18+
19+
public function setType($sType) {
20+
$this->sType = $sType;
21+
}
22+
23+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
24+
return $this->sType;
25+
}
26+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Sabberworm\CSS\RuleSet\Selector;
4+
5+
use Sabberworm\CSS\Renderable;
6+
7+
abstract class UniversalSelector extends SelectorPart {
8+
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
9+
return '*';
10+
}
11+
}

0 commit comments

Comments
 (0)