@maz-ui/eslint-config 5.0.0-beta.4 → 5.0.0-beta.44

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/README.md CHANGED
@@ -7,6 +7,7 @@ Reusable ESLint configuration for JavaScript/TypeScript projects, built on top o
7
7
  - 🚀 **Based on @antfu/eslint-config** — modern, performant, flat-config first
8
8
  - 🛡️ **TypeScript-first** — strict mode, sensible defaults
9
9
  - 🎨 **Tailwind CSS v3 + v4** — via [`eslint-plugin-better-tailwindcss`](https://github.com/schoero/eslint-plugin-better-tailwindcss) (compat ESLint 7→10, both Tailwind versions)
10
+ - 🧩 **Custom `maz/` rules** — ships its own ESLint plugin namespaced `maz/*` (see [Custom rules](#custom-rules))
10
11
  - 🔍 **SonarJS** — code quality / cognitive complexity
11
12
  - ♿ **Vue accessibility** — opt-in `eslint-plugin-vuejs-accessibility`
12
13
  - 📐 **Formatters** — Prettier-style formatting via `eslint-plugin-format`
@@ -96,6 +97,8 @@ defineConfig({
96
97
  // Tailwind v3 instead:
97
98
  // tailwindConfig: 'tailwind.config.ts',
98
99
  detectComponentClasses: true,
100
+ // Custom `maz/tailwind-no-arbitrary-px` rule — see "Custom rules" below.
101
+ noArbitraryPx: true,
99
102
  },
100
103
  })
101
104
  ```
@@ -103,6 +106,82 @@ defineConfig({
103
106
  > [!IMPORTANT]
104
107
  > The plugin's `no-unknown-classes` rule needs to know about your Tailwind setup (prefix, custom utilities, theme tokens). Without `entryPoint` (v4) or `tailwindConfig` (v3), it falls back to the default Tailwind config and will flood with false positives in projects that customize either. **Pass the path explicitly** if your Tailwind setup is non-standard.
105
108
 
109
+ ## Custom rules
110
+
111
+ This preset ships its own ESLint plugin under the `maz/*` namespace. Rules are organized by category — `maz/tailwind-*` for Tailwind-specific rules, ready for `maz/js-*` and others as they get added.
112
+
113
+ ### `maz/tailwind-no-arbitrary-px`
114
+
115
+ Forbids `px` units inside Tailwind arbitrary value classes (`w-[16px]`, `m-[-16px]`, `[gap:24px]`, …) and **autofixes** them to `rem` (or `em`) using the configured root font-size. Whitespace inside brackets (e.g. `[up to 100px]`) is left alone so plain prose is never rewritten.
116
+
117
+ > [!NOTE]
118
+ > The rule and the `maz` plugin are only registered when `tailwindcss` is enabled (any value other than `false`). With `tailwindcss: false` _(default)_ neither the plugin nor the rule appear in the final flat-config. To use the rule in a project that doesn't opt into the full Tailwind preset, register it manually (see [Use the plugin directly](#use-the-plugin-directly)).
119
+
120
+ When `tailwindcss` is on, the rule is enabled with defaults. You can tune it either way:
121
+
122
+ **Standard ESLint override** _(idiomatic, max control)_
123
+
124
+ ```js
125
+ defineConfig({
126
+ tailwindcss: 'recommended',
127
+ rules: {
128
+ 'maz/tailwind-no-arbitrary-px': ['error', { baseFontSize: 10, unit: 'em' }],
129
+ },
130
+ })
131
+ ```
132
+
133
+ User `rules` overrides are applied in a _trailing_ block, so they win over the rule's defaults wired in by `tailwindcssConfigs`.
134
+
135
+ **Ergonomic shortcut** _(set the defaults via `tailwindcss.noArbitraryPx`)_
136
+
137
+ ```js
138
+ defineConfig({
139
+ tailwindcss: {
140
+ preset: 'recommended',
141
+ noArbitraryPx: {
142
+ baseFontSize: 16, // default — convert px / 16 → rem
143
+ unit: 'rem', // default — target unit ('rem' | 'em')
144
+ severity: 'error', // default — 'off' | 'warn' | 'error'
145
+ },
146
+ },
147
+ })
148
+ ```
149
+
150
+ | `noArbitraryPx` value | Behavior |
151
+ | ---------------------------------- | -------------------------------------------------- |
152
+ | `true` _(default)_ | Enabled with defaults (`baseFontSize: 16`, `rem`). |
153
+ | `false` | Disabled. |
154
+ | `{ baseFontSize, unit, severity }` | Override any subset of the defaults. |
155
+
156
+ If both are set, the standard `rules` override wins (last block applied).
157
+
158
+ Examples after autofix (with `baseFontSize: 16`):
159
+
160
+ | Before | After |
161
+ | --------------------- | ----------------------- |
162
+ | `w-[16px]` | `w-[1rem]` |
163
+ | `m-[-16px]` | `m-[-1rem]` |
164
+ | `tracking-[.5px]` | `tracking-[0.03125rem]` |
165
+ | `p-[16px_8px]` | `p-[1rem_0.5rem]` |
166
+ | `[gap:24px]` | `[gap:1.5rem]` |
167
+ | `w-[calc(100%-16px)]` | `w-[calc(100%-1rem)]` |
168
+
169
+ ### Use the plugin directly
170
+
171
+ If you don't want the full Tailwind preset (or just prefer wiring rules yourself), import `mazPlugin` and register it in your own flat-config block. This is also the way to use `maz/tailwind-*` rules without enabling `tailwindcss` in `defineConfig`:
172
+
173
+ ```js
174
+ import { mazPlugin } from '@maz-ui/eslint-config'
175
+
176
+ export default [{
177
+ files: ['**/*.{ts,tsx,vue}'],
178
+ plugins: { maz: mazPlugin },
179
+ rules: {
180
+ 'maz/tailwind-no-arbitrary-px': ['error', { baseFontSize: 16 }],
181
+ },
182
+ }]
183
+ ```
184
+
106
185
  ## Advanced
107
186
 
108
187
  ### Compose your own config
@@ -110,6 +189,7 @@ defineConfig({
110
189
  ```js
