@alexlit/lint-kit 215.0.0 → 216.1.0

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.
Files changed (73) hide show
  1. package/eslint.config.js +8 -4
  2. package/package.json +1 -1
  3. package/packages/config-eslint/README.md +57 -32
  4. package/packages/config-eslint/base.js +4 -1
  5. package/packages/config-eslint/index.d.ts +34 -32
  6. package/packages/config-eslint/index.js +5 -2
  7. package/packages/config-eslint/package.json +4 -4
  8. package/packages/config-eslint/plugins/de-morgan.js +4 -2
  9. package/packages/config-eslint/plugins/import-x.js +5 -1
  10. package/packages/config-eslint/plugins/javascript.js +5 -1
  11. package/packages/config-eslint/plugins/jsdoc.js +5 -1
  12. package/packages/config-eslint/plugins/json.js +5 -1
  13. package/packages/config-eslint/plugins/perfectionist.js +5 -1
  14. package/packages/config-eslint/plugins/pinia.js +5 -1
  15. package/packages/config-eslint/plugins/prettier.js +10 -2
  16. package/packages/config-eslint/plugins/regexp.js +5 -1
  17. package/packages/config-eslint/plugins/sonar.js +5 -1
  18. package/packages/config-eslint/plugins/stylistic.js +5 -1
  19. package/packages/config-eslint/plugins/tailwindcss.js +20 -17
  20. package/packages/config-eslint/plugins/tanstack-query.js +5 -1
  21. package/packages/config-eslint/plugins/typescript-type-checked.js +5 -1
  22. package/packages/config-eslint/plugins/typescript.js +5 -1
  23. package/packages/config-eslint/plugins/unicorn.js +5 -1
  24. package/packages/config-eslint/plugins/unocss.js +5 -1
  25. package/packages/config-eslint/plugins/vitest.js +5 -1
  26. package/packages/config-eslint/plugins/vue-accessibility.js +5 -1
  27. package/packages/config-eslint/plugins/vue-i18n.js +10 -5
  28. package/packages/config-eslint/plugins/vue.js +5 -1
  29. package/packages/config-eslint/plugins/zod.js +5 -1
  30. package/packages/config-hooks/README.md +2 -2
  31. package/packages/config-htmllint/README.md +2 -2
  32. package/packages/config-markdownlint/README.md +2 -2
  33. package/packages/config-npmlint/README.md +2 -2
  34. package/packages/config-prettier/README.md +68 -16
  35. package/packages/config-prettier/index.d.ts +9 -1
  36. package/packages/config-prettier/index.js +20 -28
  37. package/packages/config-prettier/package.json +3 -2
  38. package/packages/config-prettier/plugins/jsdoc.js +14 -8
  39. package/packages/config-prettier/plugins/mdc.js +12 -6
  40. package/packages/config-prettier/plugins/packagejson.js +9 -5
  41. package/packages/config-prettier/plugins/php.js +9 -5
  42. package/packages/config-prettier/plugins/pug.js +15 -9
  43. package/packages/config-prettier/plugins/ruby.js +12 -6
  44. package/packages/config-prettier/plugins/sh.js +9 -5
  45. package/packages/config-prettier/plugins/solidity.js +9 -5
  46. package/packages/config-prettier/plugins/sort-json.js +12 -6
  47. package/packages/config-prettier/plugins/sql.js +9 -5
  48. package/packages/config-prettier/plugins/tailwindcss.js +18 -12
  49. package/packages/config-prettier/plugins/xml.js +12 -6
  50. package/packages/config-prettier/utils/merge-configs.js +18 -0
  51. package/packages/config-stylelint/README.md +80 -29
  52. package/packages/config-stylelint/index.d.ts +4 -0
  53. package/packages/config-stylelint/index.js +4 -12
  54. package/packages/config-stylelint/package.json +3 -2
  55. package/packages/config-stylelint/plugins/a11y.js +15 -21
  56. package/packages/config-stylelint/plugins/bem.js +14 -13
  57. package/packages/config-stylelint/plugins/color-format.js +10 -8
  58. package/packages/config-stylelint/plugins/declaration-block-no-ignored-properties.js +10 -12
  59. package/packages/config-stylelint/plugins/gamut.js +9 -9
  60. package/packages/config-stylelint/plugins/high-performance-animation.js +15 -15
  61. package/packages/config-stylelint/plugins/logical-css.js +9 -8
  62. package/packages/config-stylelint/plugins/media-use-custom-media.js +10 -9
  63. package/packages/config-stylelint/plugins/no-indistinguishable-colors.js +10 -12
  64. package/packages/config-stylelint/plugins/no-nested-media.js +9 -9
  65. package/packages/config-stylelint/plugins/no-unresolved-module.js +16 -16
  66. package/packages/config-stylelint/plugins/no-unsupported-browser-features.js +16 -16
  67. package/packages/config-stylelint/plugins/order.js +15 -17
  68. package/packages/config-stylelint/plugins/prettier.js +9 -9
  69. package/packages/config-stylelint/plugins/scss.js +14 -17
  70. package/packages/config-stylelint/plugins/selector-no-empty.js +10 -9
  71. package/packages/config-stylelint/plugins/use-nesting.js +9 -12
  72. package/packages/config-stylelint/plugins/vue.js +6 -7
  73. package/packages/config-stylelint/utils/merge-configs.js +20 -0
