JavaScript 的 CSS 解析器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10963997/
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
CSS parser for JavaScript?
提问by a paid nerd
Update 2018: This question was asked long before PostCSSexisted, and I would have probably used that.
2018 年更新:早在PostCSS出现之前就有人问过这个问题,我可能会使用它。
I'd like to parse a blob of CSS into an AST so I can add prefixes to certain CSS directives.
我想将一团 CSS 解析为 AST,以便我可以为某些 CSS 指令添加前缀。
Is there a CSS parser for JavaScript or Node that will do this?
是否有适用于 JavaScript 或 Node 的 CSS 解析器可以执行此操作?
I've searched NPM. The only useful result I've found is parser-lib, but it's stream-based and it looks like I'll need to write my own emitter for every CSS node.
我已经搜索了 NPM。我发现的唯一有用的结果是parser-lib,但它是基于流的,看起来我需要为每个 CSS 节点编写自己的发射器。
Update:I also found JSCSSP, but it has no documentation...
更新:我也找到了JSCSSP,但它没有文档......
采纳答案by a paid nerd
Update:I previously mentioned JSCSSP, which is buggy seems to be abandoned. Obviously enough, the css moduleon NPM is the best:
更新:我之前提到过 JSCSSP,这是 buggy 似乎被放弃了。显然,NPM 上的css 模块是最好的:
css = require 'css'
input = '''
body {
font-family: sans-serif;
}
#thing.foo p.bar {
font-weight: bold;
}
'''
obj = css.parse input
sheet = obj.stylesheet
for rule in sheet.rules
rule.selectors = ('#XXX ' + s for s in rule.selectors)
console.log css.stringify(obj)
Output:
输出:
#XXX body {
font-family: sans-serif;
}
#XXX #thing.foo p.bar {
font-weight: bold;
}
回答by josh3736
Also worth mentioning is LESS. While it is primarily a (fantastic) extension to CSS, the LESS parser does give you access to the AST.
另外值得一提的是LESS。虽然它主要是 CSS 的(了不起的)扩展,但 LESS 解析器确实可以让您访问 AST。
A pure CSS stylesheet is also a valid LESS stylesheet, so you can start with what you have now and ease in to LESS' extensions.
纯 CSS 样式表也是有效的 LESS 样式表,因此您可以从现有的样式开始,然后轻松使用 LESS 的扩展。
回答by Kemal Da?
Here is our open source CSS parser css.js
这是我们的开源 CSS 解析器css.js
Here is a simple parsing example :
这是一个简单的解析示例:
<script type="text/javascript">
var cssString = ' .someSelector { margin:40px 10px; padding:5px}';
//initialize parser object
var parser = new cssjs();
//parse css string
var parsed = parser.parseCSS(cssString);
console.log(parsed);
</script>
To stringify parsed data structure into CSS string after editing
编辑后将解析的数据结构字符串化为 CSS 字符串
var newCSSString = parser.getCSSForEditor(parsed);
Main features of our CSS parser is :
我们的 CSS 解析器的主要特点是:
- It is lightweight.
- It outputs easy to understand javascript object. No complex AST.
- It is battle tested(and unit tested also) and constantly used in our products(JotForm Form Designer).
- It supports media queries, keyframes and font-face rules.
- It preserves comments while parsing.
- 它很轻。
- 它输出易于理解的 javascript 对象。没有复杂的 AST。
- 它经过实战测试(也经过单元测试)并经常用于我们的产品(JotForm 表单设计器)。
- 它支持媒体查询、关键帧和字体规则。
- 它在解析时保留注释。
回答by CTS_AE
Edit
编辑
I ended up using this library which was light enough for my implementation (provided in Kemal Da?
's answer). Other options were too heavy for the client-side implementation I was after.
我最终使用了这个库,它对于我的实现来说足够轻(在Kemal Da?
的答案中提供)。其他选项对于我所追求的客户端实现来说太重了。
https://github.com/jotform/css.js
https://github.com/jotform/css.js
Original Content
原创内容
a paid nerd
's original answer worked great until I hit media queries.
a paid nerd
的原始答案效果很好,直到我点击媒体查询。
I had to add some recursion and this is what I ended up with.
我不得不添加一些递归,这就是我的结果。
Forgive me for the TypeScript.
原谅我打字稿。
TypeScript Implementation
打字稿实现
private scopeCSS(css: string): CSS.Stylesheet {
let ast: CSS.Stylesheet = CSS.parse(css);
let stylesheet: CSS.StyleRules|undefined = ast.stylesheet;
if (stylesheet) {
let rules: Array<CSS.Rule|CSS.Media> = stylesheet.rules;
let prefix = `[data-id='sticky-container-${this.parent.id}']`;
// Append our container scope to rules
// Recursive rule appender
let ruleAppend = (rules: Array<CSS.Rule|CSS.Media>) => {
rules.forEach(rule => {
let cssRule = <CSS.Rule>rule;
let mediaRule = <CSS.Media>rule;
if (cssRule.selectors !== undefined) {
cssRule.selectors = cssRule.selectors.map(selector => `${prefix} ${selector}`);
}
if (mediaRule.rules !== undefined) {
ruleAppend(mediaRule.rules);
}
});
};
ruleAppend(rules);
}
return ast;
}
Babel'ized Vanilla JS Implementation
Babel'ized Vanilla JS 实现
function scopeCSS(css, prefix) {
var ast = CSS.parse(css);
var stylesheet = ast.stylesheet;
if (stylesheet) {
var rules = stylesheet.rules;
// Append our container scope to rules
// Recursive rule appender
var ruleAppend = function(rules) {
rules.forEach(function(rule) {
if (rule.selectors !== undefined) {
rule.selectors = rule.selectors.map(function(selector) {
return prefix + " " + selector;
});
}
if (rule.rules !== undefined) {
ruleAppend(rule.rules);
}
});
};
ruleAppend(rules);
}
return ast;
}
回答by ddlshack
http://www.glazman.org/JSCSSP/
http://www.glazman.org/JSCSSP/
sheet
is sort of like an AST.
sheet
有点像 AST。
回答by ??l?j?
No need use external css parser,we can use native css parser
无需使用外部 css 解析器,我们可以使用原生 css 解析器
var sheetRef=document.getElementsByTagName("style")[0];
console.log("----------------list of rules--------------");
for (var i=0; i<sheetRef.sheet.cssRules.length; i++){
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
if (sheet.cssRules.length > 0) {
//console.log(sheet.cssRules[i]);
console.log(sheet.cssRules[i].selectorText);
console.log(sheet.cssRules[i].cssText);
}}
.red{
color:red;
}
To Insert Rule
插入规则
var sheetRef=document.getElementsByTagName("style")[0];
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
sheet.insertRule('.foo{color:red;}', 0);
To Remove Ruleall browsers, except IE before version 9
删除规则所有浏览器,版本 9 之前的 IE 除外
var sheetRef=document.getElementsByTagName("style")[0];
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
sheet.removeRule (0);
To Delete Ruleall browsers, except IE before version 9
删除规则所有浏览器,版本 9 之前的 IE 除外
var sheetRef=document.getElementsByTagName("style")[0];
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
sheet.deleteRule (0);
To add Media
添加媒体
function AddScreenMedia () {
var styleTag = document.getElementsByTagName("style")[0];
// the style sheet in the style tag
var sheet = styleTag.sheet ? styleTag.sheet : styleTag.styleSheet;
if (sheet.cssRules) { // all browsers, except IE before version 9
var rule = sheet.cssRules[0];
var mediaList = rule.media;
alert ("The media types before adding the screen media type: " + mediaList.mediaText);
mediaList.appendMedium ("screen");
alert ("The media types after adding the screen media type: " + mediaList.mediaText);
}
else { // Internet Explorer before version 9
// note: the rules collection does not contain the at-rules
alert ("Your browser does not support this example!");
}
}
@media print {
body {
font-size: 13px;
color: #FF0000;
}
}
some text
<button onclick="AddScreenMedia ();">Add screen media</button>
To get rules
获取规则
var sheetRef=document.getElementsByTagName("style")[0];
console.log("----------------list of rules--------------");
for (var i=0; i<sheetRef.sheet.cssRules.length; i++){
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
if (sheet.cssRules.length > 0) {
//console.log(sheet.cssRules[i]);
console.log(sheet.cssRules[i].selectorText);
console.log(sheet.cssRules[i].cssText);
console.log(sheet.cssRules[i].style.color)
console.log(sheet.cssRules[i].style.background)
console.log(sheet.cssRules[i].style)
}}
.red{
color:red;
background:orange;
}
<h1>red</h1>