在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中生成解析器时,为什么要重新工作。

  1. Jison
  2. Peg.js
  3. Cruiser.Parse
  4. McLexer
  5. 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