@@ -1,15 +1,21 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = {
4
+ overrides: [{ files: '*.html.erb', options: { parser: 'eruby-parse' } }],
5
+ plugins: ['@prettier/plugin-ruby', 'prettier-plugin-eruby'],
6
+ };
7
+
1
8
  /**
2
9
  * Форматирует Ruby и ERB файлы
3
10
  *
4
- * @param {Partial<import('prettier').Config>} [options]
11
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
12
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
13
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
14
+ * выигрывают, остальные поля заменяются
5
15
  *
6
16
  * @returns {import('prettier').Config}
7
17
  *
8
18
  * @see [plugin-ruby](https://github.com/prettier/plugin-ruby)
9
19
  * @see [prettier-plugin-eruby](https://github.com/ippachi/prettier-plugin-eruby)
10
20
  */
11
- export const ruby = (options = {}) => ({
12
- overrides: [{ files: '*.html.erb', options: { parser: 'eruby-parse' } }],
13
- plugins: ['@prettier/plugin-ruby', 'prettier-plugin-eruby'],
14
- ...options,
15
- });
21
+ export const ruby = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,13 +1,17 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = { plugins: ['prettier-plugin-sh'] };
4
+
1
5
  /**
2
6
  * Форматирует shell-скрипты
3
7
  *
4
- * @param {Partial<import('prettier').Config>} [options]
8
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
9
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
10
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
11
+ * выигрывают, остальные поля заменяются
5
12
  *
6
13
  * @returns {import('prettier').Config}
7
14
  *
8
15
  * @see [prettier-plugin-sh](https://github.com/astorije/prettier-plugin-sh)
9
16
  */
10
- export const sh = (options = {}) => ({
11
- plugins: ['prettier-plugin-sh'],
12
- ...options,
13
- });
17
+ export const sh = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,13 +1,17 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = { plugins: ['prettier-plugin-solidity'] };
4
+
1
5
  /**
2
6
  * Форматирует контракты Solidity
3
7
  *
4
- * @param {Partial<import('prettier').Config>} [options]
8
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
9
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
10
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
11
+ * выигрывают, остальные поля заменяются
5
12
  *
6
13
  * @returns {import('prettier').Config}
7
14
  *
8
15
  * @see [prettier-plugin-solidity](https://github.com/prettier-solidity/prettier-plugin-solidity)
9
16
  */
10
- export const solidity = (options = {}) => ({
11
- plugins: ['prettier-plugin-solidity'],
12
- ...options,
13
- });
17
+ export const solidity = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,14 +1,20 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = {
4
+ jsonRecursiveSort: true,
5
+ plugins: ['prettier-plugin-sort-json'],
6
+ };
7
+
1
8
  /**
2
9
  * Рекурсивно сортирует ключи JSON-объектов
3
10
  *
4
- * @param {Partial<import('prettier').Config>} [options]
11
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
12
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
13
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
14
+ * выигрывают, остальные поля заменяются
5
15
  *
6
16
  * @returns {import('prettier').Config}
7
17
  *
8
18
  * @see [prettier-plugin-sort-json](https://github.com/Gudahtt/prettier-plugin-sort-json)
9
19
  */