111
190
  import {
112
191
  baseRules,
192
+ mazPlugin,
113
193
  sonarjsRules,
114
194
  tailwindcssConfigs,
115
195
  vueRules,
@@ -117,13 +197,18 @@ import {
117
197
 
118
198
  export default [
119
199
  {
200
+ plugins: { maz: mazPlugin },
120
201
  rules: {
121
202
  ...baseRules(true), // production = true
122
203
  ...sonarjsRules,
123
204
  ...vueRules,
205
+ 'maz/tailwind-no-arbitrary-px': 'error',
124
206
  },
125
207
  },
126
- ...tailwindcssConfigs('stylistic', { entryPoint: 'src/main.css' }),
208
+ ...tailwindcssConfigs('stylistic', {
209
+ entryPoint: 'src/main.css',
210
+ noArbitraryPx: { unit: 'em' },
211
+ }),
127
212
  ]
128
213
  ```
129
214
 
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { antfu, OptionsConfig, Rules, TypedFlatConfigItem } from '@antfu/eslint-config';
2
- import { Linter } from 'eslint';
2
+ import { Linter, ESLint, Rule } from 'eslint';
3
3
 
4
4
  /**
5
5
  * Mirror of `@maz-ui/node`'s LogLevel — kept inline here to avoid making this
@@ -53,6 +53,35 @@ interface MazTailwindcssOptions {
53
53
  * Tailwind config.
54
54
  */
55
55
  tsconfig?: string;
56
+ /**
57
+ * Configure the `maz/tailwind-no-arbitrary-px` rule (forbids `px`
58
+ * values inside Tailwind arbitrary value classes such as `w-[16px]`).
59
+ *
60
+ * - `false`: disable the rule.
61
+ * - `true` *(default)*: enable with defaults (`baseFontSize: 16`,
62
+ * `unit: 'rem'`).
63
+ * - Object: enable with custom options.
64
+ */
65
+ noArbitraryPx?: boolean | {
66
+ /**
67
+ * Root font size, in pixels, used to convert `Npx` to `rem`/`em`.
68
+ *
69
+ * @default 16
70
+ */
71
+ baseFontSize?: number;
72
+ /**
73
+ * Output unit for the autofix.
74
+ *
75
+ * @default 'rem'
76
+ */
77
+ unit?: 'rem' | 'em';
78
+ /**
79
+ * ESLint severity for the rule.
80
+ *
81
+ * @default 'error'
82
+ */
83
+ severity?: 'off' | 'warn' | 'error';
84
+ };
56
85
  }
57
86
  interface MazESLintOptions extends OptionsConfig {
58
87
  /**
@@ -147,9 +176,11 @@ declare const sonarjsTestRules: {
147
176
  declare const TAILWINDCSS_DEFAULT_FILES: string[];
148
177
  /**
149
178
  * Build the flat-config block(s) that wire up
150
- * `eslint-plugin-better-tailwindcss`. The plugin already ships preset
179
+ * `eslint-plugin-better-tailwindcss` AND the custom `maz/tailwind-*`
180
+ * rules shipped by this package. The plugin already ships preset
151
181
  * objects with `plugins` + `rules`; we spread them and add `files` plus
152
- * `settings['better-tailwindcss']` so the user's options reach the plugin.
182
+ * `settings['better-tailwindcss']` so the user's options reach the
183
+ * plugin.
153
184
  */
154
185
  declare function tailwindcssConfigs(preset: TailwindcssPreset, settings: MazTailwindcssOptions): Linter.Config[];
155
186
 
@@ -160,6 +191,32 @@ declare const vueSfcOnlyRules: {
160
191
  'no-useless-assignment': "off";
161
192
  };
162
193
 
194
+ /**
195
+ * The `maz` ESLint plugin bundling all custom rules shipped by
196
+ * `@maz-ui/eslint-config`. Rules are namespaced by category:
197
+ *
198
+ * - `maz/tailwind-*` — Tailwind-specific rules
199
+ * - `maz/js-*` — general JS/TS rules (when added)
200
+ * - …
201
+ *
202
+ * The plugin is auto-wired by the relevant config block in
203
+ * `src/configs/*.ts`, but it is also exported so users can compose
204
+ * their own flat-config setup.
205
+ */
206
+ declare const mazPlugin: ESLint.Plugin;
207
+
208
+ /**
209
+ * Registry of all custom rules shipped by `@maz-ui/eslint-config`.
210
+ *
211
+ * Keys here are the final rule names exposed by the `maz` plugin, so a
212
+ * file in `src/rules/tailwind/no-arbitrary-px.ts` becomes
213
+ * `maz/tailwind-no-arbitrary-px` when wired through the plugin.
214
+ *
215
+ * Add new rules by dropping a file in the matching category folder
216
+ * (`tailwind/`, `js/`, …) and registering it below.
217
+ */
218
+ declare const rules: Record<string, Rule.RuleModule>;
219
+
163
220
  /**
164
221
  * Create ESLint configuration for Maz-UI and JavaScript/TypeScript projects
165
222
  *
@@ -180,5 +237,5 @@ declare const vueSfcOnlyRules: {
180
237
  */
181
238
  declare function defineConfig(options?: MazESLintOptions, ...userConfigs: MazESLintUserConfig[]): MazESLintConfig;
182
239
 
183
- export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
240
+ export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, mazPlugin, rules as mazRules, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
184
241
  export type { MazESLintConfig, MazESLintOptions, MazTailwindcssOptions, TailwindcssPreset };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { antfu, OptionsConfig, Rules, TypedFlatConfigItem } from '@antfu/eslint-config';
2
- import { Linter } from 'eslint';
2
+ import { Linter, ESLint, Rule } from 'eslint';
3
3
 
4
4
  /**
5
5
  * Mirror of `@maz-ui/node`'s LogLevel — kept inline here to avoid making this
@@ -53,6 +53,35 @@ interface MazTailwindcssOptions {
53
53
  * Tailwind config.
54
54
  */
55
55
  tsconfig?: string;
56
+ /**
57
+ * Configure the `maz/tailwind-no-arbitrary-px` rule (forbids `px`
58
+ * values inside Tailwind arbitrary value classes such as `w-[16px]`).
59
+ *
60
+ * - `false`: disable the rule.
61
+ * - `true` *(default)*: enable with defaults (`baseFontSize: 16`,
62
+ * `unit: 'rem'`).
63
+ * - Object: enable with custom options.
64
+ */
65
+ noArbitraryPx?: boolean | {
66
+ /**
67
+ * Root font size, in pixels, used to convert `Npx` to `rem`/`em`.
68
+ *
69
+ * @default 16
70
+ */
71
+ baseFontSize?: number;
72
+ /**
73
+ * Output unit for the autofix.
74
+ *
75
+ * @default 'rem'
76
+ */
77
+ unit?: 'rem' | 'em';
78
+ /**
79
+ * ESLint severity for the rule.
80
+ *
81
+ * @default 'error'
82
+ */
83
+ severity?: 'off' | 'warn' | 'error';
84
+ };
56
85
  }
57
86
  interface MazESLintOptions extends OptionsConfig {
58
87
  /**
@@ -147,9 +176,11 @@ declare const sonarjsTestRules: {
147
176
  declare const TAILWINDCSS_DEFAULT_FILES: string[];
148
177
  /**
149
178
  * Build the flat-config block(s) that wire up
150
- * `eslint-plugin-better-tailwindcss`. The plugin already ships preset
179
+ * `eslint-plugin-better-tailwindcss` AND the custom `maz/tailwind-*`
180
+ * rules shipped by this package. The plugin already ships preset
151
181
  * objects with `plugins` + `rules`; we spread them and add `files` plus
152
- * `settings['better-tailwindcss']` so the user's options reach the plugin.
182
+ * `settings['better-tailwindcss']` so the user's options reach the
183
+ * plugin.
153
184
  */
154
185
  declare function tailwindcssConfigs(preset: TailwindcssPreset, settings: MazTailwindcssOptions): Linter.Config[];
155
186
 
@@ -160,6 +191,32 @@ declare const vueSfcOnlyRules: {
160
191
  'no-useless-assignment': "off";
161
192
  };
162
193
 
194
+ /**
195
+ * The `maz` ESLint plugin bundling all custom rules shipped by
196
+ * `@maz-ui/eslint-config`. Rules are namespaced by category:
197
+ *
198
+ * - `maz/tailwind-*` — Tailwind-specific rules
199
+ * - `maz/js-*` — general JS/TS rules (when added)
200
+ * - …
201
+ *
202
+ * The plugin is auto-wired by the relevant config block in
203
+ * `src/configs/*.ts`, but it is also exported so users can compose
204
+ * their own flat-config setup.
205
+ */
206
+ declare const mazPlugin: ESLint.Plugin;
207
+
208
+ /**
209
+ * Registry of all custom rules shipped by `@maz-ui/eslint-config`.
210
+ *
211
+ * Keys here are the final rule names exposed by the `maz` plugin, so a
212
+ * file in `src/rules/tailwind/no-arbitrary-px.ts` becomes
213
+ * `maz/tailwind-no-arbitrary-px` when wired through the plugin.
214
+ *
215
+ * Add new rules by dropping a file in the matching category folder
216
+ * (`tailwind/`, `js/`, …) and registering it below.
217
+ */
218
+ declare const rules: Record<string, Rule.RuleModule>;
219
+
163
220
  /**
164
221
  * Create ESLint configuration for Maz-UI and JavaScript/TypeScript projects
165
222
  *
@@ -180,5 +237,5 @@ declare const vueSfcOnlyRules: {
180
237
  */
181
238
  declare function defineConfig(options?: MazESLintOptions, ...userConfigs: MazESLintUserConfig[]): MazESLintConfig;
182
239
 
183
- export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
240
+ export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, mazPlugin, rules as mazRules, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
184
241
  export type { MazESLintConfig, MazESLintOptions, MazTailwindcssOptions, TailwindcssPreset };
package/dist/index.mjs CHANGED
@@ -30,8 +30,6 @@ function baseRules(isProduction) {
30
30
  "no-unassigned-vars": "error",
31
31
  "no-useless-assignment": "error",
32
32
  "preserve-caught-error": "error",
33
- // Unicorn
34
- "unicorn/prefer-global-this": "error",
35
33
  // Test
36
34
  "test/prefer-lowercase-title": "off",
37
35
  // e18e
@@ -127,8 +125,134 @@ const sonarjsTestRules = {
127
125
  "sonarjs/no-duplicate-string": "off"
128
126
  };
129
127
 
128
+ const DEFAULT_BASE_FONT_SIZE = 16;
129
+ const DEFAULT_UNIT = "rem";
130
+ const ARBITRARY_BRACKET = /\[(?=([^\s\]]+))\1\]/g;
131
+ const HAS_PX_VALUE = /\dpx/i;
132
+ const PX_VALUE = /(-?(?=(\d+(?:\.\d+)?|\.\d+))\2)px/gi;
133
+ function convertPx(pxStr, base, unit) {
134
+ const px = Number.parseFloat(pxStr);
135
+ const value = px / base;
136
+ const formatted = Number.parseFloat(value.toFixed(6)).toString();
137
+ return `${formatted}${unit}`;
138
+ }
139
+ function findReplacements(input, base, unit) {
140
+ const out = [];
141
+ for (const match of input.matchAll(ARBITRARY_BRACKET)) {
142
+ const full = match[0];
143
+ const inner = match[1];
144
+ if (!HAS_PX_VALUE.test(inner))
145
+ continue;
146
+ const fixedInner = inner.replace(PX_VALUE, (_m, num) => convertPx(num, base, unit));
147
+ out.push({
148
+ original: full,
149
+ fixed: `[${fixedInner}]`,
150
+ index: match.index,
151
+ length: full.length
152
+ });
153
+ }
154
+ return out;
155
+ }
156
+ function applyReplacements(input, replacements) {
157
+ let output = "";
158
+ let cursor = 0;
159
+ for (const r of replacements) {
160
+ output += input.slice(cursor, r.index) + r.fixed;
161
+ cursor = r.index + r.length;
162
+ }
163
+ output += input.slice(cursor);
164
+ return output;
165
+ }
166
+ const rule = {
167
+ meta: {
168
+ type: "problem",
169
+ docs: {
170
+ description: "Disallow `px` units inside Tailwind arbitrary value classes; prefer `rem` (or `em`).",
171
+ recommended: false
172
+ },
173
+ fixable: "code",
174
+ schema: [
175
+ {
176
+ type: "object",
177
+ additionalProperties: false,
178
+ properties: {
179
+ baseFontSize: { type: "number", minimum: 1 },
180
+ unit: { type: "string", enum: ["rem", "em"] }
181
+ }
182
+ }
183
+ ],
184
+ messages: {
185
+ preferRelativeUnit: "Tailwind class uses px; replace `{{original}}` with `{{fixed}}`."
186
+ }
187
+ },
188
+ create(context) {
189
+ const options = context.options[0] ?? {};
190
+ const base = options.baseFontSize ?? DEFAULT_BASE_FONT_SIZE;
191
+ const unit = options.unit ?? DEFAULT_UNIT;
192
+ const { sourceCode } = context;
193
+ function check(node) {
194
+ const raw = sourceCode.getText(node);
195
+ const replacements = findReplacements(raw, base, unit);
196
+ if (replacements.length === 0)
197
+ return;
198
+ const fixedRaw = applyReplacements(raw, replacements);
199
+ for (const r of replacements) {
200
+ context.report({
201
+ node,
202
+ messageId: "preferRelativeUnit",
203
+ data: { original: r.original, fixed: r.fixed },
204
+ fix: (fixer) => fixer.replaceText(node, fixedRaw)
205
+ });
206
+ }
207
+ }
208
+ const jsVisitor = {
209
+ Literal(node) {
210
+ if (typeof node.value !== "string")
211
+ return;
212
+ check(node);
213
+ },
214
+ TemplateElement(node) {
215
+ check(node);
216
+ }
217
+ };
218
+ const parserServices = context.sourceCode.parserServices;
219
+ if (parserServices.defineTemplateBodyVisitor) {
220
+ return parserServices.defineTemplateBodyVisitor(
221
+ { VLiteral: (node) => check(node) },
222
+ jsVisitor
223
+ );
224
+ }
225
+ return jsVisitor;
226
+ }
227
+ };
228
+
229
+ const rules = {
230
+ "tailwind-no-arbitrary-px": rule
231
+ };
232
+
233
+ const mazPlugin = {
234
+ meta: {
235
+ name: "maz"
236
+ },
237
+ rules
238
+ };
239
+
130
240
  const TAILWINDCSS_FILES = ["**/*.{js,jsx,cjs,mjs,ts,mts,cts,tsx,vue,html,svelte,astro,astrojs,css,scss}"];
131
241
  const TAILWINDCSS_DEFAULT_FILES = TAILWINDCSS_FILES;
242
+ function resolveNoArbitraryPx(setting) {
243
+ if (setting === false)
244
+ return { severity: "off", options: { baseFontSize: 16, unit: "rem" } };
245
+ if (setting === void 0 || setting === true) {
246
+ return { severity: "error", options: { baseFontSize: 16, unit: "rem" } };
247
+ }
248
+ return {
249
+ severity: setting.severity ?? "error",
250
+ options: {
251
+ baseFontSize: setting.baseFontSize ?? 16,
252
+ unit: setting.unit ?? "rem"
253
+ }
254
+ };
255
+ }
132
256
  function tailwindcssConfigs(preset, settings) {
133
257
  const presetConfig = betterTailwindcss.configs[preset];
134
258
  const tailwindSettings = {};
@@ -142,16 +266,23 @@ function tailwindcssConfigs(preset, settings) {
142
266
  tailwindSettings.cwd = settings.cwd;
143
267
  if (settings.tsconfig)
144
268
  tailwindSettings.tsconfig = settings.tsconfig;
269
+ const noArbitraryPx = resolveNoArbitraryPx(settings.noArbitraryPx);
145
270
  return [{
146
271
  ...presetConfig,
147
272
  files: TAILWINDCSS_FILES,
273
+ plugins: {
274
+ ...presetConfig.plugins,
275
+ maz: mazPlugin
276
+ },
148
277
  settings: {
149
278
  "better-tailwindcss": tailwindSettings
150
279
  },
151
280
  rules: {
152
281
  ...presetConfig.rules,
153
282
  "better-tailwindcss/no-unknown-classes": "off",
154
- "better-tailwindcss/enforce-consistent-line-wrapping": "off"
283
+ "better-tailwindcss/enforce-consistent-line-wrapping": "off",
284
+ "better-tailwindcss/no-concatenated-classes": "off",
285
+ "maz/tailwind-no-arbitrary-px": [noArbitraryPx.severity, noArbitraryPx.options]
155
286
  }
156
287
  }];
157
288
  }
@@ -160,6 +291,13 @@ const testRules = {
160
291
  "max-nested-callbacks": "off"
161
292
  };
162
293
 
294
+ const unicorn = {
295
+ files: ["**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue}"],
296
+ rules: {
297
+ "unicorn/prefer-global-this": "error"
298
+ }
299
+ };
300
+
163
301
  const vueRules = {
164
302
  "vue/custom-event-name-casing": ["error", "kebab-case"]
165
303
  };
@@ -167,6 +305,7 @@ const vueSfcOnlyRules = {
167
305
  "no-useless-assignment": "off"
168
306
  };
169
307
 
308
+ process.env.SYNCKIT_TIMEOUT ??= "120000";
170
309
  const TAG = "[@maz-ui/eslint-config]";
171
310
  const defaultOptions = {
172
311
  formatters: true,
@@ -286,6 +425,10 @@ function defineConfig(options = {}, ...userConfigs) {
286
425
  });
287
426
  log.debug(`${TAG} SonarJS: applied recommended preset + ${Object.keys(sonarjsRules).length} extra rules + test-file relaxations`);
288
427
  }
428
+ if (resolved.unicorn) {
429
+ additionalConfigs.push(unicorn);
430
+ log.debug(`${TAG} Unicorn: applied JS/TS-scoped rule overrides`);
431
+ }
289
432
  if (resolved.vueAccessibility) {
290
433
  const vueA11yConfigs = vueA11y.configs["flat/recommended"];
291
434
  const configsArray = Array.isArray(vueA11yConfigs) ? vueA11yConfigs : [vueA11yConfigs];
@@ -327,17 +470,15 @@ function defineConfig(options = {}, ...userConfigs) {
327
470
  log.debug(`${TAG} User: appended ${userConfigs.length} flat-config argument(s)`);
328
471
  log.verbose(`${TAG} Final config block count: ${additionalConfigs.length + userConfigs.length + 1} (additional: ${additionalConfigs.length}, user: ${userConfigs.length}, +markdown)`);
329
472
  log.verbose(`${TAG} Ignore globs: ${opts.ignores.length}`);
473
+ const userRulesBlock = opts.rules && Object.keys(opts.rules).length > 0 ? { rules: opts.rules } : void 0;
330
474
  return antfu({
331
475
  formatters: opts.formatters,
332
476
  ...opts,
333
- rules: {
334
- ...baseRules(env === "production"),
335
- ...opts.rules
336
- },
477
+ rules: baseRules(env === "production"),
337
478
  ignores: (() => {
338
479
  return opts.ignores;
339
480
  })
340
- }, ...additionalConfigs, ...userConfigs, markdown);
481
+ }, ...additionalConfigs, ...userConfigs, ...userRulesBlock ? [userRulesBlock] : [], markdown);
341
482
  }
342
483
 
343
- export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
484
+ export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, mazPlugin, rules as mazRules, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maz-ui/eslint-config",
3
3
  "type": "module",
4
- "version": "5.0.0-beta.4",
4
+ "version": "5.0.0-beta.44",
5
5
  "description": "ESLint configuration for JavaScript/TypeScript projects",
6
6
  "author": "Louis Mazel <me@loicmazuel.com>",
7
7
  "license": "MIT",
@@ -25,7 +25,8 @@
25
25
  "exports": {
26
26
  ".": {
27
27
  "types": "./dist/index.d.ts",
28
- "import": "./dist/index.mjs"
28
+ "import": "./dist/index.mjs",
29
+ "default": "./dist/index.mjs"
29
30
  }
30
31
  },
31
32
  "main": "./dist/index.mjs",
@@ -39,19 +40,21 @@
39
40
  "node": ">=20.19.0"
40
41
  },
