1- /**
2- * ParserCSS Class
3- */
4- class Parser {
1+ class ICSSStatments {
2+ static get IMPORT ( ) { return 'import' }
3+ static get MEDIA ( ) { return 'media' }
4+ static get KEYFRAME ( ) { return 'keyframe' }
5+ static get FONT_FACE ( ) { return 'font-face' }
6+ }
57
8+ class ICSS {
69 static get EMPTY ( ) { return '' }
710
811 static get DOTS ( ) { return ':' }
@@ -19,6 +22,8 @@ class Parser {
1922
2023 static get END_BRACKET ( ) { return ')' }
2124
25+ static get DOUBLE_END_BRACKETS ( ) { return '}}' }
26+
2227 static get END_BRACKET_RULE ( ) { return ');' }
2328
2429 static get DATA_URI ( ) { return 'data:' }
@@ -35,14 +40,27 @@ class Parser {
3540 let re = new RegExp ( Object . keys ( obj ) . join ( '|' ) , 'g' )
3641 return str . replace ( re , i => obj [ i ] )
3742 }
43+ }
3844
45+ /**
46+ * ParserCSS Class
47+ */
48+ class Parser {
49+
50+ /**
51+ * Initializate Parser
52+ * @param string css (optional)
53+ * @return object Parser
54+ */
3955 constructor ( css ) {
4056 this . css = css
57+ this . clearCode ( )
4158 this . parseCSS ( )
4259
4360 delete this . rules
4461 delete this . query
45- return this . blocks
62+ delete this . blockRules
63+ return this
4664 }
4765
4866 /**
@@ -52,12 +70,13 @@ class Parser {
5270 */
5371 parseCSS ( css = '' ) {
5472 this . blocks = [ ]
55- this . css = ( css != Parser . EMPTY ) ? css :this . css
56- this . blocksRule = this . clearCode ( ) . split ( Parser . END_BLOCK )
73+ this . css = ( css != ICSS . EMPTY ) ? css :this . css
74+ this . blocksRule = this . parseCSSStatments ( )
75+ . split ( ICSS . END_BLOCK )
5776 this . blocksRule . pop ( )
5877
5978 this . blocksRule . map ( block => {
60- [ this . query , this . rules ] = block . split ( Parser . BEGIN_BLOCK )
79+ [ this . query , this . rules ] = block . split ( ICSS . BEGIN_BLOCK )
6180
6281 this . blocks . push ( {
6382 query : this . query . trim ( ) ,
@@ -76,50 +95,106 @@ class Parser {
7695 */
7796 parseCSSBlock ( rules = '' ) {
7897 this . blockRules = [ ]
79- this . rules = ( rules != Parser . EMPTY ) ? rules : this . rules
80- this . rules = this . parseCSSRules ( ) . split ( Parser . SEMICOLON )
98+ this . rules = ( rules != ICSS . EMPTY ) ? rules : this . rules
99+ this . rules = this . parseCSSRules ( ) . split ( ICSS . SEMICOLON )
81100 this . rules . pop ( )
82101
83102 this . rules . map ( decl => {
84- let [ prop , value ] = decl . split ( Parser . DOTS ) . map ( i => i . trim ( ) )
85- if ( prop != Parser . EMPTY && value != Parser . EMPTY )
86- this . blockRules . push ( new Rule ( prop , Parser . REGEX_REPLACE ( value , Parser . DATA_URI_VALUES ) ) )
103+ let [ prop , value ] = decl . split ( ICSS . DOTS ) . map ( i => i . trim ( ) )
104+ if ( prop != ICSS . EMPTY && value != ICSS . EMPTY )
105+ this . blockRules . push ( new Rule ( prop , ICSS . REGEX_REPLACE ( value , ICSS . DATA_URI_VALUES ) ) )
87106 } )
88107
89108 return this . blockRules
90109 }
91110
111+
112+ parseCSSStatments ( ) {
113+ this . statments = { imports :[ ] , medias :[ ] , keyframes :[ ] , font_faces :[ ] }
114+ this . css . split ( '@' ) . map ( blocklines => {
115+ let blockline = Object . keys ( this . statments )
116+ . map ( s => ICSS . REGEX_REPLACE ( s , { 's' :'' , '_' :'-' } ) )
117+ . filter ( statment => blocklines . startsWith ( statment ) )
118+
119+ if ( blockline . length > 0 ) {
120+ let statment = `${ blockline [ 0 ] . replace ( '-' , '_' ) } s`
121+
122+ if ( blockline [ 0 ] == ICSSStatments . IMPORT ) {
123+ console . log ( this . css )
124+ this . css = this . css . replace ( `@${ blocklines . split ( ICSS . SEMICOLON ) [ 0 ] } ;` , ICSS . EMPTY )
125+ let path_or_url = blocklines
126+ . split ( ICSS . SEMICOLON ) [ 0 ]
127+ . split ( blockline [ 0 ] ) [ 1 ] . trim ( )
128+
129+ if ( path_or_url . startsWith ( '"' ) ) {
130+ path_or_url = path_or_url . replace ( new RegExp ( '"' , 'g' ) , ICSS . EMPTY )
131+ }
132+
133+ this . statments [ statment ] . push ( path_or_url )
134+ } else if ( blockline [ 0 ] == ICSSStatments . FONT_FACE ) {
135+ this . css = this . css . replace ( `@${ blocklines . split ( ICSS . END_BLOCK ) [ 0 ] } }` , ICSS . EMPTY )
136+ let rules = blocklines . split ( ICSS . BEGIN_BLOCK ) [ 1 ]
137+ . split ( ICSS . END_BLOCK ) [ 0 ] . trim ( )
138+ rules = rules . split ( ICSS . SEMICOLON ) . map ( r => {
139+ if ( r != "" ) {
140+ let [ p , v ] = r . split ( ICSS . DOTS )
141+ return ( new Rule ( p , v . trim ( ) . replace ( new RegExp ( '"' , 'g' ) , ICSS . EMPTY ) ) )
142+ } } ) . filter ( r => r != undefined )
143+
144+ this . statments [ statment ] . push ( rules )
145+ } else {
146+ let mediaBlocks = [ ]
147+ let lines = blocklines . split ( ICSS . DOUBLE_END_BRACKETS ) [ 0 ]
148+ this . css = this . css . replace ( `@${ lines } }}` , ICSS . EMPTY )
149+ let mediaQuery = lines . substring ( 0 , lines . indexOf ( ICSS . BEGIN_BLOCK ) - 1 )
150+ lines = lines . substring ( lines . indexOf ( ICSS . BEGIN_BLOCK ) + 1 )
151+ . split ( ICSS . END_BLOCK )
152+
153+ lines . map ( block => {
154+ let [ query , rules ] = block . split ( ICSS . BEGIN_BLOCK )
155+
156+ mediaBlocks . push ( {
157+ query : query . trim ( ) ,
158+ selectors : query . trim ( ) . split ( ICSS . COMMA ) . map ( s => s . trim ( ) ) ,
159+ rules : rules . split ( ICSS . SEMICOLON ) . map ( r => {
160+ if ( r != "" ) {
161+ let [ p , v ] = r . split ( ICSS . DOTS )
162+ return ( new Rule ( p , v ) )
163+ } } ) . filter ( r => r != undefined )
164+ } )
165+ } )
166+ this . statments [ statment ] . push ( { query : mediaQuery , blocks : mediaBlocks } )
167+ }
168+ } } )
169+
170+ return this . css
171+ }
172+
92173 /**
93174 * parse css rules
94175 * @param string css rules
95176 * @return string
96177 */
97178 parseCSSRules ( ) {
98- let params = { }
99- return this . rules
100- . split ( Parser . BREAK_LINE )
101- . filter ( d => d != Parser . EMPTY )
179+ return this . rules . split ( ICSS . BREAK_LINE )
180+ . filter ( d => d != ICSS . EMPTY )
102181 . map ( decl => {
103- if ( decl . includes ( Parser . END_BRACKET_RULE ) ) {
182+ if ( decl . includes ( ICSS . END_BRACKET_RULE ) ) {
104183 let [ p_keys , match , params , d ] = [ [ ] , [ ] , { } , decl ]
105- while ( match = Parser . REGEX_BRACKETS . exec ( d ) ) {
184+ while ( match = ICSS . REGEX_BRACKETS . exec ( d ) ) {
106185 p_keys . push ( match [ 1 ] )
107186 d = d . replace ( match [ 1 ] , '' )
108187 }
109188 p_keys . map ( p => {
110- if ( p . includes ( Parser . DATA_URI ) ) {
111- params [ p ] = Parser . REGEX_REPLACE ( p , Parser . DATA_URI_KEYS )
112- decl = Parser . REGEX_REPLACE ( decl , params )
189+ if ( p . includes ( ICSS . DATA_URI ) ) {
190+ params [ p ] = ICSS . REGEX_REPLACE ( p , ICSS . DATA_URI_KEYS )
191+ decl = ICSS . REGEX_REPLACE ( decl , params )
113192 }
114- } )
193+ } )
115194 }
116195
117196 return decl . trim ( )
118197 } ) . join ( '' )
119- // this.rules.pop()
120- // console.log(this.rules)
121- // this.rules = this.rule.join('')
122- return this . rules
123198 }
124199
125200 /**
@@ -129,7 +204,7 @@ class Parser {
129204 parseCSSQuery ( ) {
130205 return this . query
131206 . trim ( )
132- . split ( Parser . COMMA )
207+ . split ( ICSS . COMMA )
133208 . map ( s => s . trim ( ) )
134209 }
135210
@@ -139,9 +214,8 @@ class Parser {
139214 * @return string css
140215 */
141216 clearCode ( css = '' ) {
142- console . log ( this . css )
143- this . css = ( ( css != Parser . EMPTY ) ? css :this . css ) . replace ( Parser . REGEX_COMMENTS , Parser . EMPTY )
144- return Parser . REGEX_REPLACE ( this . css , { '\n' : '' , '\t' : '' } )
217+ this . css = ICSS . REGEX_REPLACE ( ( ( ( css != ICSS . EMPTY ) ? css :this . css ) . replace ( ICSS . REGEX_COMMENTS , ICSS . EMPTY ) ) , { '\n' : '' , '\t' : '' } )
218+ return this . css
145219 }
146220}
147221
@@ -170,21 +244,16 @@ class Rule {
170244 */
171245 set ( value ) {
172246 this . value = value
173- if ( this . value . includes ( Parser . END_BRACKET ) ) {
174- let str = Parser . REGEX_BRACKETS . exec ( this . value ) [ 1 ]
247+ if ( this . value . includes ( ICSS . END_BRACKET ) ) {
248+ let str = ICSS . REGEX_BRACKETS . exec ( this . value ) [ 1 ]
175249 this . detail = { }
176- this . detail . args = str . split ( Parser . COMMA ) . map ( p => p . trim ( ) )
177- this . detail . func = this . value . trim ( ) . replace ( `(${ str } )` , Parser . EMPTY )
250+ this . detail . args = str . split ( ICSS . COMMA ) . map ( p => p . trim ( ) )
251+ this . detail . func = this . value . trim ( ) . replace ( `(${ str } )` , ICSS . EMPTY )
178252 }
179253 return this . value
180254 }
181255}
182256
183257
184- window . onload = ( ) => {
185-
186- let cssText = document . styleSheets [ 0 ] . ownerNode . innerText
187- let parsed = ( new Parser ) . parseCSS ( cssText )
188- console . log ( parsed )
189-
190- }
258+ let cssText = document . styleSheets [ 0 ] . ownerNode . innerText
259+ console . log ( new Parser ( cssText ) )
0 commit comments