Real Parser |
function parser(css) { var length = css.length, stack = [], context, nested, match, open, close, rule, rules, state = 'before-selector', buffer = 0, name, i = 0, char, nested, start;
this.cssText = css; this.rules = rules = context = [];
while (char = css.charAt(i++)) { switch(char) { case ' ': case '\t': case '\r': case '\n': case '\f': if (state === 'selector') { buffer++; } break; case '{': if (state === 'selector') { start = i - buffer - 1; rule = new Rule(css, css.slice(start, i - 1).trim(), start, i); context.push(rule); stack.push(context); context = rule.nested;
state = 'before-selector' buffer = 0; } break; case ';': if (state === 'selector') { state = 'before-selector'; buffer = 0; } break; case '}': if (state === 'before-selector') { context = stack.pop(); rule = context[context.length - 1]; if (rule) { rule.end = i; rule.declarationEnd = i - 1; } else { console.log('Closing unopened rule'); } state = "before-selector"; buffer = 0; } break; default: if (state === 'before-selector') { state = 'selector'; } buffer++; break; } }
return rules; }
var result = parser("h1 {\n color: red;\n }\n\n .some-class {\n color: #ff0;\n background: #f00;\n\n .nested {\n color: blue;\n\n .another {\n background: pink;\n }\n }\n }");
|
pending… |
Regex Parser |
function parser(css) { var length = css.length, stack = [], context, nested, match, open, close, rule, rules; this.cssText = css; this.rules = rules = context = [];
while (css) { open = css.indexOf('{'); close = css.indexOf('}'); if (open >= 0 && (close == -1 || open < close) && (match = css.match(openRe))) { css = css.slice(open + 1); rule = new Rule(this.cssText, match[2].trim(), length - css.length - match[1].length, length - css.length); context.push(rule); stack.push(context); context = rule.nested; } else if (close >= 0 && (open == -1 || close < open) && (match = css.match(closeRe))) { css = css.slice(close + match.length); context = stack.pop(); rule = context[context.length - 1]; if (rule) { rule.end = length - css.length; rule.declarationEnd = rule.end - match.length; } else { console.log('Closing unopened rule'); } } else { css = null; } }
// Pop remaining while (stack.length) { context = stack.pop(); rule = context[context.length - 1]; rule.end = rule.declarationEnd = length; console.log("Unclosed rule: '" + rule.selector + "'"); }
return rules; }
var result = parser("h1 {\n color: red;\n }\n\n .some-class {\n color: #ff0;\n background: #f00;\n\n .nested {\n color: blue;\n\n .another {\n background: pink;\n }\n }\n }");
|
pending… |
0 comments