Skip to content

Commit 3e40393

Browse files
committed
chore: extract stylelint configs
1 parent b901b94 commit 3e40393

6 files changed

Lines changed: 137 additions & 51 deletions

File tree

stylelint.config.mts

Lines changed: 10 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,10 @@
1-
import type { Config } from 'stylelint';
2-
3-
const config: Config = {
4-
plugins: ['stylelint-prettier'],
5-
extends: [
6-
'stylelint-config-standard',
7-
'@stylistic/stylelint-config',
8-
'stylelint-prettier/recommended',
9-
],
10-
rules: {
11-
// tailwind rules
12-
'import-notation': null,
13-
'at-rule-no-unknown': [
14-
true,
15-
{
16-
ignoreAtRules: [
17-
'theme',
18-
'source',
19-
'utility',
20-
'variant',
21-
'custom-variant',
22-
'plugin',
23-
],
24-
},
25-
],
26-
'function-no-unknown': [
27-
true,
28-
{
29-
ignoreFunctions: ['theme'],
30-
},
31-
],
32-
33-
// rules conflict with prettier
34-
'@stylistic/declaration-colon-newline-after': null,
35-
'@stylistic/declaration-colon-space-after': null,
36-
'@stylistic/value-list-comma-newline-after': null,
37-
38-
'custom-property-pattern': null,
39-
},
40-
ignoreFiles: [
41-
'**/.idea/**',
42-
'**/node_modules/**',
43-
'.next/**',
44-
'out/**',
45-
'coverage/**',
46-
'.swc/**',
47-
'.rollup.cache/**',
48-
],
49-
};
50-
51-
export default config;
1+
import { defineStylelintConfig } from './tools/stylelint/defineStylelintConfig';
2+
import { getBaseConfig } from './tools/stylelint/getBaseConfig';
3+
import { getStylisticConfig } from './tools/stylelint/getStylisticConfig';
4+
import { getTailwindCssConfig } from './tools/stylelint/getTailwindCssConfig';
5+
6+
export default defineStylelintConfig([
7+
getBaseConfig(),
8+
getStylisticConfig(),
9+
getTailwindCssConfig(),
10+
]);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { Config, Plugin } from 'stylelint';
2+
import type { PartialStyleLintConfig } from './types';
3+
4+
const formatValue = <T>(value: T | T[] | undefined): T[] => {
5+
if (!value) {
6+
return [];
7+
}
8+
if (Array.isArray(value)) {
9+
return value;
10+
}
11+
return [value];
12+
};
13+
14+
const dedupeAdd = <T>(array: T[], values: T[], set: Set<T>) => {
15+
for (const item of values) {
16+
if (!set.has(item)) {
17+
set.add(item);
18+
array.push(item);
19+
}
20+
}
21+
};
22+
23+
export const defineStylelintConfig = (
24+
configs: PartialStyleLintConfig[],
25+
): Config => {
26+
const finalPlugins: (Plugin | string)[] = [];
27+
const finalExtends: string[] = [];
28+
const finalIgnoreFiles: string[] = [];
29+
const finalRules: Config['rules'] = {};
30+
31+
// use set to deduplicate
32+
const pluginSet = new Set<Plugin | string>();
33+
const extendsSet = new Set<string>();
34+
const ignoreFilesSet = new Set<string>();
35+
36+
for (const config of configs) {
37+
const plugins = formatValue(config.plugins);
38+
dedupeAdd(finalPlugins, plugins, pluginSet);
39+
40+
const extendsValue = formatValue(config.extends);
41+
dedupeAdd(finalExtends, extendsValue, extendsSet);
42+
43+
const ignoreFiles = formatValue(config.ignoreFiles);
44+
dedupeAdd(finalIgnoreFiles, ignoreFiles, ignoreFilesSet);
45+
46+
const rules = config.rules;
47+
if (rules) {
48+
Object.assign(finalRules, rules);
49+
}
50+
}
51+
52+
return {
53+
plugins: finalPlugins,
54+
extends: finalExtends,
55+
rules: finalRules,
56+
ignoreFiles: finalIgnoreFiles,
57+
};
58+
};

tools/stylelint/getBaseConfig.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { PartialStyleLintConfig } from './types';
2+
3+
export const getBaseConfig = (): PartialStyleLintConfig => {
4+
return {
5+
extends: ['stylelint-config-standard'],
6+
ignoreFiles: [
7+
'**/.idea/**',
8+
'**/node_modules/**',
9+
'.next/**',
10+
'out/**',
11+
'coverage/**',
12+
'.swc/**',
13+
'.rollup.cache/**',
14+
],
15+
};
16+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { PartialStyleLintConfig } from './types';
2+
3+
export const getStylisticConfig = (): PartialStyleLintConfig => {
4+
return {
5+
plugins: ['stylelint-prettier'],
6+
extends: ['@stylistic/stylelint-config', 'stylelint-prettier/recommended'],
7+
rules: {
8+
// rules conflict with prettier
9+
'@stylistic/declaration-colon-newline-after': null,
10+
'@stylistic/declaration-colon-space-after': null,
11+
'@stylistic/value-list-comma-newline-after': null,
12+
},
13+
};
14+
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { PartialStyleLintConfig } from './types';
2+
3+
export const getTailwindCssConfig = (): PartialStyleLintConfig => {
4+
return {
5+
// tailwind
6+
rules: {
7+
// tailwind rules
8+
'import-notation': null,
9+
'at-rule-no-unknown': [
10+
true,
11+
{
12+
ignoreAtRules: [
13+
'theme',
14+
'source',
15+
'utility',
16+
'variant',
17+
'custom-variant',
18+
'plugin',
19+
],
20+
},
21+
],
22+
'function-no-unknown': [
23+
true,
24+
{
25+
ignoreFunctions: ['theme'],
26+
},
27+
],
28+
29+
'custom-property-pattern': null,
30+
},
31+
};
32+
};

tools/stylelint/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { Config } from 'stylelint';
2+
3+
export type PartialStyleLintConfig = Pick<
4+
Config,
5+
// TODO: for now, only these fields are supported, type-guard is applied here to avoid unexpected usage.
6+
'plugins' | 'extends' | 'ignoreFiles' | 'rules'
7+
>;

0 commit comments

Comments
 (0)