Skip to content

Commit a11dfbc

Browse files
committed
wip standard config
1 parent 92b42b8 commit a11dfbc

File tree

11 files changed

+410
-113
lines changed

11 files changed

+410
-113
lines changed

code-pushup.config.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import 'dotenv/config';
22
import { z } from 'zod';
3+
import {
4+
coverageCoreConfigNx,
5+
eslintCoreConfigNx,
6+
jsPackagesCoreConfig,
7+
lighthouseCoreConfig,
8+
} from './code-pushup.preset.js';
39
import type { CoreConfig } from './packages/models/src/index.js';
4-
import { getAudits, getCategoryRefs } from './packages/plugin-stylelint/src';
510
import { stylelintPlugin } from './packages/plugin-stylelint/src/lib/stylelint-plugin';
611
import { getCategoryRefsFromGroups } from './packages/plugin-stylelint/src/lib/utils';
712
import { mergeConfigs } from './packages/utils/src/index.js';
@@ -31,12 +36,12 @@ const stylelintrc =
3136
'packages/plugin-stylelint/mocks/fixtures/basic/.stylelintrc.json';
3237
export default mergeConfigs(
3338
config,
34-
/*await coverageCoreConfigNx(),
39+
await coverageCoreConfigNx(),
3540
await jsPackagesCoreConfig(),
3641
await lighthouseCoreConfig(
3742
'https://github.com/code-pushup/cli?tab=readme-ov-file#code-pushup-cli/',
3843
),
39-
await eslintCoreConfigNx(),*/
44+
await eslintCoreConfigNx(),
4045
{
4146
plugins: [
4247
await stylelintPlugin([
@@ -48,11 +53,33 @@ export default mergeConfigs(
4853
],
4954
categories: [
5055
{
51-
slug: 'style',
56+
slug: 'code-style',
5257
title: 'Code style',
5358
description:
5459
'Lint rules that promote **good practices** and consistency in your code.',
55-
refs: await getCategoryRefsFromGroups({ stylelintrc }),
60+
refs: (
61+
await getCategoryRefsFromGroups([
62+
{
63+
stylelintrc,
64+
patterns:
65+
'packages/plugin-stylelint/mocks/fixtures/basic/**/*.css', // Adjust the path to your CSS files
66+
},
67+
])
68+
).filter(ref => ref.slug === 'suggestions'),
69+
},
70+
{
71+
slug: 'bug-prevention',
72+
title: 'Bug Prevention',
73+
description: 'Lint rules that help **prevent bugs** in your code.',
74+
refs: (
75+
await getCategoryRefsFromGroups([
76+
{
77+
stylelintrc,
78+
patterns:
79+
'packages/plugin-stylelint/mocks/fixtures/basic/**/*.css', // Adjust the path to your CSS files
80+
},
81+
])
82+
).filter(ref => ref.slug === 'problems'),
5683
},
5784
],
5885
},

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"semver": "^7.6.3",
4242
"simple-git": "^3.26.0",
4343
"stylelint": "^16.12.0",
44+
"stylelint-config-recommended": "^14.0.1",
4445
"stylelint-config-standard": "^36.0.1",
4546
"tslib": "^2.6.2",
4647
"vscode-material-icons": "^0.1.1",
Lines changed: 160 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,165 @@
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'],
39
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' }],
4817
'declaration-block-no-duplicate-properties': [
4918
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' }],
59162
},
60163
};
164+
165+
export default stylelintConfig;

0 commit comments

Comments
 (0)