Skip to content

Commit bc80c84

Browse files
committed
Added query parser and Rule class
1 parent 1e6d577 commit bc80c84

File tree

1 file changed

+115
-35
lines changed

1 file changed

+115
-35
lines changed

parsercss.js

Lines changed: 115 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,62 @@
11
/**
22
* ParserCSS Class
33
*/
4-
class Parser {
4+
class Parser {
55

6+
static get EMPTY() { return '' }
67

78
static get DOTS() { return ':' }
89

910
static get COMMA() { return ',' }
1011

1112
static get SEMICOLON() { return ';' }
1213

14+
static get BREAK_LINE() { return '\n' }
15+
1316
static get BEGIN_BLOCK() { return '{' }
1417

1518
static get END_BLOCK() { return '}' }
1619

20+
static get END_BRACKET() { return ')' }
21+
22+
static get END_BRACKET_RULE() { return ');' }
23+
24+
static get DATA_URI() { return 'data:' }
25+
26+
static get DATA_URI_KEYS() { return {':': '=', ';': '&'} }
27+
28+
static get DATA_URI_VALUES() { return {'=': ':', '&': ';'} }
29+
1730
static get REGEX_COMMENTS() { return /\/\*(\r|\n|.)*\*\//g }
1831

1932
static get REGEX_BRACKETS() { return /\(([^)]+)\)/ }
2033

34+
constructor(css) {
35+
this.css = css
36+
this.parseCSS()
37+
38+
delete this.rules
39+
return this
40+
}
41+
2142
/**
2243
* get blocks of queries and rules
2344
* @param string css
2445
* @return object rule
2546
*/
26-
parseCSS(css) {
47+
parseCSS(css = '') {
2748
let blocks = []
28-
let rules = this.remove(css).split(Parser.END_BLOCK)
29-
rules.pop()
30-
rules.map(block => {
31-
let [query, rule] = block.split(Parser.BEGIN_BLOCK)
49+
this.css = (css != Parser.EMPTY)? css:this.css
50+
this.blocksRule = this.clearCode().split(Parser.END_BLOCK)
51+
this.blocksRule.pop()
52+
53+
this.blocksRule.map(block => {
54+
[this.query, this.rules] = block.split(Parser.BEGIN_BLOCK)
55+
3256
blocks.push({
33-
query: query.trim(),
34-
selectors: query.trim().split(',').map(s => s.trim()),
35-
rule: this.parseCSSBlock(rule)
57+
query: this.query.trim(),
58+
selectors: this.parseCSSQuery(),
59+
rules: this.parseCSSBlock()
3660
})
3761
})
3862

@@ -44,44 +68,100 @@ class Parser {
4468
* @param string css
4569
* @return object rule
4670
*/
47-
parseCSSBlock(css) {
48-
let rule = {}
49-
let params = []
50-
const regex = /\(([^)]+)\)/;
71+
parseCSSBlock(rules = '') {
72+
let blockRules = []
73+
this.rules = (rules != Parser.EMPTY)? rules : this.rules
74+
this.parseCSSRules()
75+
.split(Parser.SEMICOLON)
76+
.map(decl => {
77+
let [prop, value] = decl.split(Parser.DOTS).map(i => i.trim())
78+
if (prop != Parser.EMPTY && value != Parser.EMPTY)
79+
blockRules.push(new Rule(prop, this._replaceAll(value, Parser.DATA_URI_VALUES)))
80+
})
81+
82+
return blockRules
83+
}
5184

52-
let decls = css.split('\n')
53-
.filter(d => d != "")
85+
/**
86+
* treat css selectors
87+
* @param string css rules
88+
* @return string
89+
*/
90+
parseCSSRules() {
91+
let params = {}
92+
return this.rules.split(Parser.BREAK_LINE)
93+
.filter(d => d != Parser.EMPTY)
5494
.map(decl => {
55-
if (decl.includes('('))
56-
params.push(Parser.REGEX_BRACKETS.exec(decl)[1])
95+
if (decl.includes(Parser.END_BRACKET_RULE)) {
96+
let p_key = Parser.REGEX_BRACKETS.exec(decl)[1]
97+
if (p_key.includes(Parser.DATA_URI)) {
98+
params[p_key] = this._replaceAll(p_key, Parser.DATA_URI_KEYS)
99+
decl = this._replaceAll(decl, params)
100+
}
101+
}
102+
57103
return decl.trim()
58104
}).join('')
105+
}
59106

60-
if (params.length > 0) {
61-
let _params = params.map(p => p.replace(':', '=').replace(';', '&'))
62-
decls = params.map((p, i) => {
63-
return decls.replace(p, _params[i])
64-
}).join('')
65-
}
107+
/**
108+
* parse css selectors
109+
* @return array Selector
110+
*/
111+
parseCSSQuery() {
112+
return this.query
113+
.trim()
114+
.split(Parser.COMMA)
115+
.map(s => s.trim())
116+
}
66117

67-
decls = decls.split(';')
68-
decls.pop()
118+
/**
119+
* clear code and remove comments
120+
* @param string css
121+
* @return string css
122+
*/
123+
clearCode(css = '') {
124+
this.css = ((css != Parser.EMPTY)? css:this.css)
125+
.replace(Parser.REGEX_COMMENTS, Parser.EMPTY)
126+
// .replaceAll({' ':'', '\n': '', '\t': ''})
127+
return this.css
128+
}
69129

70-
decls.map(decl => {
71-
let [prop, value] = decl.split(":").map(i => i.trim())
72-
if (prop != "" && value != "") rule[prop] = value.replace('=', ':').replace('&', ';')
73-
})
130+
_replaceAll(str, obj) {
131+
return str.replace((new RegExp(Object.keys(obj).join('|')), 'g'), i => obj[i])
132+
}
133+
}
134+
135+
136+
class Rule {
74137

75-
return rule
138+
/**
139+
* Rule Constructor
140+
* @param string prop
141+
* @param string value
142+
* @return object Rule
143+
*/
144+
constructor(prop, value) {
145+
this.prop = prop
146+
this.value = value
147+
this.details()
148+
149+
return this
76150
}
77151

78152
/**
79-
* remove comments
80-
* @param string css
81-
* @return string css
153+
* get details of value rule
154+
*
82155
*/
83-
remove(css) {
84-
return css.replace(this.REGEX_COMMENTS, "")
156+
details() {
157+
if (this.value.includes(Parser.END_BRACKET)) {
158+
let str = Parser.REGEX_BRACKETS.exec(this.value)[1]
159+
this.detail = {}
160+
this.detail.args = str.split(Parser.COMMA).map(p => p.trim())
161+
this.detail.func = this.value.trim().replace(`(${str})`, Parser.EMPTY)
162+
163+
return this.detail
164+
}
85165
}
86166
}
87167

0 commit comments

Comments
 (0)