@@ -9,6 +9,11 @@ class mediaquery {
99 */
1010 protected $ root ;
1111
12+ /**
13+ * @var array An array of media query parameters
14+ */
15+ protected $ media = [];
16+
1217 /**
1318 * @var array An array of child token objects
1419 */
@@ -19,8 +24,9 @@ class mediaquery {
1924 *
2025 * @param cssdoc $root The parent htmldoc object
2126 */
22- public function __construct (cssdoc $ root ) {
27+ public function __construct (cssdoc $ root, array $ media = null ) {
2328 $ this ->root = $ root ;
29+ $ this ->media = $ media ;
2430 }
2531
2632 /**
@@ -31,24 +37,94 @@ public function __construct(cssdoc $root) {
3137 * @return void
3238 */
3339 public function parse (array &$ tokens ) : bool {
40+ $ default = $ rule = [
41+ 'media ' => false ,
42+ 'only ' => false ,
43+ 'not ' => false ,
44+ 'properties ' => []
45+ ];
3446
3547 // parse tokens
36- while (($ token = next ($ tokens )) !== false ) {
48+ $ token = current ($ tokens );
49+ do {
3750 switch ($ token ['type ' ]) {
38- case 'string ' :
51+ case 'directive ' :
52+
53+ // parse media query
3954 if ($ token ['value ' ] == '@media ' ) {
40- $ item = new mediaquery ($ this ->root );
55+ $ media = [];
56+ $ rule = $ default ;
57+ while (($ token = next ($ tokens )) !== false ) {
58+ switch ($ token ['type ' ]) {
59+ case 'string ' :
60+ if ($ token ['value ' ] == 'only ' ) {
61+ $ rule ['only ' ] = true ;
62+ } elseif ($ token ['value ' ] == 'not ' ) {
63+ $ rule ['not ' ] = true ;
64+ } elseif ($ token ['value ' ] != 'and ' ) {
65+ $ rule ['media ' ] = $ token ['value ' ];
66+ }
67+ break ;
68+ case 'bracketopen ' :
69+ $ compare = false ;
70+ while (($ token = next ($ tokens )) !== false && $ token ['type ' ] != 'bracketclose ' ) {
71+ if ($ token ['type ' ] == 'string ' ) {
72+ if (!$ compare ) {
73+ $ prop = $ token ['value ' ];
74+ } elseif ($ compare == ': ' ) {
75+ $ rule ['properties ' ][$ prop ] = $ token ['value ' ];
76+ $ prop = false ;
77+ $ compare = false ;
78+ } else {
79+ if (intval ($ prop )) {
80+ $ rule ['properties ' ]['min- ' .$ token ['value ' ]] = $ prop ;
81+ $ prop = 'max ' .$ token ['value ' ];
82+ } else {
83+ $ rule ['properties ' ][$ prop ] = $ token ['value ' ];
84+ }
85+ $ prop = false ;
86+ $ compare = false ;
87+ }
88+ } elseif ($ token ['type ' ] == 'colon ' ) {
89+ $ compare = ': ' ;
90+ } elseif ($ token ['type ' ] == 'comparison ' && $ token ['value ' ] == '<= ' ) {
91+ $ compare = '<= ' ;
92+ }
93+ }
94+ if ($ prop ) {
95+ $ rule ['properties ' ][$ prop ] = null ;
96+ }
97+ break ;
98+ case 'comma ' :
99+ $ media [] = $ rule ;
100+ $ rule = $ default ;
101+ break ;
102+ case 'curlyopen ' :
103+ break 2 ;
104+ }
105+ }
106+ $ media [] = $ rule ;
107+ // var_dump($media);
108+
109+ // create media query object
110+ $ item = new mediaquery ($ this ->root , $ media );
41111 $ item ->parse ($ tokens );
42112 $ this ->rules [] = $ item ;
43113 } else {
44- prev ($ tokens );
45- $ item = new rule ($ this );
114+ $ item = new directive ($ this );
46115 $ item ->parse ($ tokens );
47116 $ this ->rules [] = $ item ;
48117 }
49118 break ;
119+ case 'string ' :
120+ $ item = new rule ($ this );
121+ $ item ->parse ($ tokens );
122+ $ this ->rules [] = $ item ;
123+ break ;
124+ case 'curlyclose ' :
125+ break 2 ;
50126 }
51- }
127+ } while (( $ token = next ( $ tokens )) !== false );
52128 return !!$ this ->rules ;
53129 }
54130
@@ -59,6 +135,9 @@ public function parse(array &$tokens) : bool {
59135 * @return void
60136 */
61137 public function minify (array $ minify ) : void {
138+ foreach ($ this ->rules AS $ item ) {
139+ $ item ->minify ($ minify );
140+ }
62141 }
63142
64143 /**
@@ -70,13 +149,38 @@ public function minify(array $minify) : void {
70149 public function compile (array $ options ) : string {
71150 $ b = $ options ['output ' ] != 'minify ' ;
72151 $ css = '' ;
152+ if ($ this ->media ) {
153+ $ css .= '@media ' ;
154+ $ media = [];
155+ foreach ($ this ->media AS $ item ) {
156+ $ query = '' ;
157+ $ join = '' ;
158+ if ($ item ['media ' ]) {
159+ $ query .= trim (($ item ['only ' ] ? ' only ' : '' ).($ item ['not ' ] ? ' not ' : '' ).($ item ['media ' ] ? ' ' .$ item ['media ' ] : '' ));
160+ $ join = ' and ' ;
161+ }
162+ foreach ($ item ['properties ' ] AS $ key => $ prop ) {
163+ $ query .= $ join .'( ' .$ key .($ prop === null ? '' : ': ' .($ b ? ' ' : '' ).$ prop ).') ' ;
164+ $ join = ' and ' ;
165+ }
166+ $ media [] = $ query ;
167+ }
168+ $ css .= implode ($ b ? ', ' : ', ' , $ media );
169+ $ css .= $ b ? " { \n" : '{ ' ;
170+ if ($ b ) {
171+ $ options ['prefix ' ] = "\t" ;
172+ }
173+ }
73174
74175 // compile selectors
75176 $ join = '' ;
76177 foreach ($ this ->rules AS $ item ) {
77178 $ css .= $ join .$ item ->compile ($ options );
78179 $ join = $ b ? "\n\n" : '' ;
79180 }
181+ if ($ this ->media ) {
182+ $ css .= '} ' ;
183+ }
80184 return $ css ;
81185 }
82186}
0 commit comments