@master/eslint-plugin-css 2.0.0-rc.70 → 2.0.0-rc.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -11
- package/dist/configs/recommended.cjs +4 -3
- package/dist/configs/recommended.mjs +4 -3
- package/dist/plugin.cjs +10 -6
- package/dist/plugin.mjs +10 -6
- package/dist/rules/no-conflicting-classes.cjs +101 -0
- package/dist/rules/no-conflicting-classes.d.ts +4 -0
- package/dist/rules/no-conflicting-classes.mjs +99 -0
- package/dist/rules/no-invalid-classes.cjs +51 -0
- package/dist/rules/{class-validation.d.ts → no-invalid-classes.d.ts} +1 -1
- package/dist/rules/no-invalid-classes.mjs +49 -0
- package/dist/rules/no-unapproved-raw-values.cjs +77 -0
- package/dist/rules/no-unapproved-raw-values.d.ts +8 -0
- package/dist/rules/no-unapproved-raw-values.mjs +75 -0
- package/dist/rules/prefer-canonical-classes.cjs +112 -0
- package/dist/rules/prefer-canonical-classes.d.ts +5 -0
- package/dist/rules/prefer-canonical-classes.mjs +110 -0
- package/dist/rules/{class-order.cjs → sort-classes.cjs} +10 -21
- package/dist/rules/{class-order.mjs → sort-classes.mjs} +10 -21
- package/dist/settings-schema.cjs +29 -23
- package/dist/settings-schema.d.ts +3 -2
- package/dist/settings-schema.mjs +25 -23
- package/dist/settings.cjs +2 -8
- package/dist/settings.d.ts +2 -2
- package/dist/settings.mjs +2 -8
- package/dist/utils/define-visitors.cjs +1 -1
- package/dist/utils/define-visitors.mjs +1 -1
- package/dist/utils/master-css.cjs +2 -82
- package/dist/utils/master-css.d.ts +0 -16
- package/dist/utils/master-css.mjs +1 -75
- package/dist/utils/resolve-class-node.cjs +18 -67
- package/dist/utils/resolve-class-node.d.ts +15 -7
- package/dist/utils/resolve-class-node.mjs +18 -67
- package/dist/utils/resolve-context.d.ts +1 -1
- package/package.json +1 -1
- package/dist/common.cjs +0 -7
- package/dist/common.d.ts +0 -2
- package/dist/common.mjs +0 -4
- package/dist/functions/filter-collision-classes.cjs +0 -29
- package/dist/functions/filter-collision-classes.d.ts +0 -2
- package/dist/functions/filter-collision-classes.mjs +0 -27
- package/dist/rules/class-collision.cjs +0 -76
- package/dist/rules/class-collision.d.ts +0 -4
- package/dist/rules/class-collision.mjs +0 -74
- package/dist/rules/class-validation.cjs +0 -60
- package/dist/rules/class-validation.mjs +0 -58
- /package/dist/rules/{class-order.d.ts → sort-classes.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ export default [
|
|
|
86
86
|
css,
|
|
87
87
|
{
|
|
88
88
|
rules: {
|
|
89
|
-
'@master/css/
|
|
89
|
+
'@master/css/no-invalid-classes': ['error', {
|
|
90
90
|
disallowUnknownClass: true
|
|
91
91
|
}]
|
|
92
92
|
}
|
|
@@ -96,29 +96,29 @@ export default [
|
|
|
96
96
|
|
|
97
97
|
## Rules
|
|
98
98
|
|
|
99
|
-
### `@master/css/
|
|
99
|
+
### `@master/css/sort-classes`
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Sorts Master CSS classes into a consistent and logical order.
|
|
102
102
|
|
|
103
103
|
```js
|
|
104
104
|
export default [
|
|
105
105
|
{
|
|
106
106
|
rules: {
|
|
107
|
-
'@master/css/
|
|
107
|
+
'@master/css/sort-classes': 'warn'
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
]
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
### `@master/css/
|
|
113
|
+
### `@master/css/no-invalid-classes`
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
Disallows invalid Master CSS classes.
|
|
116
116
|
|
|
117
117
|
```js
|
|
118
118
|
export default [
|
|
119
119
|
{
|
|
120
120
|
rules: {
|
|
121
|
-
'@master/css/
|
|
121
|
+
'@master/css/no-invalid-classes': 'error'
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
]
|
|
@@ -130,7 +130,7 @@ Set `disallowUnknownClass: true` to reject classes that do not match the active
|
|
|
130
130
|
export default [
|
|
131
131
|
{
|
|
132
132
|
rules: {
|
|
133
|
-
'@master/css/
|
|
133
|
+
'@master/css/no-invalid-classes': ['error', {
|
|
134
134
|
disallowUnknownClass: true
|
|
135
135
|
}]
|
|
136
136
|
}
|
|
@@ -138,20 +138,77 @@ export default [
|
|
|
138
138
|
]
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
### `@master/css/
|
|
141
|
+
### `@master/css/prefer-canonical-classes`
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
Prefers canonical Master CSS class forms, including semantic utilities, theme tokens, property aliases, composition utilities, and condition suffix order.
|
|
144
144
|
|
|
145
145
|
```js
|
|
146
146
|
export default [
|
|
147
147
|
{
|
|
148
148
|
rules: {
|
|
149
|
-
'@master/css/
|
|
149
|
+
'@master/css/prefer-canonical-classes': 'warn'
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
]
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
+
For example, this rule can fix `text-align:center` to `text-center`, `font:16px` to `font:md`, `margin:md` to `m:md`, `m:1rem|1.5rem` to `m:md|lg`, `fg:var(--color-red-60)` to `fg:red-60`, `w:md h:md` to `size:md`, `mt:md mb:md` to `my:md`, and `block@dark@sm` to `block@sm@dark`.
|
|
156
|
+
|
|
157
|
+
You can disable specific canonicalization families:
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
export default [
|
|
161
|
+
{
|
|
162
|
+
rules: {
|
|
163
|
+
'@master/css/prefer-canonical-classes': ['warn', {
|
|
164
|
+
preferStaticUtilities: true,
|
|
165
|
+
preferThemeTokens: true,
|
|
166
|
+
preferPropertyAliases: true,
|
|
167
|
+
preferVariableReferences: true,
|
|
168
|
+
preferMultiValueTokens: true,
|
|
169
|
+
preferCompositionUtilities: true,
|
|
170
|
+
preferConditionOrder: true
|
|
171
|
+
}]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### `@master/css/no-conflicting-classes`
|
|
178
|
+
|
|
179
|
+
Disallows classes that emit the same CSS declaration properties for the same variant.
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
export default [
|
|
183
|
+
{
|
|
184
|
+
rules: {
|
|
185
|
+
'@master/css/no-conflicting-classes': 'warn'
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
When two classes conflict, the later class is treated as the effective one and the fix removes the earlier class. For partially overlapping spacing, physical inset, radius, and border width/color/style shorthands, the fix preserves the surviving declarations by splitting the earlier class, such as `mx:md ml:lg` to `mr:md ml:lg` or `b-solid bt-dashed` to `br-solid bb-solid bl-solid bt-dashed`.
|
|
192
|
+
|
|
193
|
+
### `@master/css/no-unapproved-raw-values`
|
|
194
|
+
|
|
195
|
+
Disallows raw values in token-backed utilities unless they are explicitly allowed. This rule is opt-in team policy and is not enabled by the recommended config.
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
export default [
|
|
199
|
+
{
|
|
200
|
+
rules: {
|
|
201
|
+
'@master/css/no-unapproved-raw-values': ['warn', {
|
|
202
|
+
allowProperties: ['width', 'height'],
|
|
203
|
+
allowedPatterns: ['^var\\(', '^calc\\(']
|
|
204
|
+
}]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
For example, this rule reports `font:15px`, `m:17px`, and `fg:#123456` when those values are not theme tokens. It does not autofix because there may be no safe token replacement.
|
|
211
|
+
|
|
155
212
|
## Settings
|
|
156
213
|
|
|
157
214
|
Settings live under the `@master/css` settings key:
|
|
@@ -5,9 +5,10 @@ var base = require('./base.cjs');
|
|
|
5
5
|
var recommended = {
|
|
6
6
|
...base,
|
|
7
7
|
rules: {
|
|
8
|
-
'@master/css/
|
|
9
|
-
'@master/css/
|
|
10
|
-
'@master/css/
|
|
8
|
+
'@master/css/sort-classes': 'warn',
|
|
9
|
+
'@master/css/no-invalid-classes': 'error',
|
|
10
|
+
'@master/css/no-conflicting-classes': 'warn',
|
|
11
|
+
'@master/css/prefer-canonical-classes': 'warn'
|
|
11
12
|
}
|
|
12
13
|
};
|
|
13
14
|
|
|
@@ -3,9 +3,10 @@ import base from './base.mjs';
|
|
|
3
3
|
var recommended = {
|
|
4
4
|
...base,
|
|
5
5
|
rules: {
|
|
6
|
-
'@master/css/
|
|
7
|
-
'@master/css/
|
|
8
|
-
'@master/css/
|
|
6
|
+
'@master/css/sort-classes': 'warn',
|
|
7
|
+
'@master/css/no-invalid-classes': 'error',
|
|
8
|
+
'@master/css/no-conflicting-classes': 'warn',
|
|
9
|
+
'@master/css/prefer-canonical-classes': 'warn'
|
|
9
10
|
}
|
|
10
11
|
};
|
|
11
12
|
|
package/dist/plugin.cjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var noConflictingClasses = require('./rules/no-conflicting-classes.cjs');
|
|
4
|
+
var noInvalidClasses = require('./rules/no-invalid-classes.cjs');
|
|
5
|
+
var noUnapprovedRawValues = require('./rules/no-unapproved-raw-values.cjs');
|
|
6
|
+
var preferCanonicalClasses = require('./rules/prefer-canonical-classes.cjs');
|
|
7
|
+
var sortClasses = require('./rules/sort-classes.cjs');
|
|
6
8
|
var fs = require('fs');
|
|
7
9
|
var url = require('url');
|
|
8
10
|
var path = require('path');
|
|
@@ -17,9 +19,11 @@ const plugin = {
|
|
|
17
19
|
version: pkg.version
|
|
18
20
|
},
|
|
19
21
|
rules: {
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
22
|
+
'no-conflicting-classes': noConflictingClasses,
|
|
23
|
+
'no-invalid-classes': noInvalidClasses,
|
|
24
|
+
'no-unapproved-raw-values': noUnapprovedRawValues,
|
|
25
|
+
'prefer-canonical-classes': preferCanonicalClasses,
|
|
26
|
+
'sort-classes': sortClasses
|
|
23
27
|
}
|
|
24
28
|
};
|
|
25
29
|
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import noConflictingClasses from './rules/no-conflicting-classes.mjs';
|
|
2
|
+
import noInvalidClasses from './rules/no-invalid-classes.mjs';
|
|
3
|
+
import noUnapprovedRawValues from './rules/no-unapproved-raw-values.mjs';
|
|
4
|
+
import preferCanonicalClasses from './rules/prefer-canonical-classes.mjs';
|
|
5
|
+
import sortClasses from './rules/sort-classes.mjs';
|
|
4
6
|
import { readFileSync } from 'fs';
|
|
5
7
|
import { fileURLToPath } from 'url';
|
|
6
8
|
import { dirname, resolve } from 'path';
|
|
@@ -14,9 +16,11 @@ const plugin = {
|
|
|
14
16
|
version: pkg.version
|
|
15
17
|
},
|
|
16
18
|
rules: {
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
19
|
+
'no-conflicting-classes': noConflictingClasses,
|
|
20
|
+
'no-invalid-classes': noInvalidClasses,
|
|
21
|
+
'no-unapproved-raw-values': noUnapprovedRawValues,
|
|
22
|
+
'prefer-canonical-classes': preferCanonicalClasses,
|
|
23
|
+
'sort-classes': sortClasses
|
|
20
24
|
}
|
|
21
25
|
};
|
|
22
26
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var defineVisitors = require('../utils/define-visitors.cjs');
|
|
4
|
+
var resolveContext = require('../utils/resolve-context.cjs');
|
|
5
|
+
var createRule = require('../create-rule.cjs');
|
|
6
|
+
var cssLint = require('@master/css-lint');
|
|
7
|
+
|
|
8
|
+
var noConflictingClasses = createRule({
|
|
9
|
+
name: 'no-conflicting-classes',
|
|
10
|
+
meta: {
|
|
11
|
+
type: 'layout',
|
|
12
|
+
docs: {
|
|
13
|
+
description: 'Disallow conflicting Master CSS classes'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
collisionClass: '{{message}}',
|
|
17
|
+
partialCollisionClass: 'Prefer "{{replacement}}" over "{{actual}}" because "{{conflict}}" overrides part of it.'
|
|
18
|
+
},
|
|
19
|
+
fixable: 'code',
|
|
20
|
+
schema: []
|
|
21
|
+
},
|
|
22
|
+
defaultOptions: [],
|
|
23
|
+
create (context) {
|
|
24
|
+
const { settings, css } = resolveContext(context);
|
|
25
|
+
return defineVisitors({
|
|
26
|
+
context,
|
|
27
|
+
settings
|
|
28
|
+
}, (_, { raw, start, end, unescape, classNodes, classValues })=>{
|
|
29
|
+
const conflicts = cssLint.findClassConflicts(classValues, css);
|
|
30
|
+
if (conflicts.length) {
|
|
31
|
+
const classNamesToRemove = conflicts.map(({ className })=>className);
|
|
32
|
+
const keptClassNames = [
|
|
33
|
+
...new Set(conflicts.flatMap(({ conflicts })=>conflicts))
|
|
34
|
+
];
|
|
35
|
+
const formatClassName = (className)=>`"${className}"`;
|
|
36
|
+
const formatClassList = (classNames)=>{
|
|
37
|
+
if (classNames.length <= 2) return classNames.map(formatClassName).join(' and ');
|
|
38
|
+
return `${classNames.slice(0, -1).map(formatClassName).join(', ')}, and ${formatClassName(classNames[classNames.length - 1])}`;
|
|
39
|
+
};
|
|
40
|
+
const fixedRaw = cssLint.removeClassNamesFromClassList(raw, classNamesToRemove, {
|
|
41
|
+
unescape
|
|
42
|
+
});
|
|
43
|
+
const firstClassNode = classNodes.find((node)=>node.value === classNamesToRemove[0]);
|
|
44
|
+
context.report({
|
|
45
|
+
loc: firstClassNode.loc,
|
|
46
|
+
messageId: 'collisionClass',
|
|
47
|
+
data: {
|
|
48
|
+
message: `${formatClassList(classNamesToRemove)} ${classNamesToRemove.length === 1 ? 'is' : 'are'} overridden by ${formatClassList(keptClassNames)}.`
|
|
49
|
+
},
|
|
50
|
+
fix: function(fixer) {
|
|
51
|
+
return fixer.replaceTextRange([
|
|
52
|
+
start,
|
|
53
|
+
end
|
|
54
|
+
], fixedRaw);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const partialConflicts = cssLint.findPartialClassConflicts(classValues, css);
|
|
60
|
+
if (!partialConflicts.length) return;
|
|
61
|
+
let fixedRaw = raw;
|
|
62
|
+
for (const conflict of partialConflicts){
|
|
63
|
+
fixedRaw = cssLint.replaceClassNameInClassList(fixedRaw, conflict.className, conflict.replacement, {
|
|
64
|
+
unescape
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const classNodeQueues = new Map();
|
|
68
|
+
for (const classNode of classNodes){
|
|
69
|
+
const queue = classNodeQueues.get(classNode.value);
|
|
70
|
+
if (queue) {
|
|
71
|
+
queue.push(classNode);
|
|
72
|
+
} else {
|
|
73
|
+
classNodeQueues.set(classNode.value, [
|
|
74
|
+
classNode
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
for (const conflict of partialConflicts){
|
|
79
|
+
const classNode = classNodeQueues.get(conflict.className)?.shift();
|
|
80
|
+
if (!classNode) continue;
|
|
81
|
+
context.report({
|
|
82
|
+
loc: classNode.loc,
|
|
83
|
+
messageId: 'partialCollisionClass',
|
|
84
|
+
data: {
|
|
85
|
+
actual: conflict.className,
|
|
86
|
+
replacement: conflict.replacement,
|
|
87
|
+
conflict: conflict.conflict
|
|
88
|
+
},
|
|
89
|
+
fix (fixer) {
|
|
90
|
+
return fixer.replaceTextRange([
|
|
91
|
+
start,
|
|
92
|
+
end
|
|
93
|
+
], fixedRaw);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
module.exports = noConflictingClasses;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import defineVisitors from '../utils/define-visitors.mjs';
|
|
2
|
+
import resolveContext from '../utils/resolve-context.mjs';
|
|
3
|
+
import createRule from '../create-rule.mjs';
|
|
4
|
+
import { findClassConflicts, removeClassNamesFromClassList, findPartialClassConflicts, replaceClassNameInClassList } from '@master/css-lint';
|
|
5
|
+
|
|
6
|
+
var noConflictingClasses = createRule({
|
|
7
|
+
name: 'no-conflicting-classes',
|
|
8
|
+
meta: {
|
|
9
|
+
type: 'layout',
|
|
10
|
+
docs: {
|
|
11
|
+
description: 'Disallow conflicting Master CSS classes'
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
collisionClass: '{{message}}',
|
|
15
|
+
partialCollisionClass: 'Prefer "{{replacement}}" over "{{actual}}" because "{{conflict}}" overrides part of it.'
|
|
16
|
+
},
|
|
17
|
+
fixable: 'code',
|
|
18
|
+
schema: []
|
|
19
|
+
},
|
|
20
|
+
defaultOptions: [],
|
|
21
|
+
create (context) {
|
|
22
|
+
const { settings, css } = resolveContext(context);
|
|
23
|
+
return defineVisitors({
|
|
24
|
+
context,
|
|
25
|
+
settings
|
|
26
|
+
}, (_, { raw, start, end, unescape, classNodes, classValues })=>{
|
|
27
|
+
const conflicts = findClassConflicts(classValues, css);
|
|
28
|
+
if (conflicts.length) {
|
|
29
|
+
const classNamesToRemove = conflicts.map(({ className })=>className);
|
|
30
|
+
const keptClassNames = [
|
|
31
|
+
...new Set(conflicts.flatMap(({ conflicts })=>conflicts))
|
|
32
|
+
];
|
|
33
|
+
const formatClassName = (className)=>`"${className}"`;
|
|
34
|
+
const formatClassList = (classNames)=>{
|
|
35
|
+
if (classNames.length <= 2) return classNames.map(formatClassName).join(' and ');
|
|
36
|
+
return `${classNames.slice(0, -1).map(formatClassName).join(', ')}, and ${formatClassName(classNames[classNames.length - 1])}`;
|
|
37
|
+
};
|
|
38
|
+
const fixedRaw = removeClassNamesFromClassList(raw, classNamesToRemove, {
|
|
39
|
+
unescape
|
|
40
|
+
});
|
|
41
|
+
const firstClassNode = classNodes.find((node)=>node.value === classNamesToRemove[0]);
|
|
42
|
+
context.report({
|
|
43
|
+
loc: firstClassNode.loc,
|
|
44
|
+
messageId: 'collisionClass',
|
|
45
|
+
data: {
|
|
46
|
+
message: `${formatClassList(classNamesToRemove)} ${classNamesToRemove.length === 1 ? 'is' : 'are'} overridden by ${formatClassList(keptClassNames)}.`
|
|
47
|
+
},
|
|
48
|
+
fix: function(fixer) {
|
|
49
|
+
return fixer.replaceTextRange([
|
|
50
|
+
start,
|
|
51
|
+
end
|
|
52
|
+
], fixedRaw);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const partialConflicts = findPartialClassConflicts(classValues, css);
|
|
58
|
+
if (!partialConflicts.length) return;
|
|
59
|
+
let fixedRaw = raw;
|
|
60
|
+
for (const conflict of partialConflicts){
|
|
61
|
+
fixedRaw = replaceClassNameInClassList(fixedRaw, conflict.className, conflict.replacement, {
|
|
62
|
+
unescape
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const classNodeQueues = new Map();
|
|
66
|
+
for (const classNode of classNodes){
|
|
67
|
+
const queue = classNodeQueues.get(classNode.value);
|
|
68
|
+
if (queue) {
|
|
69
|
+
queue.push(classNode);
|
|
70
|
+
} else {
|
|
71
|
+
classNodeQueues.set(classNode.value, [
|
|
72
|
+
classNode
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const conflict of partialConflicts){
|
|
77
|
+
const classNode = classNodeQueues.get(conflict.className)?.shift();
|
|
78
|
+
if (!classNode) continue;
|
|
79
|
+
context.report({
|
|
80
|
+
loc: classNode.loc,
|
|
81
|
+
messageId: 'partialCollisionClass',
|
|
82
|
+
data: {
|
|
83
|
+
actual: conflict.className,
|
|
84
|
+
replacement: conflict.replacement,
|
|
85
|
+
conflict: conflict.conflict
|
|
86
|
+
},
|
|
87
|
+
fix (fixer) {
|
|
88
|
+
return fixer.replaceTextRange([
|
|
89
|
+
start,
|
|
90
|
+
end
|
|
91
|
+
], fixedRaw);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export { noConflictingClasses as default };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var defineVisitors = require('../utils/define-visitors.cjs');
|
|
4
|
+
var resolveContext = require('../utils/resolve-context.cjs');
|
|
5
|
+
var createRule = require('../create-rule.cjs');
|
|
6
|
+
var settingsSchema = require('../settings-schema.cjs');
|
|
7
|
+
var cssLint = require('@master/css-lint');
|
|
8
|
+
|
|
9
|
+
var noInvalidClasses = createRule({
|
|
10
|
+
name: 'no-invalid-classes',
|
|
11
|
+
meta: {
|
|
12
|
+
type: 'problem',
|
|
13
|
+
docs: {
|
|
14
|
+
description: 'Disallow invalid Master CSS classes'
|
|
15
|
+
},
|
|
16
|
+
messages: {
|
|
17
|
+
invalidClass: '{{message}}',
|
|
18
|
+
disallowUnknownClass: '{{message}}'
|
|
19
|
+
},
|
|
20
|
+
fixable: null,
|
|
21
|
+
schema: [
|
|
22
|
+
settingsSchema.noInvalidClassesOptionsSchema
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
defaultOptions: [],
|
|
26
|
+
create: function(context) {
|
|
27
|
+
const { options, settings, css } = resolveContext(context);
|
|
28
|
+
return defineVisitors({
|
|
29
|
+
context,
|
|
30
|
+
settings
|
|
31
|
+
}, (_, { classNodes })=>{
|
|
32
|
+
for (const node of classNodes){
|
|
33
|
+
const issues = cssLint.getClassValidationIssues(node.value, css, {
|
|
34
|
+
disallowUnknownClass: options.disallowUnknownClass,
|
|
35
|
+
displayClassName: node.raw
|
|
36
|
+
});
|
|
37
|
+
for (const issue of issues){
|
|
38
|
+
context.report({
|
|
39
|
+
loc: node.loc,
|
|
40
|
+
messageId: issue.kind === 'invalid' ? 'invalidClass' : 'disallowUnknownClass',
|
|
41
|
+
data: {
|
|
42
|
+
message: issue.message
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
module.exports = noInvalidClasses;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"
|
|
1
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"disallowUnknownClass" | "invalidClass", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
2
2
|
name: string;
|
|
3
3
|
};
|
|
4
4
|
export default _default;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import defineVisitors from '../utils/define-visitors.mjs';
|
|
2
|
+
import resolveContext from '../utils/resolve-context.mjs';
|
|
3
|
+
import createRule from '../create-rule.mjs';
|
|
4
|
+
import { noInvalidClassesOptionsSchema } from '../settings-schema.mjs';
|
|
5
|
+
import { getClassValidationIssues } from '@master/css-lint';
|
|
6
|
+
|
|
7
|
+
var noInvalidClasses = createRule({
|
|
8
|
+
name: 'no-invalid-classes',
|
|
9
|
+
meta: {
|
|
10
|
+
type: 'problem',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Disallow invalid Master CSS classes'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
invalidClass: '{{message}}',
|
|
16
|
+
disallowUnknownClass: '{{message}}'
|
|
17
|
+
},
|
|
18
|
+
fixable: null,
|
|
19
|
+
schema: [
|
|
20
|
+
noInvalidClassesOptionsSchema
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create: function(context) {
|
|
25
|
+
const { options, settings, css } = resolveContext(context);
|
|
26
|
+
return defineVisitors({
|
|
27
|
+
context,
|
|
28
|
+
settings
|
|
29
|
+
}, (_, { classNodes })=>{
|
|
30
|
+
for (const node of classNodes){
|
|
31
|
+
const issues = getClassValidationIssues(node.value, css, {
|
|
32
|
+
disallowUnknownClass: options.disallowUnknownClass,
|
|
33
|
+
displayClassName: node.raw
|
|
34
|
+
});
|
|
35
|
+
for (const issue of issues){
|
|
36
|
+
context.report({
|
|
37
|
+
loc: node.loc,
|
|
38
|
+
messageId: issue.kind === 'invalid' ? 'invalidClass' : 'disallowUnknownClass',
|
|
39
|
+
data: {
|
|
40
|
+
message: issue.message
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export { noInvalidClasses as default };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var defineVisitors = require('../utils/define-visitors.cjs');
|
|
4
|
+
var resolveContext = require('../utils/resolve-context.cjs');
|
|
5
|
+
var createRule = require('../create-rule.cjs');
|
|
6
|
+
var cssLint = require('@master/css-lint');
|
|
7
|
+
|
|
8
|
+
var noUnapprovedRawValues = createRule({
|
|
9
|
+
name: 'no-unapproved-raw-values',
|
|
10
|
+
meta: {
|
|
11
|
+
type: 'suggestion',
|
|
12
|
+
docs: {
|
|
13
|
+
description: 'Disallow unapproved raw values in token-backed Master CSS classes'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
unapprovedRawValue: 'Unexpected raw value "{{value}}" in "{{className}}". Use a token or allow it explicitly.'
|
|
17
|
+
},
|
|
18
|
+
fixable: null,
|
|
19
|
+
schema: [
|
|
20
|
+
{
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
allowRawValues: {
|
|
24
|
+
type: 'boolean'
|
|
25
|
+
},
|
|
26
|
+
allowProperties: {
|
|
27
|
+
type: 'array',
|
|
28
|
+
items: {
|
|
29
|
+
type: 'string'
|
|
30
|
+
},
|
|
31
|
+
uniqueItems: true
|
|
32
|
+
},
|
|
33
|
+
allowedPatterns: {
|
|
34
|
+
type: 'array',
|
|
35
|
+
items: {
|
|
36
|
+
type: 'string'
|
|
37
|
+
},
|
|
38
|
+
uniqueItems: true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
additionalProperties: false
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
defaultOptions: [
|
|
46
|
+
{
|
|
47
|
+
allowRawValues: false,
|
|
48
|
+
allowProperties: [],
|
|
49
|
+
allowedPatterns: []
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
create (context) {
|
|
53
|
+
const { settings, css } = resolveContext(context);
|
|
54
|
+
const options = context.options[0] || {};
|
|
55
|
+
return defineVisitors({
|
|
56
|
+
context,
|
|
57
|
+
settings
|
|
58
|
+
}, (node, { classNodes, classValues })=>{
|
|
59
|
+
const issues = cssLint.findUnapprovedRawValueClasses(classValues, css, options);
|
|
60
|
+
for (const issue of issues){
|
|
61
|
+
const classNode = classNodes.find((node)=>node.value === issue.className);
|
|
62
|
+
if (!classNode) continue;
|
|
63
|
+
context.report({
|
|
64
|
+
node,
|
|
65
|
+
loc: classNode.loc,
|
|
66
|
+
messageId: 'unapprovedRawValue',
|
|
67
|
+
data: {
|
|
68
|
+
className: issue.className,
|
|
69
|
+
value: issue.value
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
module.exports = noUnapprovedRawValues;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unapprovedRawValue", [{
|
|
2
|
+
allowRawValues: boolean;
|
|
3
|
+
allowProperties: any[];
|
|
4
|
+
allowedPatterns: any[];
|
|
5
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
6
|
+
name: string;
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|