在JavaScript / jQuery中解析CSS
我正在尝试在JavaScript中实现CSS解析,以便:
a { color: red; }
被解析为对象:
{ 'a' { 'color': 'red' } }
首先,我可以使用JavaScript / jQuery 库吗?
我的实现非常基础,所以我确信它无论如何都不是万无一失的。 例如,它适用于基本CSS,但对于类型的属性:
background: url(data:image/png;base64, ....);
它失败了,因为我使用split(';')
来分隔property:value
对。 在这里, ;
发生在value
,因此它也会在该点处分裂。
还有另一种方法吗?
这是代码:
parseCSS: function(css) { var rules = {}; css = this.removeComments(css); var blocks = css.split('}'); blocks.pop(); var len = blocks.length; for (var i = 0; i < len; i++) { var pair = blocks[i].split('{'); rules[$.trim(pair[0])] = this.parseCSSBlock(pair[1]); } return rules; }, parseCSSBlock: function(css) { var rule = {}; var declarations = css.split(';'); declarations.pop(); var len = declarations.length; for (var i = 0; i < len; i++) { var loc = declarations[i].indexOf(':'); var property = $.trim(declarations[i].substring(0, loc)); var value = $.trim(declarations[i].substring(loc + 1)); if (property != "" && value != "") rule[property] = value; } return rule; }, removeComments: function(css) { return css.replace(/\/\*(\r|\n|.)*\*\//g,""); }
谢谢!
有一个用Javascript编写的CSS解析器叫做JSCSSP
您可以轻松使用浏览器自己的CSSOM来解析CSS:
var rulesForCssText = function (styleContent) { var doc = document.implementation.createHTMLDocument(""), styleElement = document.createElement("style"); styleElement.textContent = styleContent; // the style will only be parsed once it is added to a document doc.body.appendChild(styleElement); return styleElement.sheet.cssRules; };
对于返回的每个规则,您可以查看rule.style
中的属性。 有关示例,请参见http://jsfiddle.net/v2JsZ/ 。
要编写最傻瓜式的解析器,请遵循规范中定义的标记化和CSS 语法的确切规则。 请注意,您不必通过墨水实现规范。 您可以从最有可能遇到的小部件和CSS开始,然后从那里扩展。 更好的是,完全跳过整个过程并使用@ Matthew的解决方案,除非这是一个学习练习。
JavaScript中有各种词法扫描程序和解析器生成器。 整个语法可以在w3的网站上找到。 当你可以简单地使用它和解析器生成器在JavaScript中生成解析器时,为什么要重新工作。
- Jison
- Peg.js
- Cruiser.Parse
- McLexer
- JS / CC
CSS的生产规则如下。
stylesheet : [ CHARSET_SYM STRING ';' ]? [S|CDO|CDC]* [ import [ CDO S* | CDC S* ]* ]* [ [ ruleset | media | page ] [ CDO S* | CDC S* ]* ]* ; import : IMPORT_SYM S* [STRING|URI] S* media_list? ';' S* ; media : MEDIA_SYM S* media_list LBRACE S* ruleset* '}' S* ; media_list : medium [ COMMA S* medium]* ; medium : IDENT S* ; page : PAGE_SYM S* pseudo_page? '{' S* declaration? [ ';' S* declaration? ]* '}' S* ; pseudo_page : ':' IDENT S* ; operator : '/' S* | ',' S* ; combinator : '+' S* | '>' S* ; unary_operator : '-' | '+' ; property : IDENT S* ; ruleset : selector [ ',' S* selector ]* '{' S* declaration? [ ';' S* declaration? ]* '}' S* ; selector : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]? ; simple_selector : element_name [ HASH | class | attrib | pseudo ]* | [ HASH | class | attrib | pseudo ]+ ; class : '.' IDENT ; element_name : IDENT | '*' ; attrib : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* [ IDENT | STRING ] S* ]? ']' ; pseudo : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ] ; declaration : property ':' S* expr prio? ; prio : IMPORTANT_SYM S* ; expr : term [ operator? term ]* ; term : unary_operator? [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* ] | STRING S* | IDENT S* | URI S* | hexcolor | function ; function : FUNCTION S* expr ')' S* ; /* * There is a constraint on the color that it must * have either 3 or 6 hex-digits (ie, [0-9a-fA-F]) * after the "#"; eg, "#000" is OK, but "#abcd" is not. */ hexcolor : HASH S* ;
简单的例子,没有测试但应该工作,我在我的项目中使用类似的。
var div = jQuery(''); div[0].style = 'position:absolute;left:5px;top:10px;'; //Css to parse div.css('left'); // => '5px' div.css('top'); // => '10px' div[0].style; // => Object containing all css