@d-zero/stylelint-rules 5.0.0-alpha.67 → 5.0.0-alpha.69
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/dist/index.js +8 -1
- package/dist/rules/prefer-individual-transform-properties/index.js +83 -0
- package/dist/rules/prefer-individual-transform-properties/index.spec.js +137 -0
- package/dist/rules/shorthand-property-use-logical/index.js +92 -0
- package/dist/rules/shorthand-property-use-logical/index.spec.js +162 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import component from './rules/component/index.js';
|
|
2
2
|
import declarationValueTypeDisallowedList from './rules/declaration-value-type-disallowed-list/index.js';
|
|
3
|
-
|
|
3
|
+
import preferIndividualTransformProperties from './rules/prefer-individual-transform-properties/index.js';
|
|
4
|
+
import shorthandPropertyUseLogical from './rules/shorthand-property-use-logical/index.js';
|
|
5
|
+
export default [
|
|
6
|
+
component,
|
|
7
|
+
declarationValueTypeDisallowedList,
|
|
8
|
+
preferIndividualTransformProperties,
|
|
9
|
+
shorthandPropertyUseLogical,
|
|
10
|
+
];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import postcssValueParser from 'postcss-value-parser';
|
|
2
|
+
import stylelint from 'stylelint';
|
|
3
|
+
import { createRule } from '../../utils/create-rule.js';
|
|
4
|
+
/**
|
|
5
|
+
* Transform functions that can be replaced with individual properties
|
|
6
|
+
*/
|
|
7
|
+
const REPLACEABLE_TRANSFORM_FUNCTIONS = {
|
|
8
|
+
// cspell:disable-next-line
|
|
9
|
+
translate: ['translate', 'translatex', 'translatey', 'translate3d'],
|
|
10
|
+
// cspell:disable-next-line
|
|
11
|
+
rotate: ['rotate', 'rotatex', 'rotatey', 'rotatez', 'rotate3d'],
|
|
12
|
+
// cspell:disable-next-line
|
|
13
|
+
scale: ['scale', 'scalex', 'scaley', 'scale3d'],
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Check if a transform value contains only functions that can be replaced
|
|
17
|
+
* @param value
|
|
18
|
+
*/
|
|
19
|
+
function canBeReplacedWithIndividualProperties(value) {
|
|
20
|
+
const parsed = postcssValueParser(value);
|
|
21
|
+
const suggestions = [];
|
|
22
|
+
const foundTransformTypes = new Set(); // Track types of transforms found
|
|
23
|
+
let hasReplaceableFunction = false;
|
|
24
|
+
let hasNonReplaceableFunction = false;
|
|
25
|
+
parsed.walk((node) => {
|
|
26
|
+
if (node.type === 'function') {
|
|
27
|
+
const functionName = node.value.toLowerCase();
|
|
28
|
+
let isReplaceable = false;
|
|
29
|
+
// Check each category of replaceable functions
|
|
30
|
+
for (const [property, functions] of Object.entries(REPLACEABLE_TRANSFORM_FUNCTIONS)) {
|
|
31
|
+
if (functions.includes(functionName)) {
|
|
32
|
+
isReplaceable = true;
|
|
33
|
+
hasReplaceableFunction = true;
|
|
34
|
+
foundTransformTypes.add(property);
|
|
35
|
+
// Generate suggestion based on function type
|
|
36
|
+
const args = postcssValueParser.stringify(node.nodes);
|
|
37
|
+
suggestions.push(`${property}: ${args}`);
|
|
38
|
+
// Don't walk into the arguments of transform functions
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!isReplaceable) {
|
|
43
|
+
hasNonReplaceableFunction = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
});
|
|
48
|
+
// Only suggest replacement if:
|
|
49
|
+
// 1. We found replaceable functions
|
|
50
|
+
// 2. We found no non-replaceable functions
|
|
51
|
+
// 3. We only found ONE type of transform (translate, rotate, or scale)
|
|
52
|
+
const canReplace = hasReplaceableFunction &&
|
|
53
|
+
!hasNonReplaceableFunction &&
|
|
54
|
+
foundTransformTypes.size === 1;
|
|
55
|
+
return {
|
|
56
|
+
canReplace,
|
|
57
|
+
suggestions: canReplace ? suggestions : [],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export default createRule({
|
|
61
|
+
name: 'prefer-individual-transform-properties',
|
|
62
|
+
rejected: (value, suggestions) => `Use individual transform properties instead of "transform: ${value}". Consider: ${suggestions}`,
|
|
63
|
+
rule: (ruleName, messages) => () => {
|
|
64
|
+
return (root, result) => {
|
|
65
|
+
root.walkDecls((decl) => {
|
|
66
|
+
// Only check transform property
|
|
67
|
+
if (decl.prop.toLowerCase() !== 'transform') {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const { canReplace, suggestions } = canBeReplacedWithIndividualProperties(decl.value);
|
|
71
|
+
// If we can replace and have suggestions, report the issue
|
|
72
|
+
if (canReplace && suggestions.length > 0) {
|
|
73
|
+
stylelint.utils.report({
|
|
74
|
+
result,
|
|
75
|
+
ruleName,
|
|
76
|
+
message: messages.rejected(decl.value, suggestions.join(', ')),
|
|
77
|
+
node: decl,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import stylelint from 'stylelint';
|
|
2
|
+
import { describe, test, expect } from 'vitest';
|
|
3
|
+
import plugin from './index.js';
|
|
4
|
+
const ruleName = '@d-zero/prefer-individual-transform-properties';
|
|
5
|
+
/**
|
|
6
|
+
* Helper function to run stylelint with the plugin
|
|
7
|
+
* @param code
|
|
8
|
+
* @param options
|
|
9
|
+
*/
|
|
10
|
+
async function lint(code, options) {
|
|
11
|
+
const result = await stylelint.lint({
|
|
12
|
+
code,
|
|
13
|
+
config: {
|
|
14
|
+
plugins: [plugin],
|
|
15
|
+
rules: {
|
|
16
|
+
[ruleName]: options || true,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
return result.results[0]?.warnings || [];
|
|
21
|
+
}
|
|
22
|
+
describe('prefer-individual-transform-properties', () => {
|
|
23
|
+
test('should flag simple translate function', async () => {
|
|
24
|
+
const warnings = await lint(`
|
|
25
|
+
.element {
|
|
26
|
+
transform: translate(10px, 20px);
|
|
27
|
+
}
|
|
28
|
+
`);
|
|
29
|
+
expect(warnings).toHaveLength(1);
|
|
30
|
+
expect(warnings[0]?.text).toContain('translate: 10px, 20px');
|
|
31
|
+
});
|
|
32
|
+
test('should flag simple rotate function', async () => {
|
|
33
|
+
const warnings = await lint(`
|
|
34
|
+
.element {
|
|
35
|
+
transform: rotate(45deg);
|
|
36
|
+
}
|
|
37
|
+
`);
|
|
38
|
+
expect(warnings).toHaveLength(1);
|
|
39
|
+
expect(warnings[0]?.text).toContain('rotate: 45deg');
|
|
40
|
+
});
|
|
41
|
+
test('should flag simple scale function', async () => {
|
|
42
|
+
const warnings = await lint(`
|
|
43
|
+
.element {
|
|
44
|
+
transform: scale(1.5);
|
|
45
|
+
}
|
|
46
|
+
`);
|
|
47
|
+
expect(warnings).toHaveLength(1);
|
|
48
|
+
expect(warnings[0]?.text).toContain('scale: 1.5');
|
|
49
|
+
});
|
|
50
|
+
test('should flag translateX function', async () => {
|
|
51
|
+
const warnings = await lint(`
|
|
52
|
+
.element {
|
|
53
|
+
transform: translateX(10px);
|
|
54
|
+
}
|
|
55
|
+
`);
|
|
56
|
+
expect(warnings).toHaveLength(1);
|
|
57
|
+
expect(warnings[0]?.text).toContain('translate: 10px');
|
|
58
|
+
});
|
|
59
|
+
test('should flag rotateY function', async () => {
|
|
60
|
+
const warnings = await lint(`
|
|
61
|
+
.element {
|
|
62
|
+
transform: rotateY(90deg);
|
|
63
|
+
}
|
|
64
|
+
`);
|
|
65
|
+
expect(warnings).toHaveLength(1);
|
|
66
|
+
expect(warnings[0]?.text).toContain('rotate: 90deg');
|
|
67
|
+
});
|
|
68
|
+
test('should flag scaleX function', async () => {
|
|
69
|
+
const warnings = await lint(`
|
|
70
|
+
.element {
|
|
71
|
+
transform: scaleX(2);
|
|
72
|
+
}
|
|
73
|
+
`);
|
|
74
|
+
expect(warnings).toHaveLength(1);
|
|
75
|
+
expect(warnings[0]?.text).toContain('scale: 2');
|
|
76
|
+
});
|
|
77
|
+
test('should not flag complex transforms with multiple different functions', async () => {
|
|
78
|
+
const warnings = await lint(`
|
|
79
|
+
.element {
|
|
80
|
+
transform: translate(10px, 20px) rotate(45deg) scale(1.5);
|
|
81
|
+
}
|
|
82
|
+
`);
|
|
83
|
+
// This contains multiple transform types, so it cannot be easily replaced
|
|
84
|
+
expect(warnings).toHaveLength(0);
|
|
85
|
+
});
|
|
86
|
+
test('should not flag transforms with matrix functions', async () => {
|
|
87
|
+
const warnings = await lint(`
|
|
88
|
+
.element {
|
|
89
|
+
transform: matrix(1, 0, 0, 1, 10, 20);
|
|
90
|
+
}
|
|
91
|
+
`);
|
|
92
|
+
expect(warnings).toHaveLength(0);
|
|
93
|
+
});
|
|
94
|
+
test('should not flag transforms with skew functions', async () => {
|
|
95
|
+
const warnings = await lint(`
|
|
96
|
+
.element {
|
|
97
|
+
transform: skew(20deg, 10deg);
|
|
98
|
+
}
|
|
99
|
+
`);
|
|
100
|
+
expect(warnings).toHaveLength(0);
|
|
101
|
+
});
|
|
102
|
+
test('should not flag transforms mixing replaceable and non-replaceable functions', async () => {
|
|
103
|
+
const warnings = await lint(`
|
|
104
|
+
.element {
|
|
105
|
+
transform: translate(10px, 20px) skew(20deg);
|
|
106
|
+
}
|
|
107
|
+
`);
|
|
108
|
+
expect(warnings).toHaveLength(0);
|
|
109
|
+
});
|
|
110
|
+
test('should not flag non-transform properties', async () => {
|
|
111
|
+
const warnings = await lint(`
|
|
112
|
+
.element {
|
|
113
|
+
transition: transform 0.3s ease;
|
|
114
|
+
will-change: transform;
|
|
115
|
+
}
|
|
116
|
+
`);
|
|
117
|
+
expect(warnings).toHaveLength(0);
|
|
118
|
+
});
|
|
119
|
+
test('should handle CSS variables in transform values', async () => {
|
|
120
|
+
const warnings = await lint(`
|
|
121
|
+
.element {
|
|
122
|
+
transform: translate(var(--x), var(--y));
|
|
123
|
+
}
|
|
124
|
+
`);
|
|
125
|
+
expect(warnings).toHaveLength(1);
|
|
126
|
+
expect(warnings[0]?.text).toContain('translate: var(--x), var(--y)');
|
|
127
|
+
});
|
|
128
|
+
test('should handle calc() in transform values', async () => {
|
|
129
|
+
const warnings = await lint(`
|
|
130
|
+
.element {
|
|
131
|
+
transform: translate(calc(100% - 20px), 0);
|
|
132
|
+
}
|
|
133
|
+
`);
|
|
134
|
+
expect(warnings).toHaveLength(1);
|
|
135
|
+
expect(warnings[0]?.text).toContain('translate: calc(100% - 20px), 0');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import postcssValueParser from 'postcss-value-parser';
|
|
2
|
+
import stylelint from 'stylelint';
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import validateOptions from 'stylelint/lib/utils/validateOptions.mjs';
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
import { isString, isPlainObject } from 'stylelint/lib/utils/validateTypes.mjs';
|
|
7
|
+
import { createRule } from '../../utils/create-rule.js';
|
|
8
|
+
// Properties that have logical equivalents and can use shorthand syntax
|
|
9
|
+
const SHORTHAND_PROPERTIES_WITH_LOGICAL = [
|
|
10
|
+
'padding',
|
|
11
|
+
'margin',
|
|
12
|
+
'border-width',
|
|
13
|
+
'border-style',
|
|
14
|
+
'border-color',
|
|
15
|
+
'scroll-padding',
|
|
16
|
+
'scroll-margin',
|
|
17
|
+
'border-radius',
|
|
18
|
+
];
|
|
19
|
+
// Mapping from physical shorthand to logical equivalents
|
|
20
|
+
const LOGICAL_PROPERTY_MAP = {
|
|
21
|
+
padding: ['padding-block', 'padding-inline'],
|
|
22
|
+
margin: ['margin-block', 'margin-inline'],
|
|
23
|
+
'border-width': ['border-block-width', 'border-inline-width'],
|
|
24
|
+
'border-style': ['border-block-style', 'border-inline-style'],
|
|
25
|
+
'border-color': ['border-block-color', 'border-inline-color'],
|
|
26
|
+
'scroll-padding': ['scroll-padding-block', 'scroll-padding-inline'],
|
|
27
|
+
'scroll-margin': ['scroll-margin-block', 'scroll-margin-inline'],
|
|
28
|
+
'border-radius': [
|
|
29
|
+
'border-start-start-radius',
|
|
30
|
+
'border-start-end-radius',
|
|
31
|
+
'border-end-start-radius',
|
|
32
|
+
'border-end-end-radius',
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @param value
|
|
38
|
+
*/
|
|
39
|
+
function hasMultipleValues(value) {
|
|
40
|
+
const parsed = postcssValueParser(value);
|
|
41
|
+
const values = parsed.nodes.filter((node) => node.type === 'word' || node.type === 'function');
|
|
42
|
+
return values.length > 1;
|
|
43
|
+
}
|
|
44
|
+
export default createRule({
|
|
45
|
+
name: 'shorthand-property-use-logical',
|
|
46
|
+
rejected: (property, logicalProperties) => `Unexpected shorthand property "${property}" with multiple values. Consider using logical properties: ${logicalProperties}`,
|
|
47
|
+
rule: (ruleName, messages) => (primary) => {
|
|
48
|
+
return (root, result) => {
|
|
49
|
+
const validOptions = validateOptions(result, ruleName, {
|
|
50
|
+
actual: primary,
|
|
51
|
+
possible: [
|
|
52
|
+
true,
|
|
53
|
+
false,
|
|
54
|
+
(value) => {
|
|
55
|
+
if (!isPlainObject(value))
|
|
56
|
+
return false;
|
|
57
|
+
const obj = value;
|
|
58
|
+
return (!('properties' in obj) ||
|
|
59
|
+
(Array.isArray(obj.properties) && obj.properties.every(isString)));
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
if (!validOptions || primary === false) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const enabledProperties = typeof primary === 'object' && primary.properties
|
|
67
|
+
? primary.properties
|
|
68
|
+
: [...SHORTHAND_PROPERTIES_WITH_LOGICAL];
|
|
69
|
+
root.walkDecls((decl) => {
|
|
70
|
+
// Only check properties that are in our enabled list
|
|
71
|
+
if (!enabledProperties.includes(decl.prop)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Check if the property has multiple values
|
|
75
|
+
if (!hasMultipleValues(decl.value)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Get logical property suggestions
|
|
79
|
+
const logicalProperties = LOGICAL_PROPERTY_MAP[decl.prop];
|
|
80
|
+
if (!logicalProperties) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
stylelint.utils.report({
|
|
84
|
+
result,
|
|
85
|
+
ruleName,
|
|
86
|
+
message: messages.rejected(decl.prop, logicalProperties.join(', ')),
|
|
87
|
+
node: decl,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import stylelint from 'stylelint';
|
|
2
|
+
import { describe, test, expect } from 'vitest';
|
|
3
|
+
import rule from './index.js';
|
|
4
|
+
const { lint } = stylelint;
|
|
5
|
+
const config = (settings = true) => ({
|
|
6
|
+
plugins: [rule],
|
|
7
|
+
rules: {
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
[rule.ruleName]: settings,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
describe('shorthand-property-use-logical', () => {
|
|
13
|
+
describe('padding', () => {
|
|
14
|
+
test('single value - should not warn', async () => {
|
|
15
|
+
const {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
18
|
+
code: '* { padding: 2rem }',
|
|
19
|
+
config: config(),
|
|
20
|
+
});
|
|
21
|
+
expect(parseErrors).toHaveLength(0);
|
|
22
|
+
expect(warnings).toHaveLength(0);
|
|
23
|
+
});
|
|
24
|
+
test('two values - should warn', async () => {
|
|
25
|
+
const {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
28
|
+
code: '* { padding: 2rem 1rem }',
|
|
29
|
+
config: config(),
|
|
30
|
+
});
|
|
31
|
+
expect(parseErrors).toHaveLength(0);
|
|
32
|
+
expect(warnings).toStrictEqual([
|
|
33
|
+
{
|
|
34
|
+
rule: '@d-zero/shorthand-property-use-logical',
|
|
35
|
+
severity: 'error',
|
|
36
|
+
line: 1,
|
|
37
|
+
endLine: 1,
|
|
38
|
+
column: 5,
|
|
39
|
+
endColumn: 23,
|
|
40
|
+
text: 'Unexpected shorthand property "padding" with multiple values. Consider using logical properties: padding-block, padding-inline (@d-zero/shorthand-property-use-logical)',
|
|
41
|
+
url: undefined,
|
|
42
|
+
fix: undefined,
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
});
|
|
46
|
+
test('three values - should warn', async () => {
|
|
47
|
+
const {
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
50
|
+
code: '* { padding: 2rem 0 0 }',
|
|
51
|
+
config: config(),
|
|
52
|
+
});
|
|
53
|
+
expect(parseErrors).toHaveLength(0);
|
|
54
|
+
expect(warnings).toHaveLength(1);
|
|
55
|
+
expect(warnings[0].text).toContain('Unexpected shorthand property "padding"');
|
|
56
|
+
});
|
|
57
|
+
test('four values - should warn', async () => {
|
|
58
|
+
const {
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
61
|
+
code: '* { padding: 1rem 2rem 3rem 4rem }',
|
|
62
|
+
config: config(),
|
|
63
|
+
});
|
|
64
|
+
expect(parseErrors).toHaveLength(0);
|
|
65
|
+
expect(warnings).toHaveLength(1);
|
|
66
|
+
expect(warnings[0].text).toContain('Unexpected shorthand property "padding"');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('margin', () => {
|
|
70
|
+
test('single value - should not warn', async () => {
|
|
71
|
+
const {
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
74
|
+
code: '* { margin: auto }',
|
|
75
|
+
config: config(),
|
|
76
|
+
});
|
|
77
|
+
expect(parseErrors).toHaveLength(0);
|
|
78
|
+
expect(warnings).toHaveLength(0);
|
|
79
|
+
});
|
|
80
|
+
test('two values - should warn', async () => {
|
|
81
|
+
const {
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
84
|
+
code: '* { margin: 1rem 2rem }',
|
|
85
|
+
config: config(),
|
|
86
|
+
});
|
|
87
|
+
expect(parseErrors).toHaveLength(0);
|
|
88
|
+
expect(warnings).toHaveLength(1);
|
|
89
|
+
expect(warnings[0].text).toContain('margin-block, margin-inline');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('border-width', () => {
|
|
93
|
+
test('single value - should not warn', async () => {
|
|
94
|
+
const {
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
97
|
+
code: '* { border-width: 1px }',
|
|
98
|
+
config: config(),
|
|
99
|
+
});
|
|
100
|
+
expect(parseErrors).toHaveLength(0);
|
|
101
|
+
expect(warnings).toHaveLength(0);
|
|
102
|
+
});
|
|
103
|
+
test('multiple values - should warn', async () => {
|
|
104
|
+
const {
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
107
|
+
code: '* { border-width: 1px 2px }',
|
|
108
|
+
config: config(),
|
|
109
|
+
});
|
|
110
|
+
expect(parseErrors).toHaveLength(0);
|
|
111
|
+
expect(warnings).toHaveLength(1);
|
|
112
|
+
expect(warnings[0].text).toContain('border-block-width, border-inline-width');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
describe('limited properties configuration', () => {
|
|
116
|
+
test('only check specified properties', async () => {
|
|
117
|
+
const {
|
|
118
|
+
// @ts-ignore
|
|
119
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
120
|
+
code: '* { padding: 1rem 2rem; margin: 1rem 2rem; }',
|
|
121
|
+
config: config({ properties: ['padding'] }),
|
|
122
|
+
});
|
|
123
|
+
expect(parseErrors).toHaveLength(0);
|
|
124
|
+
expect(warnings).toHaveLength(1);
|
|
125
|
+
expect(warnings[0].text).toContain('padding');
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe('unsupported properties', () => {
|
|
129
|
+
test('should not check properties not in the list', async () => {
|
|
130
|
+
const {
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
133
|
+
code: '* { background: url(a.png) no-repeat }',
|
|
134
|
+
config: config(),
|
|
135
|
+
});
|
|
136
|
+
expect(parseErrors).toHaveLength(0);
|
|
137
|
+
expect(warnings).toHaveLength(0);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('complex values', () => {
|
|
141
|
+
test('calc() function with multiple values', async () => {
|
|
142
|
+
const {
|
|
143
|
+
// @ts-ignore
|
|
144
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
145
|
+
code: '* { padding: calc(1rem + 2px) 1rem }',
|
|
146
|
+
config: config(),
|
|
147
|
+
});
|
|
148
|
+
expect(parseErrors).toHaveLength(0);
|
|
149
|
+
expect(warnings).toHaveLength(1);
|
|
150
|
+
});
|
|
151
|
+
test('var() function with multiple values', async () => {
|
|
152
|
+
const {
|
|
153
|
+
// @ts-ignore
|
|
154
|
+
results: [{ warnings, parseErrors }], } = await lint({
|
|
155
|
+
code: '* { margin: var(--spacing) 2rem }',
|
|
156
|
+
config: config(),
|
|
157
|
+
});
|
|
158
|
+
expect(parseErrors).toHaveLength(0);
|
|
159
|
+
expect(warnings).toHaveLength(1);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d-zero/stylelint-rules",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.69",
|
|
4
4
|
"description": "Rules of Stylelint for D-ZERO",
|
|
5
5
|
"repository": "https://github.com/d-zero-dev/linters.git",
|
|
6
6
|
"author": "D-ZERO Co., Ltd.",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"build": "tsc"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@d-zero/csstree-scss-syntax": "5.0.0-alpha.
|
|
25
|
+
"@d-zero/csstree-scss-syntax": "5.0.0-alpha.69",
|
|
26
26
|
"css-tree": "3.1.0",
|
|
27
27
|
"postcss-selector-parser": "7.1.0",
|
|
28
28
|
"postcss-value-parser": "4.2.0",
|
|
29
|
-
"stylelint": "16.21.
|
|
29
|
+
"stylelint": "16.21.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"postcss": "8.5.6"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "8527568567fd3b4030906fbdebe06720e606f7b8"
|
|
35
35
|
}
|