更新2018 :这个问题早在PostCSS存在之前就被问过了,我可能会使用它。
我想将一小块CSS解析为AST,这样我就可以为某些CSS指令添加前缀。
是否有用于JavaScript或Node的CSS解析器可以执行此操作?
我搜索过NPM。我发现的唯一有用的结果是parser-lib,但它是基于流的,看起来我需要为每个CSS节点编写自己的发射器。
更新:我还找到了JSCSSP,但它没有文档......
答案 0 :(得分:10)
更新:我之前提到过JSCSSP,它似乎被放弃了。显然,NPM css module是最好的:
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)
输出:
#XXX body {
font-family: sans-serif;
}
#XXX #thing.foo p.bar {
font-weight: bold;
}
答案 1 :(得分:5)
另外值得一提的是LESS。虽然它主要是CSS的一个(奇妙的)扩展,但LESS解析器确实允许您访问AST。
纯CSS样式表也是一个有效的LESS样式表,因此您可以从现有的内容开始,轻松进入LESS'扩展。
答案 2 :(得分:4)
答案 3 :(得分:4)
这是我们的开源CSS解析器css.js
这是一个简单的解析示例:
<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>
在编辑后将解析后的数据结构串行化为CSS字符串
var newCSSString = parser.getCSSForEditor(parsed);
我们的CSS解析器的主要功能是:
答案 4 :(得分:2)
我最终使用的这个库足够轻便我的实现(在Kemal Dağ
的回答中提供)。对于我所追求的客户端实现,其他选项太重了。
https://github.com/jotform/css.js
a paid nerd
原始答案很有效,直到我点击媒体查询。
我不得不添加一些递归,这就是我最终的结果。
请原谅我的TypeScript。
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;
}
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;
}
答案 5 :(得分:1)
答案 6 :(得分:0)
无需使用外部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;
}
要插入规则
var sheetRef=document.getElementsByTagName("style")[0];
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
sheet.insertRule('.foo{color:red;}', 0);
要删除规则 所有浏览器,版本9之前的IE除外
var sheetRef=document.getElementsByTagName("style")[0];
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
sheet.removeRule (0);
要删除规则 所有浏览器,版本9之前的IE除外
var sheetRef=document.getElementsByTagName("style")[0];
var sheet = sheetRef.sheet ? sheetRef.sheet : sheetRef.styleSheet;
sheet.deleteRule (0);
添加媒体
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>
获取规则
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>