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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 11:39:37  来源:igfitidea点击:

CSS parser for JavaScript?

javascriptcssparsingnode.js

提问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 Jed Schmidt

For what it's worth, JSDOMuses CSSOM.

对于它的价值,JSDOM使用CSSOM

回答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 ??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>