@maz-ui/eslint-config 5.0.0-beta.5 → 5.0.0-beta.6
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 +86 -1
- package/dist/index.d.mts +61 -4
- package/dist/index.d.ts +61 -4
- package/dist/index.mjs +137 -7
- package/package.json +5 -2
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', {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
@@ -127,8 +127,134 @@ const sonarjsTestRules = {
|
|
|
127
127
|
"sonarjs/no-duplicate-string": "off"
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
+
const DEFAULT_BASE_FONT_SIZE = 16;
|
|
131
|
+
const DEFAULT_UNIT = "rem";
|
|
132
|
+
const ARBITRARY_BRACKET = /\[([^\s\]]+)\]/g;
|
|
133
|
+
const HAS_PX_VALUE = /\dpx/i;
|
|
134
|
+
const PX_VALUE = /(-?(?:\d+(?:\.\d+)?|\.\d+))px/gi;
|
|
135
|
+
function convertPx(pxStr, base, unit) {
|
|
136
|
+
const px = Number.parseFloat(pxStr);
|
|
137
|
+
const value = px / base;
|
|
138
|
+
const formatted = Number.parseFloat(value.toFixed(6)).toString();
|
|
139
|
+
return `${formatted}${unit}`;
|
|
140
|
+
}
|
|
141
|
+
function findReplacements(input, base, unit) {
|
|
142
|
+
const out = [];
|
|
143
|
+
for (const match of input.matchAll(ARBITRARY_BRACKET)) {
|
|
144
|
+
const full = match[0];
|
|
145
|
+
const inner = match[1];
|
|
146
|
+
if (!HAS_PX_VALUE.test(inner))
|
|
147
|
+
continue;
|
|
148
|
+
const fixedInner = inner.replace(PX_VALUE, (_m, num) => convertPx(num, base, unit));
|
|
149
|
+
out.push({
|
|
150
|
+
original: full,
|
|
151
|
+
fixed: `[${fixedInner}]`,
|
|
152
|
+
index: match.index,
|
|
153
|
+
length: full.length
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
function applyReplacements(input, replacements) {
|
|
159
|
+
let output = "";
|
|
160
|
+
let cursor = 0;
|
|
161
|
+
for (const r of replacements) {
|
|
162
|
+
output += input.slice(cursor, r.index) + r.fixed;
|
|
163
|
+
cursor = r.index + r.length;
|
|
164
|
+
}
|
|
165
|
+
output += input.slice(cursor);
|
|
166
|
+
return output;
|
|
167
|
+
}
|
|
168
|
+
const rule = {
|
|
169
|
+
meta: {
|
|
170
|
+
type: "problem",
|
|
171
|
+
docs: {
|
|
172
|
+
description: "Disallow `px` units inside Tailwind arbitrary value classes; prefer `rem` (or `em`).",
|
|
173
|
+
recommended: false
|
|
174
|
+
},
|
|
175
|
+
fixable: "code",
|
|
176
|
+
schema: [
|
|
177
|
+
{
|
|
178
|
+
type: "object",
|
|
179
|
+
additionalProperties: false,
|
|
180
|
+
properties: {
|
|
181
|
+
baseFontSize: { type: "number", minimum: 1 },
|
|
182
|
+
unit: { type: "string", enum: ["rem", "em"] }
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
messages: {
|
|
187
|
+
preferRelativeUnit: "Tailwind class uses px; replace `{{original}}` with `{{fixed}}`."
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
create(context) {
|
|
191
|
+
const options = context.options[0] ?? {};
|
|
192
|
+
const base = options.baseFontSize ?? DEFAULT_BASE_FONT_SIZE;
|
|
193
|
+
const unit = options.unit ?? DEFAULT_UNIT;
|
|
194
|
+
const { sourceCode } = context;
|
|
195
|
+
function check(node) {
|
|
196
|
+
const raw = sourceCode.getText(node);
|
|
197
|
+
const replacements = findReplacements(raw, base, unit);
|
|
198
|
+
if (replacements.length === 0)
|
|
199
|
+
return;
|
|
200
|
+
const fixedRaw = applyReplacements(raw, replacements);
|
|
201
|
+
for (const r of replacements) {
|
|
202
|
+
context.report({
|
|
203
|
+
node,
|
|
204
|
+
messageId: "preferRelativeUnit",
|
|
205
|
+
data: { original: r.original, fixed: r.fixed },
|
|
206
|
+
fix: (fixer) => fixer.replaceText(node, fixedRaw)
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const jsVisitor = {
|
|
211
|
+
Literal(node) {
|
|
212
|
+
if (typeof node.value !== "string")
|
|
213
|
+
return;
|
|
214
|
+
check(node);
|
|
215
|
+
},
|
|
216
|
+
TemplateElement(node) {
|
|
217
|
+
check(node);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const parserServices = context.sourceCode.parserServices;
|
|
221
|
+
if (parserServices.defineTemplateBodyVisitor) {
|
|
222
|
+
return parserServices.defineTemplateBodyVisitor(
|
|
223
|
+
{ VLiteral: (node) => check(node) },
|
|
224
|
+
jsVisitor
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
return jsVisitor;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const rules = {
|
|
232
|
+
"tailwind-no-arbitrary-px": rule
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const mazPlugin = {
|
|
236
|
+
meta: {
|
|
237
|
+
name: "maz"
|
|
238
|
+
},
|
|
239
|
+
rules
|
|
240
|
+
};
|
|
241
|
+
|
|
130
242
|
const TAILWINDCSS_FILES = ["**/*.{js,jsx,cjs,mjs,ts,mts,cts,tsx,vue,html,svelte,astro,astrojs,css,scss}"];
|
|
131
243
|
const TAILWINDCSS_DEFAULT_FILES = TAILWINDCSS_FILES;
|
|
244
|
+
function resolveNoArbitraryPx(setting) {
|
|
245
|
+
if (setting === false)
|
|
246
|
+
return { severity: "off", options: { baseFontSize: 16, unit: "rem" } };
|
|
247
|
+
if (setting === void 0 || setting === true) {
|
|
248
|
+
return { severity: "error", options: { baseFontSize: 16, unit: "rem" } };
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
severity: setting.severity ?? "error",
|
|
252
|
+
options: {
|
|
253
|
+
baseFontSize: setting.baseFontSize ?? 16,
|
|
254
|
+
unit: setting.unit ?? "rem"
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
132
258
|
function tailwindcssConfigs(preset, settings) {
|
|
133
259
|
const presetConfig = betterTailwindcss.configs[preset];
|
|
134
260
|
const tailwindSettings = {};
|
|
@@ -142,16 +268,22 @@ function tailwindcssConfigs(preset, settings) {
|
|
|
142
268
|
tailwindSettings.cwd = settings.cwd;
|
|
143
269
|
if (settings.tsconfig)
|
|
144
270
|
tailwindSettings.tsconfig = settings.tsconfig;
|
|
271
|
+
const noArbitraryPx = resolveNoArbitraryPx(settings.noArbitraryPx);
|
|
145
272
|
return [{
|
|
146
273
|
...presetConfig,
|
|
147
274
|
files: TAILWINDCSS_FILES,
|
|
275
|
+
plugins: {
|
|
276
|
+
...presetConfig.plugins,
|
|
277
|
+
maz: mazPlugin
|
|
278
|
+
},
|
|
148
279
|
settings: {
|
|
149
280
|
"better-tailwindcss": tailwindSettings
|
|
150
281
|
},
|
|
151
282
|
rules: {
|
|
152
283
|
...presetConfig.rules,
|
|
153
284
|
"better-tailwindcss/no-unknown-classes": "off",
|
|
154
|
-
"better-tailwindcss/enforce-consistent-line-wrapping": "off"
|
|
285
|
+
"better-tailwindcss/enforce-consistent-line-wrapping": "off",
|
|
286
|
+
"maz/tailwind-no-arbitrary-px": [noArbitraryPx.severity, noArbitraryPx.options]
|
|
155
287
|
}
|
|
156
288
|
}];
|
|
157
289
|
}
|
|
@@ -327,17 +459,15 @@ function defineConfig(options = {}, ...userConfigs) {
|
|
|
327
459
|
log.debug(`${TAG} User: appended ${userConfigs.length} flat-config argument(s)`);
|
|
328
460
|
log.verbose(`${TAG} Final config block count: ${additionalConfigs.length + userConfigs.length + 1} (additional: ${additionalConfigs.length}, user: ${userConfigs.length}, +markdown)`);
|
|
329
461
|
log.verbose(`${TAG} Ignore globs: ${opts.ignores.length}`);
|
|
462
|
+
const userRulesBlock = opts.rules && Object.keys(opts.rules).length > 0 ? { rules: opts.rules } : void 0;
|
|
330
463
|
return antfu({
|
|
331
464
|
formatters: opts.formatters,
|
|
332
465
|
...opts,
|
|
333
|
-
rules:
|
|
334
|
-
...baseRules(env === "production"),
|
|
335
|
-
...opts.rules
|
|
336
|
-
},
|
|
466
|
+
rules: baseRules(env === "production"),
|
|
337
467
|
ignores: (() => {
|
|
338
468
|
return opts.ignores;
|
|
339
469
|
})
|
|
340
|
-
}, ...additionalConfigs, ...userConfigs, markdown);
|
|
470
|
+
}, ...additionalConfigs, ...userConfigs, ...userRulesBlock ? [userRulesBlock] : [], markdown);
|
|
341
471
|
}
|
|
342
472
|
|
|
343
|
-
export { TAILWINDCSS_DEFAULT_FILES, baseRules, defineConfig, sonarjsRules, sonarjsTestRules, tailwindcssConfigs, vueRules, vueSfcOnlyRules };
|
|
473
|
+
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
|
+
"version": "5.0.0-beta.6",
|
|
5
5
|
"description": "ESLint configuration for JavaScript/TypeScript projects",
|
|
6
6
|
"author": "Louis Mazel <me@loicmazuel.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -64,6 +64,9 @@
|
|
|
64
64
|
"dev": "unbuild --stub",
|
|
65
65
|
"typecheck": "tsc --noEmit --skipLibCheck",
|
|
66
66
|
"lint": "cross-env NODE_ENV=production eslint .",
|
|
67
|
-
"lint:fix": "pnpm lint --fix"
|
|
67
|
+
"lint:fix": "pnpm lint --fix",
|
|
68
|
+
"test:unit": "vitest run",
|
|
69
|
+
"test:unit:coverage": "vitest run --coverage",
|
|
70
|
+
"test:unit:watch": "vitest watch"
|
|
68
71
|
}
|
|
69
72
|
}
|