|
1 | | -export default { |
2 | | - extends: 'stylelint-config-standard', |
| 1 | +/** |
| 2 | + * Standard Stylelint configuration that extends the stylelint-config-standard. |
| 3 | + * "Avoid errors" rules are set to "error" severity. |
| 4 | + * "Enforce conventions" rules are set to "warning" severity. |
| 5 | + */ |
| 6 | + |
| 7 | +const stylelintConfig = { |
| 8 | + extends: ['stylelint-config-standard'], |
3 | 9 | rules: { |
4 | | - // Style Rules - Warnings |
5 | | - |
6 | | - // Formatting |
7 | | - 'indentation': [2, { severity: 'warning' }], // Enforce consistent indentation |
8 | | - 'max-line-length': [80, { severity: 'warning' }], // Limit line length |
9 | | - 'max-empty-lines': [1, { severity: 'warning' }], // Limit empty lines |
10 | | - 'no-eol-whitespace': [true, { severity: 'warning' }], // No end-of-line whitespace |
11 | | - 'declaration-block-no-redundant-longhand-properties': [true, { severity: 'warning' }], // Combine longhand properties |
12 | | - |
13 | | - // Spacing |
14 | | - 'declaration-block-semicolon-space-after': ['always', { severity: 'warning' }], // Space after semicolons |
15 | | - 'declaration-block-semicolon-space-before': ['never', { severity: 'warning' }], // No space before semicolons |
16 | | - 'block-closing-brace-space-before': ['always-single-line', { severity: 'warning' }], // Space before closing braces |
17 | | - |
18 | | - // Quotes and Strings |
19 | | - 'string-quotes': ['double', { severity: 'warning' }], // Enforce double quotes |
20 | | - 'font-family-name-quotes': ['always-where-recommended', { severity: 'warning' }], // Font family quotes |
21 | | - 'function-url-quotes': ['always', { severity: 'warning' }], // Quotes around URLs |
22 | | - |
23 | | - // Colors |
24 | | - 'color-hex-case': ['lower', { severity: 'warning' }], // Lowercase hex codes |
25 | | - 'color-hex-length': ['short', { severity: 'warning' }], // Short hex codes |
26 | | - 'color-function-notation': ['modern', { severity: 'warning' }], // Modern color functions |
27 | | - 'lightness-notation': ['percentage', { severity: 'warning' }], // Percentage lightness |
28 | | - |
29 | | - // Lists |
30 | | - 'value-list-comma-space-after': ['always-single-line', { severity: 'warning' }], // Space after commas in lists |
31 | | - 'selector-list-comma-newline-after': ['always', { severity: 'warning' }], // Newline after selector commas |
32 | | - |
33 | | - // Miscellaneous |
34 | | - 'comment-whitespace-inside': ['always', { severity: 'warning' }], // Space inside comments |
35 | | - 'keyframes-name-pattern': [ |
36 | | - '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', |
37 | | - { severity: 'warning', message: 'Keyframe names must be kebab-case.' }, |
38 | | - ], // Keyframe names must be kebab-case |
39 | | - 'alpha-value-notation': ['percentage', { severity: 'warning' }], // Use percentages for alpha values |
40 | | - |
41 | | - // Bug Prevention Rules - Errors |
42 | | - |
43 | | - 'annotation-no-unknown': true, // Prevent unknown annotations |
44 | | - 'at-rule-no-unknown': true, // Disallow unknown at-rules |
45 | | - 'block-no-empty': true, // Disallow empty blocks |
46 | | - 'color-no-invalid-hex': true, // Disallow invalid hex colors |
47 | | - 'custom-property-no-missing-var-function': true, // Disallow missing var functions |
| 10 | + // = Avoid errors - set as errors |
| 11 | + |
| 12 | + // == Descending |
| 13 | + 'no-descending-specificity': [true, { severity: 'error' }], |
| 14 | + |
| 15 | + // == Duplicate |
| 16 | + 'declaration-block-no-duplicate-custom-properties': [true, { severity: 'error' }], |
48 | 17 | 'declaration-block-no-duplicate-properties': [ |
49 | 18 | true, |
50 | | - { ignore: ['consecutive-duplicates-with-different-syntaxes'] }, |
51 | | - ], // Prevent duplicate properties |
52 | | - 'function-no-unknown': true, // Disallow unknown functions |
53 | | - 'keyframe-block-no-duplicate-selectors': true, // Prevent duplicate keyframe selectors |
54 | | - 'media-feature-name-no-unknown': true, // Disallow unknown media features |
55 | | - 'no-duplicate-selectors': true, // Disallow duplicate selectors |
56 | | - 'property-no-unknown': true, // Disallow unknown properties |
57 | | - 'selector-pseudo-class-no-unknown': true, // Disallow unknown pseudo-classes |
58 | | - 'unit-no-unknown': true, // Disallow unknown units |
| 19 | + { severity: 'error', ignore: ['consecutive-duplicates-with-different-syntaxes'] }, |
| 20 | + ], |
| 21 | + 'font-family-no-duplicate-names': [true, { severity: 'error' }], |
| 22 | + 'keyframe-block-no-duplicate-selectors': [true, { severity: 'error' }], |
| 23 | + 'no-duplicate-at-import-rules': [true, { severity: 'error' }], |
| 24 | + 'no-duplicate-selectors': [true, { severity: 'error' }], |
| 25 | + |
| 26 | + // == Empty |
| 27 | + 'block-no-empty': [true, { severity: 'error' }], |
| 28 | + 'comment-no-empty': [true, { severity: 'error' }], |
| 29 | + 'no-empty-source': [true, { severity: 'error' }], |
| 30 | + |
| 31 | + // == Invalid |
| 32 | + 'color-no-invalid-hex': [true, { severity: 'error' }], |
| 33 | + 'function-calc-no-unspaced-operator': [true, { severity: 'error' }], |
| 34 | + 'keyframe-declaration-no-important': [true, { severity: 'error' }], |
| 35 | + 'media-query-no-invalid': [true, { severity: 'error' }], |
| 36 | + 'named-grid-areas-no-invalid': [true, { severity: 'error' }], |
| 37 | + 'no-invalid-double-slash-comments': [true, { severity: 'error' }], |
| 38 | + 'no-invalid-position-at-import-rule': [true, { severity: 'error' }], |
| 39 | + 'string-no-newline': [true, { severity: 'error' }], |
| 40 | + |
| 41 | + // == Irregular |
| 42 | + 'no-irregular-whitespace': [true, { severity: 'error' }], |
| 43 | + |
| 44 | + // == Missing |
| 45 | + 'custom-property-no-missing-var-function': [true, { severity: 'error' }], |
| 46 | + 'font-family-no-missing-generic-family-keyword': [true, { severity: 'error' }], |
| 47 | + |
| 48 | + // == Non-standard |
| 49 | + 'function-linear-gradient-no-nonstandard-direction': [true, { severity: 'error' }], |
| 50 | + |
| 51 | + // == Overrides |
| 52 | + 'declaration-block-no-shorthand-property-overrides': [true, { severity: 'error' }], |
| 53 | + |
| 54 | + // == Unmatchable |
| 55 | + 'selector-anb-no-unmatchable': [true, { severity: 'error' }], |
| 56 | + |
| 57 | + // == Unknown |
| 58 | + 'annotation-no-unknown': [true, { severity: 'error' }], |
| 59 | + 'at-rule-no-unknown': [true, { severity: 'error' }], |
| 60 | + 'function-no-unknown': [true, { severity: 'error' }], |
| 61 | + 'media-feature-name-no-unknown': [true, { severity: 'error' }], |
| 62 | + 'property-no-unknown': [true, { severity: 'error' }], |
| 63 | + 'selector-pseudo-class-no-unknown': [true, { severity: 'error' }], |
| 64 | + 'selector-type-no-unknown': [true, { severity: 'error' }], |
| 65 | + 'unit-no-unknown': [true, { severity: 'error' }], |
| 66 | + |
| 67 | + // == Maintainability Rules |
| 68 | + |
| 69 | + // Prevent overly specific selectors |
| 70 | + // Example: Good: `.class1 .class2`, Bad: `#id.class1 .class2` |
| 71 | + "selector-max-specificity": ["0,2,0", { severity: "warning" }], |
| 72 | + // Enforces a maximum specificity of 2 classes, no IDs, and no inline styles. |
| 73 | + // Encourages maintainable selectors. |
| 74 | + |
| 75 | + // Disallow the use of ID selectors |
| 76 | + // Example: Good: `.button`, Bad: `#button` |
| 77 | + "selector-max-id": [0, { severity: "warning" }], |
| 78 | + // Prevents the use of IDs in selectors, as they are too specific and hard to override. |
| 79 | + |
| 80 | + // Limit the number of class selectors in a rule |
| 81 | + // Example: Good: `.btn.primary`, Bad: `.btn.primary.large.rounded` |
| 82 | + "selector-max-class": [3, { severity: "off" }], |
| 83 | + // Can help avoid overly complex class chains, but may be unnecessary if specificity is already managed. |
| 84 | + |
| 85 | + // Limit the number of pseudo-classes in a selector |
| 86 | + // Example: Good: `.list-item:hover`, Bad: `.list-item:nth-child(2):hover:active` |
| 87 | + "selector-max-pseudo-class": [3, { severity: "warning" }], |
| 88 | + // Allows up to 3 pseudo-classes in a single selector to balance flexibility and simplicity. |
| 89 | + |
| 90 | + // Restrict the number of type selectors (e.g., `div`, `span`) |
| 91 | + // Example: Good: `.header`, Bad: `div.header` |
| 92 | + "selector-max-type": [1, { severity: "warning" }], |
| 93 | + // Promotes the use of semantic classes over type selectors for better reusability and maintainability. |
| 94 | + |
| 95 | + // Optional: Additional rules for project-specific preferences |
| 96 | + // Uncomment the following if relevant to your project: |
| 97 | + /* |
| 98 | + // Example: Limit the depth of combinators |
| 99 | + // Good: `.parent > .child`, Bad: `.parent > .child > .grandchild` |
| 100 | + "selector-max-combinators": [2, { severity: "warning" }], |
| 101 | +
|
| 102 | + // Example: Restrict the number of universal selectors in a rule |
| 103 | + // Good: `* { margin: 0; }`, Bad: `.wrapper * .content { padding: 0; }` |
| 104 | + "selector-max-universal": [1, { severity: "warning" }], |
| 105 | + */ |
| 106 | + |
| 107 | + // = Enforce conventions - set as warnings |
| 108 | + |
| 109 | + // == Allowed, disallowed & required |
| 110 | + 'at-rule-no-vendor-prefix': [true, { severity: 'warning' }], |
| 111 | + 'length-zero-no-unit': [true, { severity: 'warning' }], |
| 112 | + 'media-feature-name-no-vendor-prefix': [true, { severity: 'warning' }], |
| 113 | + 'property-no-vendor-prefix': [true, { severity: 'warning' }], |
| 114 | + 'value-no-vendor-prefix': [true, { severity: 'warning' }], |
| 115 | + |
| 116 | + // == Case |
| 117 | + 'function-name-case': ['lower', { severity: 'warning' }], |
| 118 | + 'selector-type-case': ['lower', { severity: 'warning' }], |
| 119 | + 'value-keyword-case': ['lower', { severity: 'warning' }], |
| 120 | + |
| 121 | + // == Empty lines |
| 122 | + 'at-rule-empty-line-before': ['always', { severity: 'warning' }], |
| 123 | + 'comment-empty-line-before': ['always', { severity: 'warning' }], |
| 124 | + 'custom-property-empty-line-before': ['always', { severity: 'warning' }], |
| 125 | + 'declaration-empty-line-before': ['always', { severity: 'warning' }], |
| 126 | + 'rule-empty-line-before': ['always', { severity: 'warning' }], |
| 127 | + |
| 128 | + // == Max & min |
| 129 | + 'declaration-block-single-line-max-declarations': [1, { severity: 'warning' }], |
| 130 | + 'number-max-precision': [4, { severity: 'warning' }], |
| 131 | + |
| 132 | + // == Notation |
| 133 | + 'alpha-value-notation': ['percentage', { severity: 'warning' }], |
| 134 | + 'color-function-notation': ['modern', { severity: 'warning' }], |
| 135 | + 'color-hex-length': ['short', { severity: 'warning' }], |
| 136 | + 'hue-degree-notation': ['angle', { severity: 'warning' }], |
| 137 | + 'import-notation': ['string', { severity: 'warning' }], |
| 138 | + 'keyframe-selector-notation': ['percentage', { severity: 'warning' }], |
| 139 | + 'lightness-notation': ['percentage', { severity: 'warning' }], |
| 140 | + 'media-feature-range-notation': ['context', { severity: 'warning' }], |
| 141 | + 'selector-not-notation': ['complex', { severity: 'warning' }], |
| 142 | + 'selector-pseudo-element-colon-notation': ['double', { severity: 'warning' }], |
| 143 | + |
| 144 | + // == Pattern |
| 145 | + 'custom-media-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', { severity: 'warning' }], |
| 146 | + 'custom-property-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', { severity: 'warning' }], |
| 147 | + 'keyframes-name-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', { severity: 'warning' }], |
| 148 | + 'selector-class-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', { severity: 'warning' }], |
| 149 | + 'selector-id-pattern': ['^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', { severity: 'warning' }], |
| 150 | + |
| 151 | + // == Quotes |
| 152 | + 'font-family-name-quotes': ['always-where-recommended', { severity: 'warning' }], |
| 153 | + 'function-url-quotes': ['always', { severity: 'warning' }], |
| 154 | + 'selector-attribute-quotes': ['always', { severity: 'warning' }], |
| 155 | + |
| 156 | + // == Redundant |
| 157 | + 'declaration-block-no-redundant-longhand-properties': [true, { severity: 'warning' }], |
| 158 | + 'shorthand-property-no-redundant-values': [true, { severity: 'warning' }], |
| 159 | + |
| 160 | + // == Whitespace inside |
| 161 | + 'comment-whitespace-inside': ['always', { severity: 'warning' }], |
59 | 162 | }, |
60 | 163 | }; |
| 164 | + |
| 165 | +export default stylelintConfig; |
0 commit comments