|
1 | 1 | import stylelint from 'stylelint' |
2 | | -import type { Root } from 'postcss' |
3 | | -import { AT_RULE } from '@projectwallace/css-parser/nodes' |
4 | | -import { walk } from '@projectwallace/css-parser/walker' |
5 | | -import { parse } from '@projectwallace/css-parser/parse' |
| 2 | +import type { Root, AtRule } from 'postcss' |
| 3 | +import { isAllowed } from '../../utils/allow-list.js' |
6 | 4 |
|
7 | 5 | const { createPlugin, utils } = stylelint |
8 | 6 |
|
@@ -31,63 +29,39 @@ const ruleFunction = (primaryOptions: true, secondaryOptions?: SecondaryOptions) |
31 | 29 | return |
32 | 30 | } |
33 | 31 |
|
34 | | - const css = root.toString() |
35 | | - const parsed = parse(css, { |
36 | | - parse_selectors: false, |
37 | | - parse_values: false, |
38 | | - }) |
39 | | - const line_offset = (root.source?.start?.line ?? 1) - 1 |
40 | | - |
41 | | - const declared_layers = new Map<string, { line: number; column: number }>() |
| 32 | + const declared_layers = new Map<string, AtRule>() |
42 | 33 | const defined_layers = new Set<string>() |
43 | 34 |
|
44 | | - walk(parsed, (node) => { |
45 | | - if (node.type !== AT_RULE) return |
46 | | - if (node.name !== 'layer') return |
47 | | - |
48 | | - if (node.has_block) { |
| 35 | + root.walkAtRules('layer', (atRule) => { |
| 36 | + if (atRule.nodes !== undefined) { |
49 | 37 | // Block rule: @layer name { ... } |
50 | | - const name = node.prelude?.text.trim() |
| 38 | + const name = atRule.params.trim() |
51 | 39 | if (name) { |
52 | 40 | defined_layers.add(name) |
53 | 41 | } |
54 | 42 | } else { |
55 | 43 | // Statement: @layer name; or @layer a, b, c; |
56 | | - const prelude_text = node.prelude?.text ?? '' |
57 | | - const names = prelude_text |
| 44 | + const names = atRule.params |
58 | 45 | .split(',') |
59 | 46 | .map((n) => n.trim()) |
60 | 47 | .filter(Boolean) |
61 | 48 | for (const name of names) { |
62 | 49 | if (!declared_layers.has(name)) { |
63 | | - declared_layers.set(name, { line: node.line, column: node.column }) |
| 50 | + declared_layers.set(name, atRule) |
64 | 51 | } |
65 | 52 | } |
66 | 53 | } |
67 | 54 | }) |
68 | 55 |
|
69 | | - for (const [layer, pos] of declared_layers) { |
| 56 | + for (const [layer, node] of declared_layers) { |
70 | 57 | if (defined_layers.has(layer)) continue |
71 | | - |
72 | | - if (secondaryOptions?.allowlist) { |
73 | | - const allowed = secondaryOptions.allowlist.some( |
74 | | - (pattern) => |
75 | | - (typeof pattern === 'string' && pattern === layer) || |
76 | | - (pattern instanceof RegExp && pattern.test(layer)), |
77 | | - ) |
78 | | - if (allowed) continue |
79 | | - } |
| 58 | + if (secondaryOptions?.allowlist && isAllowed(layer, secondaryOptions.allowlist)) continue |
80 | 59 |
|
81 | 60 | utils.report({ |
82 | 61 | result, |
83 | 62 | ruleName: rule_name, |
84 | 63 | message: messages.rejected(layer), |
85 | | - node: root, |
86 | | - start: { line: pos.line + line_offset, column: pos.column }, |
87 | | - end: { |
88 | | - line: pos.line + line_offset, |
89 | | - column: pos.column + '@layer'.length, |
90 | | - }, |
| 64 | + node, |
91 | 65 | word: layer, |
92 | 66 | }) |
93 | 67 | } |
|
0 commit comments