【问题标题】:Regex to extract HTML5 classes from a CSS selector string正则表达式从 CSS 选择器字符串中提取 HTML5 类
【发布时间】:2018-05-09 04:39:09
【问题描述】:

我正在从磁盘读取 CSS 文件作为字符串。

我的目标是提取与特定数据属性配对的 HTML 类,如下所示:

.foo[data-my-attr] 

data 属性足够独特,因此我不必费心遍历 CSS AST。我可以简单地使用这样的正则表达式:

(\.\S+)+\[data-my-attr\]

这已经可以了,但是\S+ 显然是在选择器中匹配 HTML 类的不好方法。它将包括各种组合器、伪类、伪选择器等。

我尝试构建正则表达式的白名单版本,例如。 G。 (\w|-)+,但是类名的 HTML5 规范非常宽松。我不可避免地会错过某些字符或包含不正确的字符。

什么正则表达式可用于从 CSS 选择器字符串中提取 HTML5 类

我正在使用节点,我。 e.正则表达式的 JavaScript 风格。

UPD1

一些例子:

  • .foo[data-my-attr] -- 应该匹配 .foo
  • .foo>span[data-my-attr] -- 不应该匹配
  • .I_f%⌘ing_♥_HTML5[data-my-attr] -- 应该匹配 .I_f%⌘ing_♥_HTML5

存在这个问题是因为我想不出所有可能的有效 HTML5 类。我需要一个基于令人惊讶的模糊 HTML5 类规范的正则表达式:

3.2.5.7 The class attribute

该属性(如果指定)必须具有一个值,该值是一组以空格分隔的标记,表示该元素所属的各种类。

一个 HTML 元素分配给它的类由所有在 class 属性的值按空格分割时返回的类组成。 (重复的被忽略。)

作者可以在 class 属性中使用的标记没有其他限制,但鼓励作者使用描述内容性质的值,而不是描述所需内容呈现的值。

显然,一个类不应该包含空格和字符,例如+>:()[]=~,因为它们是 CSS 选择器语法的一部分...

【问题讨论】:

  • 投票结束问题的人,请在 cmets 中说明可以修复哪些问题以使该问题有效。
  • 这个 stackoverflow.com/a/6329126/1156518 正则表达式扩展了您的特定属性是否适合您?
  • @DmitryDruganov 不,它对 HTML4 有效,但会省略许多 HTML5 有效的类,例如 #%LV-||_⌘⌥♥{©♤₩¤☆€~¥}
  • 请注意,# 不能在类名中,因为它是 id 的选择器。大括号也一样。
  • 您使用了错误的规范。相关规范不是 HTML5 规范,而是选择器规范,尤其是 selectors_group 生产。

标签: javascript css node.js regex html


【解决方案1】:

匹配选择器字符串中的 HTML5 类的正则表达式是:

/\.-?(?:[_a-z]|[\240-\377]|(?:(:?\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?)|\\[^\r\n\f0-9a-f]))(?:[_a-z0-9-]|[\240-\377]|(?:(:?\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?)|\\[^\r\n\f0-9a-f]))*/

信用:@KOBA789

感谢Alohci 指出正确的方向。

【讨论】:

  • 真的吗? #notaclass:after { content:".notaclasstoo { whatever you want"; } 呢?
  • @CasimiretHippolyte 您的示例不是有效的选择器。
  • 什么无效?
  • 您的代码示例是 CSS 规则,问题是关于 CSS 选择器。
  • 是的,这是一条 CSS 规则,但是您如何确保从包含引号部分的字符串中提取 CSS 选择器,即使使用描述所有可能选择器或您想要的选择器的模式?在引用的部分中,您还可以拥有与您的模式相匹配但不是选择器的内容。
【解决方案2】:

你不应该使用正则表达式。

一个更可靠的替代方案是 PostCSS(及其解析器)。 有了它,您将获得整个样式表的完整 AST(抽象语法树),您可以轻松提取所需的部分。

const postcss = require('postcss');
const Tokenizer = require('css-selector-tokenizer');

let output = [];

const postcssAttributes = postcss.plugin('postcss-attributes', function() {
  return function(css) {
    css.walkRules(function(rule) {
      rule.selectors.map(selector => {
        const tokenized = Tokenizer.parse(selector);
        if (
          tokenized.nodes.some(({ nodes }) =>
            nodes.some(
              node =>
                node.type === 'attribute' && node.content === 'data-my-attr'
            )
          )
        ) {
          output.push(selector);
        }
      });
    });
  };
});

const css = `
    .foo[data-my-attr] {
        color: red;
    }
    .foo[something] {
        color: red;
    }
`;

postcss([postcssAttributes])
  .process(css)
  .then(result => console.log(output));

// logs: [ '.foo[data-my-attr]' ]

这将记录所有匹配的选择器。

【讨论】:

  • 谢谢你的例子。我一直在考虑使用 CSS AST 并决定反对它有两个原因: 1. 它会使我的构建时间更长。 2.它没有解决从复合选择器中提取HTML类的问题,仍然需要正则表达式。
  • 我的例子确实支持复合选择器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 2021-10-19
  • 2018-02-23
相关资源
最近更新 更多