在 JavaScript / jQuery 中解析 CSS
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3326494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parsing CSS in JavaScript / jQuery
提问by ankit
I'm trying to implement parsing of CSS in JavaScript so that:
我正在尝试在 JavaScript 中实现 CSS 解析,以便:
a {
color: red;
}
is parsed into the object:
被解析为对象:
{
'a' {
'color': 'red'
}
}
First off, is there a JavaScript / jQuery libraryI can use?
首先,我可以使用JavaScript / jQuery库吗?
My implementation is pretty basic, so I'm sure it is not fool-proof by any means. For example, it works fine for basic CSS, but for a property of the type:
我的实现非常基础,所以我确信它无论如何都不是万无一失的。例如,它适用于基本 CSS,但适用于以下类型的属性:
background: url(data:image/png;base64, ....);
It fails because I am using split(';')to separate property:valuepairs. Here, ;occurs in the value, so it splits at that point too.
它失败了,因为我正在使用split(';')分隔property:value对。在这里,;发生在 中value,所以它也在那个点分裂。
Is there an alternate way to do this?
有没有其他方法可以做到这一点?
Here is the code:
这是代码:
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,"");
}
Thanks!
谢谢!
采纳答案by Matthew Manela
回答by cburgmer
You can easily use the Browser's own CSSOM to parse CSS:
您可以轻松地使用浏览器自带的 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;
};
For each rule returned you can look at the properties in rule.style. See http://jsfiddle.net/v2JsZ/for an example.
对于返回的每个规则,您可以查看 中的属性rule.style。有关示例,请参见http://jsfiddle.net/v2JsZ/。
回答by Anurag
To write the most fool-proof parser, follow the exact rules for tokenizationand CSS grammaras defined in the spec. Note that you don't have to implement the spec by the ink. You can start with small parts and CSS that you will most likely encounter, and then expand from there. Even better, skip the entire process altogether and go with @Matthew's solution unless this is a learning exercise.
要编写最简单的解析器,请遵循规范中定义的标记化和 CSS语法的确切规则。请注意,您不必通过墨水实现规范。您可以从最有可能遇到的小部件和 CSS 开始,然后从那里扩展。更好的是,除非这是一个学习练习,否则完全跳过整个过程并使用@Matthew 的解决方案。
There are various lexical scanners and parser generators available for JavaScript. The entire grammar is available on w3's website. Why do the re-work when you can simply use that and the parser generators to generate the parser in JavaScript.
有多种可用于 JavaScript 的词法扫描器和解析器生成器。整个语法可在 w3 的网站上找到。当您可以简单地使用它和解析器生成器在 JavaScript 中生成解析器时,为什么还要重新工作。
The production rules for CSS are given below.
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 (i.e., [0-9a-fA-F])
* after the "#"; e.g., "#000" is OK, but "#abcd" is not.
*/
hexcolor
: HASH S*
;
回答by Olexiy Zamkoviy
Simple example, not tested but should work, I'm using similar in my project.
简单的例子,没有经过测试但应该可以工作,我在我的项目中使用了类似的。
var div = jQuery('<div/>');
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