10
- export const sortJson = (options = {}) => ({
11
- jsonRecursiveSort: true,
12
- plugins: ['prettier-plugin-sort-json'],
13
- ...options,
14
- });
20
+ export const sortJson = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,13 +1,17 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = { plugins: ['prettier-plugin-sql'] };
4
+
1
5
  /**
2
6
  * Форматирует SQL-запросы
3
7
  *
4
- * @param {Partial<import('prettier').Config>} [options]
8
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
9
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
10
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
11
+ * выигрывают, остальные поля заменяются
5
12
  *
6
13
  * @returns {import('prettier').Config}
7
14
  *
8
15
  * @see [prettier-plugin-sql](https://github.com/un-ts/prettier/tree/master/packages/sql)
9
16
  */
10
- export const sql = (options = {}) => ({
11
- plugins: ['prettier-plugin-sql'],
12
- ...options,
13
- });
17
+ export const sql = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,13 +1,6 @@
1
- /**
2
- * Сортирует утилитарные классы Tailwind CSS по каноническому порядку
3
- *
4
- * @param {Partial<import('prettier').Config>} [options]
5
- *
6
- * @returns {import('prettier').Config}
7
- *
8
- * @see [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)
9
- */
10
- export const tailwindcss = (options = {}) => ({
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = {
11
4
  plugins: ['prettier-plugin-tailwindcss'],
12
5
  tailwindFunctions: [
13
6
  'classnames',
@@ -19,5 +12,18 @@ export const tailwindcss = (options = {}) => ({
19
12
  'tw',
20
13
  'twMerge',
21
14
  ],
22
- ...options,
23
- });
15
+ };
16
+
17
+ /**
18
+ * Сортирует утилитарные классы Tailwind CSS по каноническому порядку
19
+ *
20
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
21
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
22
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
23
+ * выигрывают, остальные поля заменяются
24
+ *
25
+ * @returns {import('prettier').Config}
26
+ *
27
+ * @see [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)
28
+ */
29
+ export const tailwindcss = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,14 +1,20 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = {
4
+ plugins: ['@prettier/plugin-xml'],
5
+ xmlWhitespaceSensitivity: 'ignore',
6
+ };
7
+
1
8
  /**
2
9
  * Форматирует XML-файлы
3
10
  *
4
- * @param {Partial<import('prettier').Config>} [options]
11
+ * @param {Partial<import('prettier').Config>} [options] - Опции, накладываемые
12
+ * поверх значений по умолчанию. Коллекции (`overrides`, `plugins`)
13
+ * дополняются, `plugins` дедуплицируются, более поздние `overrides`
14
+ * выигрывают, остальные поля заменяются
5
15
  *
6
16
  * @returns {import('prettier').Config}
7
17
  *
8
18
  * @see [plugin-xml](https://github.com/prettier/plugin-xml)
9
19
  */
10
- export const xml = (options = {}) => ({
11
- plugins: ['@prettier/plugin-xml'],
12
- xmlWhitespaceSensitivity: 'ignore',
13
- ...options,
14
- });
20
+ export const xml = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Объединяет конфигурации Prettier
3
+ *
4
+ * Коллекции `overrides` и `plugins` дополняются: пользовательские значения идут
5
+ * после дефолтных, поэтому более поздние overrides выигрывают. `plugins`
6
+ * дедуплицируются. Остальные поля заменяются значениями из последующих
7
+ * конфигураций.
8
+ *
9
+ * @param {...import('prettier').Config} configs Конфигурации в порядке
10
+ * приоритета
11
+ *
12
+ * @returns {import('prettier').Config} Объединённая конфигурация
13
+ */
14
+ export const mergeConfigs = (...configs) => ({
15
+ ...Object.assign({}, ...configs),
16
+ overrides: configs.flatMap((config) => config.overrides ?? []),
17
+ plugins: [...new Set(configs.flatMap((config) => config.plugins ?? []))],
18
+ });
@@ -1,9 +1,9 @@
1
+ # Stylelint Configuration
2
+
1
3
  [![version](https://npmx.dev/api/registry/badge/version/@alexlit/config-stylelint)](https://www.npmjs.com/package/@alexlit/config-stylelint)
2
4
  [![downloads](https://npmx.dev/api/registry/badge/downloads/@alexlit/config-stylelint)](https://npmx.dev/package/@alexlit/config-stylelint)
3
5
  [![license](https://npmx.dev/api/registry/badge/license/@alexlit/config-stylelint)](LICENSE)
4
6
 
5
- # Stylelint Configuration
6
-
7
7
  Готовая конфигурация [Stylelint](https://stylelint.io/) для проверки CSS, SCSS и
8
8
  Vue-файлов: настроенные правила из популярных stylelint-плагинов - порядок и
9
9
  синтаксис свойств, доступность, БЭМ, поддержка SCSS и т.д. Вместо того чтобы
@@ -28,6 +28,7 @@ import { defineConfig, plugins } from '@alexlit/config-stylelint';
28
28
  export default defineConfig([
29
29
  plugins.scss(),
30
30
  plugins.vue(),
31
+
31
32
  plugins.prettier(),
32
33
  ]);
33
34
  ```
@@ -42,22 +43,23 @@ export default defineConfig([
42
43
  import { defineConfig, plugins } from '@alexlit/config-stylelint';
43
44
 
44
45
  export default defineConfig([
46
+ plugins.a11y(),
47
+ plugins.bem(),
45
48
  plugins.colorFormat(),
46
49
  plugins.declarationBlockNoIgnoredProperties(),
50
+ plugins.gamut(),
47
51
  plugins.highPerformanceAnimation(),
52
+ plugins.logicalCss(),
53
+ plugins.mediaUseCustomMedia(),
48
54
  plugins.noNestedMedia(),
55
+ plugins.noUnresolvedModule(),
56
+ plugins.noUnsupportedBrowserFeatures(),
49
57
  plugins.order(),
50
58
  plugins.scss(),
51
59
  plugins.selectorNoEmpty(),
52
60
  plugins.useNesting(),
53
61
  plugins.vue(),
54
- plugins.a11y(),
55
- plugins.bem(),
56
- plugins.gamut(),
57
- plugins.logicalCss(),
58
- plugins.mediaUseCustomMedia(),
59
- plugins.noUnresolvedModule(),
60
- plugins.noUnsupportedBrowserFeatures(),
62
+
61
63
  plugins.prettier(),
62
64
  ]);
63
65
  ```
@@ -80,6 +82,40 @@ export default defineConfig([
80
82
  ]);
81
83
  ```
82
84
 
85
+ `rules` мержатся поверхностно: настройка одноимённого правила из опций заменяет
86
+ дефолтную целиком.
87
+
88
+ ### Правила для отдельных файлов
89
+
90
+ Чтобы применить правила только к части файлов, используйте `overrides` в опциях
91
+ проверки. Пользовательские overrides добавляются после дефолтных, поэтому
92
+ выигрывают у них:
93
+
94
+ ```js
95
+ // stylelint.config.js
96
+ import { defineConfig, plugins } from '@alexlit/config-stylelint';
97
+
98
+ export default defineConfig([
99
+ plugins.useNesting({
100
+ overrides: [
101
+ { files: ['**/*.vue'], rules: { 'csstools/use-nesting': 'never' } },
102
+ ],
103
+ }),
104
+ ]);
105
+ ```
106
+
107
+ `files` обязателен: Stylelint падает с ошибкой, если в override его нет.
108
+
109
+ ### Приоритет настроек
110
+
111
+ Внутри одной проверки: дефолты → `options.rules` → `options.overrides` (для
112
+ подходящих файлов). Между проверками и вторым аргументом `defineConfig`
113
+ действует тот же порядок: база → проверки по порядку → `options`.
114
+
115
+ Коллекции (`extends`, `ignoreFiles`, `overrides`, `plugins`) дополняются,
116
+ `plugins` дедуплицируются. Остальные поля, например `customSyntax`, заменяются
117
+ значениями из опций.
118
+
83
119
  ### Общие настройки Stylelint
84
120
 
85
121
  Второй аргумент `defineConfig` - общие опции: собственные правила, файлы для
@@ -97,26 +133,41 @@ export default defineConfig([plugins.scss(), plugins.vue()], {
97
133
 
98
134
  ## Проверки
99
135
 
100
- | Проверка | Что делает | Плагин |
101
- | ----------------------------------------------- | ---------------------------------------------------- | --------------------------------------------------- |
102
- | `plugins.a11y()` | Проверяет типичные ошибки доступности | `@double-great/stylelint-a11y` |
103
- | `plugins.bem()` | Настраивает линтинг по методологии БЭМ | `@morev/stylelint-plugin` |
104
- | `plugins.colorFormat()` | Нормализует формат цветов (hex → rgb/hsl) | встроенное правило `color-format/format` |
105
- | `plugins.declarationBlockNoIgnoredProperties()` | Запрещает бесполезные свойства в блоке объявлений | `stylelint-declaration-block-no-ignored-properties` |
106
- | `plugins.gamut()` | Проверяет цвета на выход за пределы цветового охвата | `stylelint-gamut` |
107
- | `plugins.highPerformanceAnimation()` | Запрещает анимации, нагружающие рендеринг | `stylelint-high-performance-animation` |
108
- | `plugins.logicalCss()` | Проверяет использование логических CSS-свойств | `stylelint-plugin-logical-css` |
109
- | `plugins.mediaUseCustomMedia()` | Требует использования кастомных медиа-запросов | `stylelint-media-use-custom-media` |
110
- | `plugins.noIndistinguishableColors()` | Запрещает неразличимые цвета | `stylelint-no-indistinguishable-colors` |
111
- | `plugins.noNestedMedia()` | Запрещает вложенные медиа-запросы | `stylelint-no-nested-media` |
112
- | `plugins.noUnresolvedModule()` | Проверяет разрешение импортов | `stylelint-no-unresolved-module` |
113
- | `plugins.noUnsupportedBrowserFeatures()` | Проверяет поддержку CSS-функций целевыми браузерами | `stylelint-no-unsupported-browser-features` |
114
- | `plugins.order()` | Настраивает порядок свойств и селекторов | `stylelint-order` |
115
- | `plugins.prettier()` | Интегрирует Prettier | `stylelint-prettier` |
116
- | `plugins.scss()` | Настраивает линтинг SCSS | `stylelint-scss` |
117
- | `plugins.selectorNoEmpty()` | Запрещает пустые селекторы | `stylelint-selector-no-empty` |
118
- | `plugins.useNesting()` | Требует использования CSS-вложенности | `stylelint-use-nesting` |
119
- | `plugins.vue()` | Подключает поддержку Vue.js SFC | `stylelint-config-recommended-vue` |
136
+ | Проверка | Что делает | Плагин |
137
+ | ----------------------------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
138
+ | `plugins.a11y()` | Проверяет типичные ошибки доступности | [`@double-great/stylelint-a11y`](https://github.com/double-great/stylelint-a11y) |
139
+ | `plugins.bem()` | Настраивает линтинг по методологии БЭМ | [`@morev/stylelint-plugin`](https://morevm.github.io/stylelint-plugin/) |
140
+ | `plugins.colorFormat()` | Нормализует формат цветов (hex → rgb/hsl) | встроенное правило `color-format/format` |
141
+ | `plugins.declarationBlockNoIgnoredProperties()` | Запрещает бесполезные свойства в блоке объявлений | [`stylelint-declaration-block-no-ignored-properties`](https://github.com/kristerkari/stylelint-declaration-block-no-ignored-properties) |
142
+ | `plugins.gamut()` | Проверяет цвета на выход за пределы цветового охвата | [`stylelint-gamut`](https://github.com/fpetrakov/stylelint-gamut) |
143
+ | `plugins.highPerformanceAnimation()` | Запрещает анимации, нагружающие рендеринг | [`stylelint-high-performance-animation`](https://github.com/kristerkari/stylelint-high-performance-animation) |
144
+ | `plugins.logicalCss()` | Проверяет использование логических CSS-свойств | [`stylelint-plugin-logical-css`](https://github.com/yuschick/stylelint-plugin-logical-css) |
145
+ | `plugins.mediaUseCustomMedia()` | Требует использования кастомных медиа-запросов | [`stylelint-media-use-custom-media`](https://github.com/csstools/stylelint-media-use-custom-media) |
146
+ | `plugins.noIndistinguishableColors()` | Запрещает неразличимые цвета | [`stylelint-no-indistinguishable-colors`](https://github.com/ierhyna/stylelint-no-indistinguishable-colors) |
147
+ | `plugins.noNestedMedia()` | Запрещает вложенные медиа-запросы | [`stylelint-no-nested-media`](https://github.com/dkrnl/stylelint-no-nested-media) |
148
+ | `plugins.noUnresolvedModule()` | Проверяет разрешение импортов | [`stylelint-no-unresolved-module`](https://github.com/niksy/stylelint-no-unresolved-module) |
149
+ | `plugins.noUnsupportedBrowserFeatures()` | Проверяет поддержку CSS-функций целевыми браузерами | [`stylelint-no-unsupported-browser-features`](https://github.com/ismay/stylelint-no-unsupported-browser-features) |
150
+ | `plugins.order()` | Настраивает порядок свойств и селекторов | [`stylelint-order`](https://github.com/hudochenkov/stylelint-order) |
151
+ | `plugins.prettier()` | Интегрирует Prettier | [`stylelint-prettier`](https://github.com/prettier/stylelint-prettier) |
152
+ | `plugins.scss()` | Настраивает линтинг SCSS | [`stylelint-scss`](https://github.com/kristerkari/stylelint-scss) |
153
+ | `plugins.selectorNoEmpty()` | Запрещает пустые селекторы | [`stylelint-selector-no-empty`](https://github.com/ssivanatarajan/stylelint-selector-no-empty) |
154
+ | `plugins.useNesting()` | Требует использования CSS-вложенности | [`stylelint-use-nesting`](https://github.com/csstools/stylelint-use-nesting) |
155
+ | `plugins.vue()` | Подключает поддержку Vue.js SFC | [`stylelint-config-recommended-vue`](https://github.com/ota-meshi/stylelint-config-recommended-vue) |
156
+
157
+ ## Миграция с v63
158
+
159
+ v64 - major-релиз: коллекции в опциях проверок теперь дополняют дефолты, а не
160
+ заменяют их.
161
+
162
+ | Было | Стало |
163
+ | --------------------------------------------------------- | ------------------------------------------------------------------- |
164
+ | `plugins.scss({ extends: ['custom'] })` заменял дефолтный | `extends` дополняется, `custom` применяется после дефолтного |
165
+ | `plugins.useNesting({ plugins: ['custom'] })` заменял | `plugins` дополняется, дубли убираются |
166
+ | `plugins.bem({ overrides: [...] })` заменял дефолтные | overrides дополняются, пользовательские применяются после дефолтных |
167
+
168
+ Отключить конкретное дефолтное правило можно через `rules: { 'rule': null }`.
169
+ Общие настройки, которые должны перебивать всё, передавайте вторым аргументом
170
+ `defineConfig`.
120
171
 
121
172
  ## Миграция с v61
122
173
 
@@ -3,6 +3,10 @@ import type { Config } from 'stylelint';
3
3
  /**
4
4
  * Опции фабрики плагина - частичный конфиг Stylelint, накладываемый поверх
5
5
  * значений по умолчанию.
6
+ *
7
+ * Коллекции (`extends`, `ignoreFiles`, `overrides`, `plugins`) дополняют
8
+ * значения по умолчанию, `rules` мержатся поверхностно, остальные поля
9
+ * заменяются. Для каждого элемента `overrides` обязателен `files`.
6
10
  */
7
11
  type PluginOptions = Partial<Config>;
8
12
 
@@ -17,6 +17,7 @@ import { scss } from './plugins/scss.js';
17
17
  import { selectorNoEmpty } from './plugins/selector-no-empty.js';
18
18
  import { useNesting } from './plugins/use-nesting.js';
19
19
  import { vue } from './plugins/vue.js';
20
+ import { mergeConfigs } from './utils/merge-configs.js';
20
21
 
21
22
  /** Плагины. Дефолтных плагинов нет - подключайте нужные явно в `defineConfig`. */
22
23
  const plugins = {
@@ -141,8 +142,8 @@ const BASE_RULES = {
141
142
  * Создать конфиг Stylelint.
142
143
  *
143
144
  * Приоритет (от низкого к высокому): база → конфиги плагинов по порядку →
144
- * `options`. `extends`, `ignoreFiles`, `overrides` и `plugins` конкатенируются
145
- * (дубли `plugins` убираются), `rules` - shallow merge.
145
+ * `options`. Коллекции (`extends`, `ignoreFiles`, `overrides`, `plugins`)
146
+ * конкатенируются (дубли `plugins` убираются), `rules` - shallow merge.
146
147
  *
147
148
  * @param {import('stylelint').Config[]} [pluginConfigs] - Конфиги плагинов
148
149
  * (например, `[plugins.scss(), plugins.vue()]`)
@@ -167,16 +168,7 @@ const defineConfig = (pluginConfigs = [], options = {}) => {
167
168
  rules: BASE_RULES,
168
169
  };
169
170
 
170
- const sources = [baseConfig, ...pluginConfigs, options];
171
-
172
- return {
173
- ...Object.assign({}, ...sources),
174
- extends: sources.flatMap((source) => source.extends ?? []),
175
- ignoreFiles: sources.flatMap((source) => source.ignoreFiles ?? []),
176
- overrides: sources.flatMap((source) => source.overrides ?? []),
177
- plugins: [...new Set(sources.flatMap((source) => source.plugins ?? []))],
178
- rules: Object.assign({}, ...sources.map((source) => source.rules ?? {})),
179
- };
171
+ return mergeConfigs(baseConfig, ...pluginConfigs, options);
180
172
  };
181
173
 
182
174
  export { defineConfig, plugins };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexlit/config-stylelint",
3
- "version": "63.0.1",
3
+ "version": "64.0.0",
4
4
  "private": false,
5
5
  "description": "Stylelint config",
6
6
  "keywords": [
@@ -28,7 +28,8 @@
28
28
  "README.md",
29
29
  "index.js",
30
30
  "index.d.ts",
31
- "plugins"
31
+ "plugins",
32
+ "utils"
32
33
  ],
33
34
  "scripts": {
34
35
  "lint": "cd ../../ && ./scripts/lint.stylelint.sh",
@@ -1,31 +1,25 @@
1
1
  /* eslint-disable unicorn/no-null */
2
+ import { mergeConfigs } from '../utils/merge-configs.js';
3
+
4
+ const DEFAULTS = {
5
+ plugins: ['@double-great/stylelint-a11y'],
6
+ rules: {
7
+ 'a11y/media-prefers-reduced-motion': null,
8
+ 'a11y/no-obsolete-attribute': true,
9
+ 'a11y/no-obsolete-element': true,
10
+ 'a11y/no-outline-none': true,
11
+ 'a11y/no-text-align-justify': true,
12
+ 'a11y/selector-pseudo-class-focus': true,
13
+ },
14
+ };
2
15
 
3
16
  /**
4
17
  * Проверяет типичные ошибки доступности.
5
18
  *
6
- * @param {Partial<import('stylelint').Config>} [options] - Опции, накладываемые
7
- * поверх значений по умолчанию (shallow merge)
19
+ * @param {Partial<import('stylelint').Config>} [options]
8
20
  *
9
21
  * @returns {import('stylelint').Config}
10
22
  *
11
23
  * @see [stylelint-a11y](https://github.com/double-great/stylelint-a11y)
12
24
  */
13
- export const a11y = (options = {}) => {
14
- const baseConfig = {
15
- plugins: ['@double-great/stylelint-a11y'],
16
- rules: {
17
- 'a11y/media-prefers-reduced-motion': null,
18
- 'a11y/no-obsolete-attribute': true,
19
- 'a11y/no-obsolete-element': true,
20
- 'a11y/no-outline-none': true,
21
- 'a11y/no-text-align-justify': true,
22
- 'a11y/selector-pseudo-class-focus': true,
23
- },
24
- };
25
-
26
- return {
27
- ...baseConfig,
28
- ...options,
29
- rules: { ...baseConfig.rules, ...options.rules },
30
- };
31
- };
25
+ export const a11y = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,21 +1,13 @@
1
1
  /* eslint-disable unicorn/no-null */
2
2
  import { createDefineRules } from '@morev/stylelint-plugin';
3
3
 
4
+ import { mergeConfigs } from '../utils/merge-configs.js';
5
+
4
6
  const defineRules = createDefineRules({
5
7
  separators: { element: '__', modifier: '--', modifierValue: '--' },
6
8
  });
7
9
 
8
- /**
9
- * Настраивает линтинг по методологии БЭМ.
10
- *
11
- * @param {Partial<import('stylelint').Config>} [options] - Опции, накладываемые
12
- * поверх значений по умолчанию (shallow merge)
13
- *
14
- * @returns {import('stylelint').Config}
15
- *
16
- * @see [@morev/stylelint-plugin](https://morevm.github.io/stylelint-plugin/)
17
- */
18
- export const bem = (options = {}) => ({
10
+ const DEFAULTS = {
19
11
  overrides: [
20
12
  {
21
13
  files: ['**/*.{css,scss,vue}'],
@@ -45,6 +37,15 @@ export const bem = (options = {}) => ({
45
37
  },
46
38
  ],
47
39
  plugins: ['@morev/stylelint-plugin'],
40
+ };
48
41
 
49
- ...options,
50
- });
42
+ /**
43
+ * Настраивает линтинг по методологии БЭМ.
44
+ *
45
+ * @param {Partial<import('stylelint').Config>} [options]
46
+ *
47
+ * @returns {import('stylelint').Config}
48
+ *
49
+ * @see [@morev/stylelint-plugin](https://morevm.github.io/stylelint-plugin/)
50
+ */
51
+ export const bem = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,5 +1,7 @@
1
1
  import stylelint from 'stylelint';
2
2
 
3
+ import { mergeConfigs } from '../utils/merge-configs.js';
4
+
3
5
  const { createPlugin } = stylelint;
4
6
  const { report, ruleMessages, validateOptions } = stylelint.utils;
5
7
 
@@ -168,18 +170,18 @@ const rule = function (actual, options, context) {
168
170
  rule.ruleName = ruleName;
169
171
  rule.messages = messages;
170
172
 
173
+ const DEFAULTS = {
174
+ plugins: [createPlugin(ruleName, rule)],
175
+ rules: { 'color-format/format': { format: 'rgb' } },
176
+ };
177
+
171
178
  /**
172
179
  * Нормализует формат цветов (hex → rgb/hsl).
173
180
  *
174
181
  * @param {Partial<import('stylelint').Config>} [options] - Опции, накладываемые
175
- * поверх значений по умолчанию (shallow merge)
182
+ * поверх значений по умолчанию. Коллекции (`extends`, `ignoreFiles`,
183
+ * `overrides`, `plugins`) дополняются, `rules` мержатся поверхностно
176
184
  *
177
185
  * @returns {import('stylelint').Config}
178
186
  */
179
- export const colorFormat = (options = {}) => ({
180
- plugins: [createPlugin(ruleName, rule)],
181
-
182
- ...options,
183
-
184
- rules: { 'color-format/format': { format: 'rgb' }, ...options.rules },
185
- });
187
+ export const colorFormat = (options = {}) => mergeConfigs(DEFAULTS, options);
@@ -1,20 +1,18 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = {
4
+ plugins: ['stylelint-declaration-block-no-ignored-properties'],
5
+ rules: { 'plugin/declaration-block-no-ignored-properties': true },
6
+ };
7
+
1
8
  /**
2
9
  * Запрещает бесполезные свойства в блоке объявлений.
3
10
  *
4
- * @param {Partial<import('stylelint').Config>} [options] - Опции, накладываемые
5
- * поверх значений по умолчанию (shallow merge)
11
+ * @param {Partial<import('stylelint').Config>} [options]
6
12
  *
7
13
  * @returns {import('stylelint').Config}
8
14
  *
9
15
  * @see [stylelint-declaration-block-no-ignored-properties](https://github.com/kristerkari/stylelint-declaration-block-no-ignored-properties)
10
16
  */
11
- export const declarationBlockNoIgnoredProperties = (options = {}) => ({
12
- plugins: ['stylelint-declaration-block-no-ignored-properties'],
13
-
14
- ...options,
15
-
16
- rules: {
17
- 'plugin/declaration-block-no-ignored-properties': true,
18
- ...options.rules,
19
- },
20
- });
17
+ export const declarationBlockNoIgnoredProperties = (options = {}) =>
18
+ mergeConfigs(DEFAULTS, options);
@@ -1,17 +1,17 @@
1
+ import { mergeConfigs } from '../utils/merge-configs.js';
2
+
3
+ const DEFAULTS = {
4
+ plugins: ['stylelint-gamut'],
5
+ rules: { 'gamut/color-no-out-gamut-range': true },
6
+ };
7
+
1
8
  /**
2
9
  * Проверяет цвета на выход за пределы цветового охвата (gamut).
3
10
  *
4
- * @param {Partial<import('stylelint').Config>} [options] - Опции, накладываемые
5
- * поверх значений по умолчанию (shallow merge)
11
+ * @param {Partial<import('stylelint').Config>} [options]
6
12
  *
7
13
  * @returns {import('stylelint').Config}
8
14
  *
9
15
  * @see [stylelint-gamut](https://github.com/fpetrakov/stylelint-gamut)
10
16
  */
11
- export const gamut = (options = {}) => ({
12
- plugins: ['stylelint-gamut'],
13
-
14
- ...options,
15
-
16
- rules: { 'gamut/color-no-out-gamut-range': true, ...options.rules },
17
- });
17
+ export const gamut = (options = {}) => mergeConfigs(DEFAULTS, options);