Skip to content

Commit e8e3b9f

Browse files
committed
Updated code to include a value object which stores a set of space separated values, this is now used also for directive properties.
Reworked properties to use multiple value objects for each comma separated set. Introduced a document object that contains a set of rules or directives, this enables media queries to work better as they are a directive that contain a document.
1 parent 3217e69 commit e8e3b9f

File tree

12 files changed

+490
-835
lines changed

12 files changed

+490
-835
lines changed

src/autoload.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
'hexydec\\html\\text' => $dir.'/tokens/text.php',
1515
'hexydec\\html\\cssmin' => $dir.'/cssmin.php',
1616
'hexydec\\css\\cssdoc' => __DIR__.'/cssdoc/cssdoc.php',
17-
'hexydec\\css\\mediaquery' => __DIR__.'/cssdoc/tokens/mediaquery.php',
17+
'hexydec\\css\\document' => __DIR__.'/cssdoc/tokens/document.php',
1818
'hexydec\\css\\directive' => __DIR__.'/cssdoc/tokens/directive.php',
1919
'hexydec\\css\\rule' => __DIR__.'/cssdoc/tokens/rule.php',
2020
'hexydec\\css\\selector' => __DIR__.'/cssdoc/tokens/selector.php',
21-
'hexydec\\css\\property' => __DIR__.'/cssdoc/tokens/property.php'
21+
'hexydec\\css\\property' => __DIR__.'/cssdoc/tokens/property.php',
22+
'hexydec\\css\\value' => __DIR__.'/cssdoc/tokens/value.php'
2223
];
2324
if (isset($classes[$class])) {
2425
return require($classes[$class]);

src/cssdoc/cssdoc.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ class cssdoc {
3636
'convertquotes' => true,
3737
'removequotes' => true,
3838
'shortenhex' => true,
39-
'lowerhex' => true,
4039
'email' => false,
4140
'maxline' => false,
41+
'lowerproperties' => true,
42+
'lowervalues' => true,
4243
'output' => 'minify'
4344
];
4445

@@ -179,7 +180,7 @@ protected function getCharsetFromCss(string $css) : ?string {
179180
* @return bool Whether the parser was able to capture any objects
180181
*/
181182
protected function parse(array &$tokens) : bool {
182-
$this->document = new mediaquery($this);
183+
$this->document = new document($this);
183184
return $this->document->parse($tokens);
184185
}
185186

src/cssdoc/tokens/directive.php

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class directive {
1717
/**
1818
* @var string The value of the directive
1919
*/
20-
protected $content = null;
20+
protected $content = [];
2121

2222
/**
2323
* @var array An array of properties
@@ -29,7 +29,7 @@ class directive {
2929
*
3030
* @param cssdoc $root The parent htmldoc object
3131
*/
32-
public function __construct(mediaquery $root) {
32+
public function __construct(document $root) {
3333
$this->root = $root;
3434
}
3535

@@ -38,34 +38,49 @@ public function __construct(mediaquery $root) {
3838
*
3939
* @param array &$tokens An array of tokens generated by tokenise()
4040
* @param array $config An array of configuration options
41-
* @return void
41+
* @return bool Whether anything was parsed
4242
*/
43-
public function parse(array &$tokens) : void {
43+
public function parse(array &$tokens) : bool {
4444
$directive = true;
4545
$token = current($tokens);
46+
$properties = false;
4647
do {
4748
switch ($token['type']) {
4849
case 'directive':
4950
$this->directive = $token['value'];
5051
break;
5152
case 'string':
52-
case 'quotes':
53-
if ($directive) {
54-
$this->content = $token['value'];
55-
} else {
53+
case 'colon':
54+
if ($properties) {
5655
$item = new property($this);
57-
$item->parse($tokens);
58-
$this->properties[] = $item;
56+
if ($item->parse($tokens)) {
57+
$this->properties[] = $item;
58+
}
59+
break;
5960
}
61+
case 'bracketopen':
62+
case 'quotes':
63+
$item = new value($this);
64+
$item->parse($tokens);
65+
$this->content[] = $item;
6066
break;
6167
case 'curlyopen':
62-
$directive = false;
68+
next($tokens);
69+
if (in_array($this->directive, ['@media', '@keyframes'])) {
70+
$item = new document($this);
71+
if ($item->parse($tokens)) {
72+
$this->properties[] = $item;
73+
}
74+
} else {
75+
$properties = true;
76+
}
6377
break;
6478
case 'semicolon':
6579
case 'curlyclose':
6680
break 2;
6781
}
6882
} while (($token = next($tokens)) !== false);
83+
return !empty($this->directive);
6984
}
7085

7186
/**
@@ -75,6 +90,20 @@ public function parse(array &$tokens) : void {
7590
* @return void
7691
*/
7792
public function minify(array $minify) : void {
93+
94+
// minify directive properties
95+
foreach ($this->content AS $item) {
96+
$item->minify($minify);
97+
}
98+
99+
// minify properties
100+
foreach ($this->properties AS $item) {
101+
$item->minify($minify);
102+
}
103+
104+
if ($this->properties && $minify['removesemicolon']) {
105+
$this->properties[count($this->properties)-1]->semicolon = false;
106+
}
78107
}
79108

80109
/**
@@ -86,8 +115,10 @@ public function minify(array $minify) : void {
86115
public function compile(array $options) : string {
87116
$b = $options['output'] != 'minify';
88117
$css = $this->directive;
89-
if ($this->content) {
90-
$css .= ' '.$this->content;
118+
$join = ' ';
119+
foreach ($this->content AS $item) {
120+
$css .= $join.$item->compile($options);
121+
$join = $b ? ', ' : ',';
91122
}
92123
if ($this->properties) {
93124
$css .= $b ? ' {' : '{';

src/cssdoc/tokens/document.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
declare(strict_types = 1);
3+
namespace hexydec\css;
4+
5+
class document {
6+
7+
/**
8+
* @var cssdoc The parent htmldoc object
9+
*/
10+
protected $root;
11+
12+
/**
13+
* @var array An array of media query parameters
14+
*/
15+
protected $media = [];
16+
17+
/**
18+
* @var array An array of child token objects
19+
*/
20+
protected $rules = [];
21+
22+
/**
23+
* Constructs the comment object
24+
*
25+
* @param cssdoc $root The parent htmldoc object
26+
*/
27+
public function __construct($root, array $media = null) {
28+
$this->root = $root;
29+
$this->media = $media;
30+
}
31+
32+
/**
33+
* Parses an array of tokens into an HTML documents
34+
*
35+
* @param array &$tokens An array of tokens generated by tokenise()
36+
* @param array $config An array of configuration options
37+
* @return bool Whether anything was parsed
38+
*/
39+
public function parse(array &$tokens) : bool {
40+
41+
// parse tokens
42+
$token = current($tokens);
43+
do {
44+
switch ($token['type']) {
45+
case 'directive':
46+
$item = new directive($this);
47+
$item->parse($tokens);
48+
$this->rules[] = $item;
49+
break;
50+
case 'string':
51+
$item = new rule($this);
52+
$item->parse($tokens);
53+
$this->rules[] = $item;
54+
break;
55+
case 'curlyclose':
56+
prev($tokens);
57+
break 2;
58+
}
59+
} while (($token = next($tokens)) !== false);
60+
return !!$this->rules;
61+
}
62+
63+
/**
64+
* Minifies the internal representation of the comment
65+
*
66+
* @param array $minify An array of minification options controlling which operations are performed
67+
* @return void
68+
*/
69+
public function minify(array $minify) : void {
70+
foreach ($this->rules AS $item) {
71+
$item->minify($minify);
72+
}
73+
}
74+
75+
/**
76+
* Compile the property to a string
77+
*
78+
* @param array $options An array of compilation options
79+
* @return void
80+
*/
81+
public function compile(array $options) : string {
82+
$b = $options['output'] != 'minify';
83+
$css = '';
84+
85+
// compile selectors
86+
$join = '';
87+
foreach ($this->rules AS $item) {
88+
$css .= $join.$item->compile($options);
89+
$join = $b ? "\n\n" : '';
90+
}
91+
if ($this->media) {
92+
$css .= '}';
93+
}
94+
return $css;
95+
}
96+
}

0 commit comments

Comments
 (0)