如何从CSS选择器中提取类名? [英] How to extract class names from a CSS selector?

查看:154
本文介绍了如何从CSS选择器中提取类名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

故事:

我目前正在建立一个ESLint规则,以警告有关在CSS选择器定位器中使用面向引导程序布局的定向和角度技术类的警告.目前,我在字符串方法中使用了一个简单的子字符串:

I'm currently building a ESLint rule to warn about using bootstrap layout-oriented and angular technical classes inside CSS selector locators. Currently I'm using a simple substring in a string approach:

for (var i = 0; i < prohibitedClasses.length; i++) {
  if (node.arguments[0].value.indexOf(prohibitedClasses[i]) >= 0) {
    context.report({
      node: node,
      message: 'Unexpected Bootstrap class "' + prohibitedClasses[i] + '" inside a CSS selector'
    })
  }

但是它还没有被证明是可靠的.例如,它在.col-sm-offset-11 CSS选择器上抛出2次错误,报告同时使用col-sm-offset-1col-sm-offset-11.我可以想象它可以轻松地在使用了多个伪类的更复杂的选择器上中断.

But it has not proved to be reliable. For example, it throws an error 2 times on .col-sm-offset-11 CSS selector reporting both col-sm-offset-1 and col-sm-offset-11 to be used. I can imagine it can easily break on more complex selectors with multiple pseudo-classes used.

问题:

从CSS选择器中提取类名称的最可靠方法是什么?

What is the most reliable way to extract class names from a CSS selector?

这是我们应涵盖(有待改进)的示例测试列表:

Here is a sample test list we should cover (to be improved):

.col-sm-push-4                 // -> ['col-sm-push-4']
.myclass.col-lg-pull-8         // -> ['myclass', 'col-lg-pull-8']
[class*='col-md-offset-4']     // -> []
[class$=col-md-offset-11]      // -> []
[class~="col-md-10"] .myclass  // -> ['col-md-10', 'myclass']
.col-md-10,.col-md-11          // -> ['col-md-10', 'col-md-11']

请注意,我们需要跳过^=$=*=部分类过滤器值,而将~=保留下来(感谢您的评论).

Note that we need to skip the ^=, $= and *= partial class filter values leaving the ~= (thanks for the comments).

推荐答案

有一个专门为问题包设计的名为 node-css-selector-parser ,其中缺少如何使用它"部分来提取类名.填补空白,这是我将其应用于问题的方式.

There is a specially designed for the problem package called node-css-selector-parser which lacks the "how to use it" part to extract the class names. Filling the gap, here is how I've applied it to the problem.

使用node-css-selector-parser,我们可以解析CSS选择器,并根据结果类型分析带点使用的类名称(例如.myclass)和在属性选择器内部使用的类名称(例如[class*=test]):

With node-css-selector-parser, we can parse a CSS selector and based on a result type analyze class names used with a dot (e.g. .myclass) and class names used inside the attribute selector (e.g. [class*=test]):

// setup up CSS selector parser
var CssSelectorParser = require('css-selector-parser').CssSelectorParser
var parser = new CssSelectorParser()

parser.registerSelectorPseudos('has', 'contains')
parser.registerNestingOperators('>', '+', '~')
parser.registerAttrEqualityMods('^', '$', '*', '~')
parser.enableSubstitutes()

function extractClassNames (rule) {
  var classNames = []
  // extract class names defined with ".", e.g. .myclass
  if (rule.classNames) {
    classNames.push.apply(classNames, rule.classNames)
  }

  // extract class names defined in attributes, e.g. [class*=myclass]
  if (rule.attrs) {
    rule.attrs.forEach(function (attr) {
      if (attr.name === 'class') {
        classNames.push(attr.value)
      }
    })
  }

  return classNames
}

module.exports = function (cssSelector) {
  try {
    var result = parser.parse(cssSelector)
  } catch (err) {
    // ignore parsing errors - we don't want it to fail miserably on a target machine during a ESLint run
    console.log('Parsing CSS selector: "' + cssSelector + '". ' + err)
    return []
  }

  // handling empty inputs
  if (!result) {
    return []
  }

  var classNames = []

  if (result.type === 'ruleSet') {
    var rule = result.rule
    while (rule) {
      classNames.push.apply(classNames, extractClassNames(rule))
      rule = rule.rule
    }
  } else if (result.type === 'selectors' && result.selectors) {
    result.selectors.forEach(function (selector) {
      classNames.push.apply(classNames, extractClassNames(selector.rule))
    })
  }
  return classNames
}

( standard 代码样式-例如,在行的结尾)

(standard code style is used - hence, for instance, no ; at the end of the lines)

事实证明,这对我有用,并希望对其他有类似问题的人有所帮助.请注意,在此状态下,此代码还将提取传递到^=$=*=的部分类值,理想情况下,应将这些部分类值跳过.

This proved to work for me and hopefully would help others with a similar problem. Note that in this state this code would also extract the partial class values passed into the ^=, $= and *= which ideally need to be skipped.

这篇关于如何从CSS选择器中提取类名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