1+ /**
2+ * ICSS Staments Interface
3+ */
14class ICSSStatments {
25 static get IMPORT ( ) { return 'import' }
36 static get MEDIA ( ) { return 'media' }
47 static get KEYFRAME ( ) { return 'keyframe' }
58 static get FONT_FACE ( ) { return 'font-face' }
69}
710
11+ /**
12+ * ICSS Symbols Interface
13+ */
814class ICSS {
915 static get EMPTY ( ) { return '' }
10-
1116 static get DOTS ( ) { return ':' }
12-
1317 static get COMMA ( ) { return ',' }
14-
1518 static get SEMICOLON ( ) { return ';' }
16-
1719 static get BREAK_LINE ( ) { return '\n' }
18-
1920 static get BEGIN_BLOCK ( ) { return '{' }
20-
2121 static get END_BLOCK ( ) { return '}' }
22-
22+ static get BEGIN_BRACKET ( ) { return '(' }
2323 static get END_BRACKET ( ) { return ')' }
24-
2524 static get DOUBLE_END_BRACKETS ( ) { return '}}' }
26-
2725 static get END_BRACKET_RULE ( ) { return ');' }
28-
2926 static get DATA_URI ( ) { return 'data:' }
30-
3127 static get DATA_URI_KEYS ( ) { return { ':' : '=' , ';' : '&' } }
32-
3328 static get DATA_URI_VALUES ( ) { return { '=' : ':' , '&' : ';' } }
34-
3529 static get REGEX_COMMENTS ( ) { return / \/ \* ( \r | \n | .) * \* \/ / g }
36-
3730 static get REGEX_BRACKETS ( ) { return / \( ( [ ^ ) ] + ) \) / }
38-
3931 static REGEX_REPLACE ( str , obj ) {
40- let re = new RegExp ( Object . keys ( obj ) . join ( '|' ) , 'g' )
41- return str . replace ( re , i => obj [ i ] )
32+ let re = new RegExp ( Object . keys ( obj ) . join ( '|' ) , 'g' )
33+ return str . replace ( re , i => obj [ i ] )
4234 }
4335}
4436
37+
4538/**
4639 * ParserCSS Class
4740 */
4841class Parser {
49-
42+
5043 /**
5144 * Initializate Parser
52- * @param string css (optional)
45+ * @param string css
5346 * @return object Parser
5447 */
5548 constructor ( css ) {
@@ -59,6 +52,7 @@ class Parser {
5952
6053 delete this . rules
6154 delete this . query
55+ delete this . blocksRule
6256 delete this . blockRules
6357 return this
6458 }
@@ -109,6 +103,10 @@ class Parser {
109103 }
110104
111105
106+ /**
107+ * Parse CSS Statments
108+ * @return string css
109+ */
112110 parseCSSStatments ( ) {
113111 this . statments = { imports :[ ] , medias :[ ] , keyframes :[ ] , font_faces :[ ] }
114112 this . css . split ( '@' ) . map ( blocklines => {
@@ -120,7 +118,6 @@ class Parser {
120118 let statment = `${ blockline [ 0 ] . replace ( '-' , '_' ) } s`
121119
122120 if ( blockline [ 0 ] == ICSSStatments . IMPORT ) {
123- console . log ( this . css )
124121 this . css = this . css . replace ( `@${ blocklines . split ( ICSS . SEMICOLON ) [ 0 ] } ;` , ICSS . EMPTY )
125122 let path_or_url = blocklines
126123 . split ( ICSS . SEMICOLON ) [ 0 ]
@@ -152,7 +149,6 @@ class Parser {
152149
153150 lines . map ( block => {
154151 let [ query , rules ] = block . split ( ICSS . BEGIN_BLOCK )
155-
156152 mediaBlocks . push ( {
157153 query : query . trim ( ) ,
158154 selectors : query . trim ( ) . split ( ICSS . COMMA ) . map ( s => s . trim ( ) ) ,
@@ -198,28 +194,80 @@ class Parser {
198194 }
199195
200196 /**
201- * parse css selectors
202- * @return array Selector
203- */
197+ * parse css selectors
198+ * @return array Selector
199+ */
204200 parseCSSQuery ( ) {
205- return this . query
206- . trim ( )
201+ return this . query . trim ( )
207202 . split ( ICSS . COMMA )
208- . map ( s => s . trim ( ) )
203+ . map ( s => new Selector ( s . trim ( ) ) )
209204 }
210205
211206 /**
212207 * clear code and remove comments
213208 * @param string css
214209 * @return string css
215- */
210+ */
216211 clearCode ( css = '' ) {
217- this . css = ICSS . REGEX_REPLACE ( ( ( ( css != ICSS . EMPTY ) ? css :this . css ) . replace ( ICSS . REGEX_COMMENTS , ICSS . EMPTY ) ) , { '\n' : '' , '\t' : '' } )
212+ this . css = ICSS . REGEX_REPLACE ( ( ( ( css != ICSS . EMPTY ) ? css :this . css )
213+ . replace ( ICSS . REGEX_COMMENTS , ICSS . EMPTY ) ) , { '\n' : '' , '\t' : '' } )
218214 return this . css
219215 }
220216}
221217
222218
219+ /**
220+ * Selector Class
221+ * selector object for query selectors
222+ */
223+ class Selector {
224+
225+ constructor ( s ) {
226+ this . selector = s
227+ return this . selector
228+ }
229+
230+ set selector ( s ) {
231+ let chars = {
232+ "#" : 'IDSelector' ,
233+ "." : 'ClassSelector' ,
234+ "[" : 'AttrSelector' ,
235+ ":" : 'PseudoSelector' ,
236+ "::" : 'PseudoElementSelector' ,
237+ } ; let signs = Object . keys ( chars ) ;
238+
239+ this . type = ( signs . includes ( s . substr ( 0 , 2 ) ) || signs . includes ( s [ 0 ] ) ) ?
240+ chars [ signs . filter ( i => s . substr ( 0 , 2 ) == i ) [ 0 ] || signs . filter ( i => s [ 0 ] == i ) ] :'HTMLElement'
241+
242+ let sel = s . replace ( Object . entries ( chars ) . map ( ( [ k , v ] ) => ( v == this . type ) ?k :'' ) . filter ( f => f != "" ) [ 0 ] , '' )
243+ Pseudo . _indexs . map ( p => {
244+ if ( sel . includes ( p ) )
245+ this . pseudo = new Pseudo ( p + sel . split ( p ) [ ( this . type == 'PseudoElementSelector' ) ? 2 :1 ] )
246+ } )
247+ }
248+ }
249+
250+
251+ /**
252+ * Pseudo Class
253+ * pseudo object for query selectors
254+ */
255+ class Pseudo {
256+
257+ constructor ( pseudo ) {
258+ this . _pseudo = pseudo
259+ this . type = ( pseudo [ 1 ] == ':' ) ? 'PseudoElement' :( pseudo [ 0 ] == ':' ) ? 'PseudoClass' :'PseudoEvent'
260+ }
261+
262+ get pseudo ( ) {
263+ return this . _pseudo . replace ( ( this . _pseudo [ 1 ] == ':' ) ? '::' :( this . _pseudo [ 0 ] == ':' ) ? ':' :'@' , '' )
264+ }
265+
266+ static get _indexs ( ) {
267+ return [ ':' , '::' , '@' ]
268+ }
269+ }
270+
223271/**
224272 * Rule Class
225273 */
@@ -233,24 +281,56 @@ class Rule {
233281 */
234282 constructor ( prop , value ) {
235283 this . prop = prop
236- this . value = this . set ( value )
284+ this . value = value
237285
238286 return this
239287 }
240288
241289 /**
242- * set details of value rule
243- * @return object
244- */
245- set ( value ) {
246- this . value = value
247- if ( this . value . includes ( ICSS . END_BRACKET ) ) {
248- let str = ICSS . REGEX_BRACKETS . exec ( this . value ) [ 1 ]
249- this . detail = { }
250- this . detail . args = str . split ( ICSS . COMMA ) . map ( p => p . trim ( ) )
251- this . detail . func = this . value . trim ( ) . replace ( `(${ str } )` , ICSS . EMPTY )
290+ * get property of rule
291+ * @return string property
292+ */
293+ get property ( ) {
294+ return this . prop
295+ }
296+
297+ /**
298+ * get value of rule
299+ * @return string value
300+ */
301+ get value ( ) {
302+ return this . _value . value
303+ }
304+
305+ /**
306+ * set value and details of rule
307+ * @param string val
308+ */
309+ set value ( val ) {
310+
311+ let func_values = [ ]
312+
313+ if ( val . includes ( ICSS . END_BRACKET ) ) {
314+ let value = val . split ( ICSS . END_BRACKET ) . map ( s => s . trim ( ) ) ; value . pop ( )
315+ let functions = value . map ( s => {
316+ let [ func , values ] = s . split ( ICSS . BEGIN_BRACKET ) . map ( s => s . trim ( ) ) ; let f = { }
317+ f [ func . replaceAll ( '-' , '_' ) ] = ( values . includes ( ICSS . DATA_URI ) ) ?
318+ [ values ] :values . split ( ICSS . COMMA ) . map ( v => v . trim ( ) . split ( ' ' ) )
319+
320+ func_values . push ( values )
321+ return f
322+ } )
323+
324+ this . details = { functions }
252325 }
253- return this . value
326+
327+ // trying support to many values of property
328+ // if (func_values.length > 0) {
329+ // let v = val.replace(new RegExp(func_values.join('|'), 'g'), '')
330+ // let values = v.split(ICSS.COMMA).map(s => s.trim())
331+ // }
332+
333+ this . _value = Object . assign ( { value : val } , this . details )
254334 }
255335}
256336
0 commit comments