41
42
  "peerDependencies": {
42
- "eslint": ">=9.0.0 <11.0.0"
43
+ "eslint": "^9.10.0 || ^10.0.0"
43
44
  },
44
45
  "dependencies": {
45
- "@antfu/eslint-config": "^8.2.0",
46
+ "@antfu/eslint-config": "^9.5.1",
46
47
  "consola": "^3.4.2",
47
- "eslint-plugin-better-tailwindcss": "^4.5.0",
48
+ "eslint-plugin-better-tailwindcss": "^4.7.0",
48
49
  "eslint-plugin-format": "^2.0.1",
49
- "eslint-plugin-sonarjs": "^4.0.3",
50
- "eslint-plugin-vuejs-accessibility": "^2.5.0"
50
+ "eslint-plugin-sonarjs": "^4.2.2",
51
+ "eslint-plugin-vuejs-accessibility": "^2.6.0"
51
52
  },
52
53
  "devDependencies": {
53
- "eslint": "^10.3.0",
54
- "unbuild": "^3.6.1"
54
+ "@typescript-eslint/rule-tester": "^8.70.1",
55
+ "eslint": "^10.11.0",
56
+ "unbuild": "^3.6.1",
57
+ "vue-eslint-parser": "^10.4.0"
55
58
  },
56
59
  "lint-staged": {
57
60
  "*.{js,jsx,ts,tsx,mjs,mts,cjs,md,yml,json}": [
@@ -59,11 +62,13 @@
59
62
  ]
60
63
  },
61
64
  "scripts": {
62
- "codegen": "nx build",
63
65
  "build": "unbuild",
64
66
  "dev": "unbuild --stub",
65
67
  "typecheck": "tsc --noEmit --skipLibCheck",
66
68
  "lint": "cross-env NODE_ENV=production eslint .",
67
- "lint:fix": "pnpm lint --fix"
69
+ "lint:fix": "pnpm lint --fix",
70
+ "test:unit": "vitest run",
71
+ "test:unit:coverage": "vitest run --coverage",
72
+ "test:unit:watch": "vitest watch"
68
73
  }
69
74
  }