@adyen/eslint-plugin-bento 2.7.7 → 2.9.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 (37) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +48 -15
  3. package/configs/tailwind.js +17 -0
  4. package/configs/vue-recommended.js +3 -0
  5. package/configs/vue-strict.js +3 -0
  6. package/index.js +5 -0
  7. package/package.json +1 -1
  8. package/rules/deprecation-bento-dropdown-size-prop/README.md +25 -0
  9. package/rules/deprecation-bento-dropdown-size-prop/__tests__/deprecation-bento-dropdown-size-prop.vue +9 -0
  10. package/rules/deprecation-bento-dropdown-size-prop/__tests__/eslint.config.js +26 -0
  11. package/rules/deprecation-bento-dropdown-size-prop/deprecation-bento-dropdown-size-prop.integration.test.ts +33 -0
  12. package/rules/deprecation-bento-dropdown-size-prop/deprecation-bento-dropdown-size-prop.js +78 -0
  13. package/rules/deprecation-bento-dropdown-size-prop/deprecation-bento-dropdown-size-prop.test.ts +101 -0
  14. package/rules/deprecation-components-error-prop/README.md +43 -0
  15. package/rules/deprecation-components-error-prop/__tests__/deprecation-components-error-prop.vue +17 -0
  16. package/rules/deprecation-components-error-prop/__tests__/eslint.config.js +26 -0
  17. package/rules/deprecation-components-error-prop/deprecation-components-error-prop.integration.test.ts +37 -0
  18. package/rules/deprecation-components-error-prop/deprecation-components-error-prop.js +79 -0
  19. package/rules/deprecation-components-error-prop/deprecation-components-error-prop.test.ts +120 -0
  20. package/rules/deprecation-components-input-emit/__tests__/eslint.config.js +1 -1
  21. package/rules/deprecation-components-input-emit/deprecation-components-input-emit.js +19 -4
  22. package/rules/deprecation-components-input-emit/deprecation-components-input-emit.test.ts +40 -0
  23. package/rules/deprecation-components-value-prop/__tests__/eslint.config.js +1 -1
  24. package/rules/deprecation-components-value-prop/deprecation-components-value-prop.js +24 -7
  25. package/rules/deprecation-components-value-prop/deprecation-components-value-prop.test.ts +56 -0
  26. package/rules/deprecation-filter-bar-deprecated-props/README.md +64 -0
  27. package/rules/deprecation-filter-bar-deprecated-props/__tests__/deprecation-filter-bar-deprecated-props.vue +48 -0
  28. package/rules/deprecation-filter-bar-deprecated-props/__tests__/eslint.config.js +25 -0
  29. package/rules/deprecation-filter-bar-deprecated-props/deprecation-filter-bar-deprecated-props.integration.test.ts +22 -0
  30. package/rules/deprecation-filter-bar-deprecated-props/deprecation-filter-bar-deprecated-props.js +187 -0
  31. package/rules/deprecation-filter-bar-deprecated-props/deprecation-filter-bar-deprecated-props.test.ts +421 -0
  32. package/rules/tailwind-v3-to-bento/README.md +114 -0
  33. package/rules/tailwind-v3-to-bento/__tests__/eslint.config.js +24 -0
  34. package/rules/tailwind-v3-to-bento/__tests__/tailwind-v3-to-bento.vue +15 -0
  35. package/rules/tailwind-v3-to-bento/tailwind-v3-to-bento.integration.test.ts +29 -0
  36. package/rules/tailwind-v3-to-bento/tailwind-v3-to-bento.js +377 -0
  37. package/rules/tailwind-v3-to-bento/tailwind-v3-to-bento.test.ts +403 -0
@@ -0,0 +1,421 @@
1
+ import { RuleTester } from 'eslint';
2
+ import vueParser from 'vue-eslint-parser';
3
+ import tsParser from '@typescript-eslint/parser';
4
+ import deprecationFilterBarDeprecatedProps from './deprecation-filter-bar-deprecated-props';
5
+
6
+ const ruleTester = new RuleTester({
7
+ languageOptions: {
8
+ ecmaVersion: 'latest',
9
+ sourceType: 'module',
10
+ parser: vueParser,
11
+ parserOptions: {
12
+ parser: tsParser,
13
+ },
14
+ },
15
+ });
16
+
17
+ describe('@adyen/bento/deprecation-filter-bar-deprecated-props', () => {
18
+ ruleTester.run('deprecation-filter-bar-deprecated-props', deprecationFilterBarDeprecatedProps, {
19
+ valid: [
20
+ {
21
+ name: 'Valid: bento-filter-bar with config prop (no value)',
22
+ filename: 'test.vue',
23
+ code: `
24
+ <template>
25
+ <bento-filter-bar :config="config" :filter-values="values" />
26
+ </template>
27
+ `,
28
+ },
29
+ {
30
+ name: 'Valid: filter config item without deprecated value property',
31
+ filename: 'test.vue',
32
+ code: `
33
+ <script setup>
34
+ const config = [{ field: 'name', label: 'Name', type: 'BentoInputFilter' }];
35
+ </script>
36
+ <template><bento-filter-bar :config="config" /></template>
37
+ `,
38
+ },
39
+ {
40
+ name: 'Valid: filter config options without deprecated messages keys',
41
+ filename: 'test.vue',
42
+ code: `
43
+ <script setup>
44
+ const config = [{
45
+ field: 'status',
46
+ label: 'Status',
47
+ type: 'BentoSelectFilter',
48
+ options: { listboxItems: [] },
49
+ }];
50
+ </script>
51
+ <template><bento-filter-bar :config="config" /></template>
52
+ `,
53
+ },
54
+ {
55
+ name: 'Valid: computed property key matching deprecated name (no false positive)',
56
+ filename: 'test.vue',
57
+ code: `
58
+ <script setup>
59
+ const key = 'value';
60
+ const config = [{ field: 'x', type: 'BentoInputFilter', [key]: 'test' }];
61
+ </script>
62
+ <template><bento-filter-bar :config="config" /></template>
63
+ `,
64
+ },
65
+ {
66
+ name: 'Valid: spread in options (no crash)',
67
+ filename: 'test.vue',
68
+ code: `
69
+ <script setup>
70
+ const defaults = {};
71
+ const config = [{
72
+ field: 'x',
73
+ type: 'BentoSelectFilter',
74
+ options: { ...defaults, listboxItems: [] },
75
+ }];
76
+ </script>
77
+ <template><bento-filter-bar :config="config" /></template>
78
+ `,
79
+ },
80
+ {
81
+ name: 'Valid: bento-data-grid with filters without deprecated props',
82
+ filename: 'test.vue',
83
+ code: `
84
+ <script setup>
85
+ const filters = [{ field: 'x', label: 'X', type: 'BentoInputFilter' }];
86
+ </script>
87
+ <template><bento-data-grid :filters="filters" /></template>
88
+ `,
89
+ },
90
+ {
91
+ name: 'Valid: unrelated object with options.messages (no false positive)',
92
+ filename: 'test.vue',
93
+ code: `
94
+ <script setup>
95
+ const unrelated = { options: { messages: {} } };
96
+ </script>
97
+ <template><div /></template>
98
+ `,
99
+ },
100
+ {
101
+ name: 'Valid: unrelated object with value property (no false positive)',
102
+ filename: 'test.vue',
103
+ code: `
104
+ <script setup>
105
+ const obj = { value: 'test', options: { messages: {} } };
106
+ </script>
107
+ <template><div /></template>
108
+ `,
109
+ },
110
+ ],
111
+ invalid: [
112
+ // Direct "value" prop on bento-filter-bar
113
+ {
114
+ name: 'Invalid: static value prop on bento-filter-bar',
115
+ filename: 'test.vue',
116
+ code: `<template><bento-filter-bar value="val" /></template>`,
117
+ errors: [{ messageId: 'deprecationValue' }],
118
+ },
119
+ {
120
+ name: 'Invalid: dynamic value prop on bento-filter-bar',
121
+ filename: 'test.vue',
122
+ code: `<template><bento-filter-bar :value="filters" /></template>`,
123
+ errors: [{ messageId: 'deprecationValue' }],
124
+ },
125
+ {
126
+ name: 'Invalid: v-model on bento-filter-bar',
127
+ filename: 'test.vue',
128
+ code: `<template><bento-filter-bar v-model="filters" /></template>`,
129
+ errors: [{ messageId: 'deprecationValue' }],
130
+ },
131
+ // "value" inside filter config items (script)
132
+ {
133
+ name: 'Invalid: value property in filter config item (script)',
134
+ filename: 'test.vue',
135
+ code: `
136
+ <script setup>
137
+ const config = [{
138
+ field: 'name',
139
+ type: 'BentoInputFilter',
140
+ value: 'test',
141
+ }];
142
+ </script>
143
+ <template><bento-filter-bar :config="config" /></template>
144
+ `,
145
+ errors: [{ messageId: 'deprecationConfigValue' }],
146
+ },
147
+ // "value" inside filter config items (inline template)
148
+ {
149
+ name: 'Invalid: value property in filter config item (inline template)',
150
+ filename: 'test.vue',
151
+ code: `
152
+ <template>
153
+ <bento-filter-bar :config="[{ field: 'name', type: 'BentoInputFilter', value: 'test' }]" />
154
+ </template>
155
+ `,
156
+ errors: [{ messageId: 'deprecationConfigValue' }],
157
+ },
158
+ // Deprecated messages option
159
+ {
160
+ name: 'Invalid: messages option in filter config',
161
+ filename: 'test.vue',
162
+ code: `
163
+ <script setup>
164
+ const config = [{
165
+ field: 'status',
166
+ type: 'BentoSelectFilter',
167
+ options: { messages: { en: { persistentButtonLabelPartiallySelected: 'x' } }, listboxItems: [] },
168
+ }];
169
+ </script>
170
+ <template><bento-filter-bar :config="config" /></template>
171
+ `,
172
+ errors: [{ messageId: 'deprecationOption', data: { key: 'messages' } }],
173
+ },
174
+ // Deprecated messagesPersistentButtonLabelPartiallySelectedKey
175
+ {
176
+ name: 'Invalid: messagesPersistentButtonLabelPartiallySelectedKey option',
177
+ filename: 'test.vue',
178
+ code: `
179
+ <script setup>
180
+ const config = [{
181
+ field: 'status',
182
+ type: 'BentoSelectFilter',
183
+ options: { messagesPersistentButtonLabelPartiallySelectedKey: 'customKey', listboxItems: [] },
184
+ }];
185
+ </script>
186
+ <template><bento-filter-bar :config="config" /></template>
187
+ `,
188
+ errors: [
189
+ {
190
+ messageId: 'deprecationOption',
191
+ data: { key: 'messagesPersistentButtonLabelPartiallySelectedKey' },
192
+ },
193
+ ],
194
+ },
195
+ // Deprecated messagesPersistentButtonLabelAllSelectedKey
196
+ {
197
+ name: 'Invalid: messagesPersistentButtonLabelAllSelectedKey option',
198
+ filename: 'test.vue',
199
+ code: `
200
+ <script setup>
201
+ const config = [{
202
+ field: 'status',
203
+ type: 'BentoSelectFilter',
204
+ options: { messagesPersistentButtonLabelAllSelectedKey: 'customKey', listboxItems: [] },
205
+ }];
206
+ </script>
207
+ <template><bento-filter-bar :config="config" /></template>
208
+ `,
209
+ errors: [
210
+ { messageId: 'deprecationOption', data: { key: 'messagesPersistentButtonLabelAllSelectedKey' } },
211
+ ],
212
+ },
213
+ // All 3 deprecated options together
214
+ {
215
+ name: 'Invalid: all deprecated options in one config',
216
+ filename: 'test.vue',
217
+ code: `
218
+ <script setup>
219
+ const config = [{
220
+ field: 'status',
221
+ type: 'BentoSelectFilter',
222
+ options: {
223
+ messages: {},
224
+ messagesPersistentButtonLabelPartiallySelectedKey: 'k1',
225
+ messagesPersistentButtonLabelAllSelectedKey: 'k2',
226
+ listboxItems: [],
227
+ },
228
+ }];
229
+ </script>
230
+ <template><bento-filter-bar :config="config" /></template>
231
+ `,
232
+ errors: [
233
+ { messageId: 'deprecationOption', data: { key: 'messages' } },
234
+ {
235
+ messageId: 'deprecationOption',
236
+ data: { key: 'messagesPersistentButtonLabelPartiallySelectedKey' },
237
+ },
238
+ { messageId: 'deprecationOption', data: { key: 'messagesPersistentButtonLabelAllSelectedKey' } },
239
+ ],
240
+ },
241
+ // String literal key (edge case)
242
+ {
243
+ name: 'Invalid: string literal key for deprecated option',
244
+ filename: 'test.vue',
245
+ code: `
246
+ <script setup>
247
+ const config = [{
248
+ field: 'status',
249
+ type: 'BentoSelectFilter',
250
+ options: { 'messages': {} },
251
+ }];
252
+ </script>
253
+ <template><bento-filter-bar :config="config" /></template>
254
+ `,
255
+ errors: [{ messageId: 'deprecationOption', data: { key: 'messages' } }],
256
+ },
257
+ // bento-data-grid filters with deprecated value
258
+ {
259
+ name: 'Invalid: value in data-grid filter config item',
260
+ filename: 'test.vue',
261
+ code: `
262
+ <script setup>
263
+ const filters = [{
264
+ field: 'name',
265
+ type: 'BentoInputFilter',
266
+ value: 'test',
267
+ }];
268
+ </script>
269
+ <template><bento-data-grid :filters="filters" /></template>
270
+ `,
271
+ errors: [{ messageId: 'deprecationConfigValue' }],
272
+ },
273
+ // bento-data-grid filters with deprecated options
274
+ {
275
+ name: 'Invalid: deprecated options in data-grid filter config',
276
+ filename: 'test.vue',
277
+ code: `
278
+ <script setup>
279
+ const filters = [{
280
+ field: 'status',
281
+ type: 'BentoSelectFilter',
282
+ options: { messages: {}, listboxItems: [] },
283
+ }];
284
+ </script>
285
+ <template><bento-data-grid :filters="filters" /></template>
286
+ `,
287
+ errors: [{ messageId: 'deprecationOption', data: { key: 'messages' } }],
288
+ },
289
+ // Inline template with deprecated options
290
+ {
291
+ name: 'Invalid: deprecated options in inline template config',
292
+ filename: 'test.vue',
293
+ code: `
294
+ <template>
295
+ <bento-filter-bar :config="[{
296
+ field: 'status',
297
+ type: 'BentoSelectFilter',
298
+ options: { messages: {}, listboxItems: [] },
299
+ }]" />
300
+ </template>
301
+ `,
302
+ errors: [{ messageId: 'deprecationOption', data: { key: 'messages' } }],
303
+ },
304
+ // Spread + deprecated key combined
305
+ {
306
+ name: 'Invalid: spread + deprecated option combined',
307
+ filename: 'test.vue',
308
+ code: `
309
+ <script setup>
310
+ const defaults = {};
311
+ const config = [{
312
+ field: 'status',
313
+ type: 'BentoSelectFilter',
314
+ options: { ...defaults, messages: {} },
315
+ }];
316
+ </script>
317
+ <template><bento-filter-bar :config="config" /></template>
318
+ `,
319
+ errors: [{ messageId: 'deprecationOption', data: { key: 'messages' } }],
320
+ },
321
+ ],
322
+ });
323
+
324
+ /* ------------------------------------------------ */
325
+ /* AUTOFIX TESTS */
326
+ /* ------------------------------------------------ */
327
+ ruleTester.run('deprecation-filter-bar-deprecated-props (autofix enabled)', deprecationFilterBarDeprecatedProps, {
328
+ valid: [
329
+ {
330
+ name: 'Valid: no deprecated props (autofix enabled)',
331
+ filename: 'test.vue',
332
+ options: [{ autofix: true }],
333
+ code: `<template><bento-filter-bar :config="config" /></template>`,
334
+ },
335
+ ],
336
+ invalid: [
337
+ {
338
+ name: 'Autofix: removes static value prop from bento-filter-bar',
339
+ filename: 'test.vue',
340
+ options: [{ autofix: true }],
341
+ code: `<template><bento-filter-bar value="val" /></template>`,
342
+ output: `<template><bento-filter-bar /></template>`,
343
+ errors: [{ messageId: 'deprecationValue' }],
344
+ },
345
+ {
346
+ name: 'Autofix: removes dynamic value prop from bento-filter-bar',
347
+ filename: 'test.vue',
348
+ options: [{ autofix: true }],
349
+ code: `<template><bento-filter-bar :value="filters" /></template>`,
350
+ output: `<template><bento-filter-bar /></template>`,
351
+ errors: [{ messageId: 'deprecationValue' }],
352
+ },
353
+ {
354
+ name: 'Autofix: removes v-model from bento-filter-bar',
355
+ filename: 'test.vue',
356
+ options: [{ autofix: true }],
357
+ code: `<template><bento-filter-bar v-model="filters" /></template>`,
358
+ output: `<template><bento-filter-bar /></template>`,
359
+ errors: [{ messageId: 'deprecationValue' }],
360
+ },
361
+ {
362
+ name: 'Autofix: removes value from filter config item',
363
+ filename: 'test.vue',
364
+ options: [{ autofix: true }],
365
+ code: `
366
+ <script setup>
367
+ const config = [{
368
+ field: 'name',
369
+ type: 'BentoInputFilter',
370
+ value: 'test',
371
+ }];
372
+ </script>
373
+ <template><bento-filter-bar :config="config" /></template>
374
+ `,
375
+ output: `
376
+ <script setup>
377
+ const config = [{
378
+ field: 'name',
379
+ type: 'BentoInputFilter',
380
+ }];
381
+ </script>
382
+ <template><bento-filter-bar :config="config" /></template>
383
+ `,
384
+ errors: [{ messageId: 'deprecationConfigValue' }],
385
+ },
386
+ {
387
+ name: 'Autofix: removes deprecated messages option from filter config',
388
+ filename: 'test.vue',
389
+ options: [{ autofix: true }],
390
+ code: `
391
+ <script setup>
392
+ const config = [{
393
+ field: 'status',
394
+ type: 'BentoSelectFilter',
395
+ options: { messages: {}, listboxItems: [] },
396
+ }];
397
+ </script>
398
+ <template><bento-filter-bar :config="config" /></template>
399
+ `,
400
+ output: `
401
+ <script setup>
402
+ const config = [{
403
+ field: 'status',
404
+ type: 'BentoSelectFilter',
405
+ options: { listboxItems: [] },
406
+ }];
407
+ </script>
408
+ <template><bento-filter-bar :config="config" /></template>
409
+ `,
410
+ errors: [{ messageId: 'deprecationOption', data: { key: 'messages' } }],
411
+ },
412
+ {
413
+ name: 'Autofix: does not fix when autofix is false',
414
+ filename: 'test.vue',
415
+ options: [{ autofix: false }],
416
+ code: `<template><bento-filter-bar value="val" other="x" /></template>`,
417
+ errors: [{ messageId: 'deprecationValue' }],
418
+ },
419
+ ],
420
+ });
421
+ });
@@ -0,0 +1,114 @@
1
+ # @adyen/bento/tailwind-v3-to-bento
2
+
3
+ > Replace Tailwind CSS v3 utility classes with Bento design token equivalents.
4
+
5
+ - This rule is included in the `plugin:@adyen/bento/recommended` configuration
6
+ - The `--fix` option can automatically fix most problems reported by this rule
7
+
8
+ This rule helps developers migrate from Tailwind CSS v3 default utility classes to Bento design token equivalents. It
9
+ covers spacing, border radius, border width, box shadows, breakpoints, and colors. Typography classes are flagged but
10
+ not auto-fixed — use the `bento-typography` component instead.
11
+
12
+ ## Auto-fixable mappings
13
+
14
+ ### Spacing
15
+
16
+ | Before (Tailwind 3) | After (Bento) | Value |
17
+ |---|---|---|
18
+ | `p-0` | `p-000` | 0px |
19
+ | `p-0.5` | `p-010` | 2px |
20
+ | `p-1` | `p-020` | 4px |
21
+ | `p-1.5` | `p-030` | 6px |
22
+ | `p-2` | `p-040` | 8px |
23
+ | `p-2.5` | `p-050` | 10px |
24
+ | `p-3` | `p-060` | 12px |
25
+ | `p-4` | `p-070` | 16px |
26
+ | `p-5` | `p-080` | 20px |
27
+ | `p-6` | `p-090` | 24px |
28
+ | `p-8` | `p-100` | 32px |
29
+ | `p-10` | `p-110` | 40px |
30
+ | `p-12` | `p-120` | 48px |
31
+ | `p-14` | `p-130` | 56px |
32
+ | `p-16` | `p-140` | 64px |
33
+
34
+ The same mapping applies to all spacing utilities (`m-*`, `mx-*`, `my-*`, `gap-*`, `space-x-*`, `space-y-*`, `w-*`,
35
+ `h-*`, `inset-*`, `top-*`, `right-*`, `bottom-*`, `left-*`, etc.).
36
+
37
+ ### Border radius
38
+
39
+ | Before | After | Value |
40
+ |---|---|---|
41
+ | `rounded` | `rounded-s` | 4px |
42
+ | `rounded-sm` | `rounded-xs` | 2px |
43
+ | `rounded-md` | `rounded-m` | 8px |
44
+ | `rounded-lg` | `rounded-l` | 12px |
45
+ | `rounded-xl` | `rounded-xl` | 24px |
46
+
47
+ ### Border width
48
+
49
+ | Before | After | Value |
50
+ |---|---|---|
51
+ | `border` | `border-s` | 1px |
52
+ | `border-2` | `border-m` | 2px |
53
+ | `border-4` | `border-l` | 3px |
54
+
55
+ ### Box shadows
56
+
57
+ | Before | After |
58
+ |---|---|
59
+ | `shadow` | `shadow-medium` |
60
+ | `shadow-sm` | `shadow-low` |
61
+ | `shadow-md` | `shadow-medium` |
62
+ | `shadow-lg` | `shadow-high` |
63
+ | `shadow-xl` | `shadow-high` |
64
+ | `shadow-2xl` | `shadow-high` |
65
+
66
+ ### Breakpoints
67
+
68
+ | Before | After | Value |
69
+ |---|---|---|
70
+ | `sm:` | `s-min:` | min-width: 376px |
71
+ | `md:` | `m-min:` | min-width: 500px |
72
+ | `lg:` | `l-min:` | min-width: 768px |
73
+ | `xl:` | `xl-min:` | min-width: 1280px |
74
+ | `2xl:` | `xxl:` | min-width: 1536px |
75
+
76
+ ### Colors (best-effort)
77
+
78
+ Color mappings are best-effort since Tailwind 3 uses raw color values while Bento uses semantic tokens. Examples:
79
+
80
+ | Before | After |
81
+ |---|---|
82
+ | `text-red-500` | `text-label-critical` |
83
+ | `text-green-500` | `text-label-success` |
84
+ | `text-blue-500` | `text-label-highlight` |
85
+ | `text-gray-500` | `text-label-secondary` |
86
+ | `bg-gray-100` | `bg-secondary` |
87
+ | `bg-red-100` | `bg-critical-weak` |
88
+ | `border-gray-300` | `border-outline-primary` |
89
+
90
+ ## Warn only (no auto-fix)
91
+
92
+ ### Typography
93
+
94
+ Typography classes are flagged with a warning but not auto-fixed. Use the `bento-typography` component instead.
95
+
96
+ Detected patterns: `text-sm`, `text-lg`, `font-bold`, `font-sans`, `leading-tight`, `tracking-wide`, etc.
97
+
98
+ ## ✗ BAD
99
+
100
+ ```html
101
+ <template>
102
+ <div class="p-4 m-2 rounded-md shadow-lg sm:p-8 text-red-500">Content</div>
103
+ <p class="text-sm font-bold leading-tight">Hello</p>
104
+ </template>
105
+ ```
106
+
107
+ ## ✓ GOOD
108
+
109
+ ```html
110
+ <template>
111
+ <div class="p-070 m-040 rounded-m shadow-high s-min:p-100 text-label-critical">Content</div>
112
+ <bento-typography variant="body" stronger>Hello</bento-typography>
113
+ </template>
114
+ ```
@@ -0,0 +1,24 @@
1
+ const { defineConfig } = require('eslint/config');
2
+ const vueParser = require('vue-eslint-parser');
3
+ const tsParser = require('@typescript-eslint/parser');
4
+ const adyenBento = require('@adyen/eslint-plugin-bento');
5
+
6
+ module.exports = defineConfig([
7
+ {
8
+ languageOptions: {
9
+ ecmaVersion: 'latest',
10
+ sourceType: 'module',
11
+ parser: vueParser,
12
+ parserOptions: {
13
+ parser: tsParser,
14
+ },
15
+ },
16
+ plugins: {
17
+ '@adyen/bento': adyenBento,
18
+ },
19
+ rules: {
20
+ '@adyen/bento/tailwind-v3-to-bento': 'warn',
21
+ },
22
+ files: ['**/*.vue'],
23
+ },
24
+ ]);
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div>
3
+ <div class="p-4 m-2 gap-8"></div>
4
+ <div class="rounded rounded-md rounded-lg"></div>
5
+ <div class="border border-2 border-4"></div>
6
+ <div class="shadow shadow-sm shadow-lg"></div>
7
+ <div class="sm:p-4 lg:p-8 2xl:m-2"></div>
8
+ <div class="text-red-500 bg-gray-100 border-gray-300"></div>
9
+ <div class="text-sm font-bold leading-tight tracking-wide"></div>
10
+ <div class="p-4 rounded-md shadow-lg sm:p-8 text-red-500"></div>
11
+ <div class="flex items-center justify-between"></div>
12
+ </div>
13
+ </template>
14
+
15
+ <script setup></script>
@@ -0,0 +1,29 @@
1
+ import path from 'node:path';
2
+ import { execFileSyncEslintVueFiles } from '../../utils/exec-file-sync-eslint-vue-files';
3
+
4
+ describe('@adyen/bento/tailwind-v3-to-bento', () => {
5
+ it('should lint with warning', () => {
6
+ const eslintrc = path.resolve(__dirname, '__tests__', 'eslint.config.js');
7
+ const vueFile = path.resolve(__dirname, '__tests__', 'tailwind-v3-to-bento.vue');
8
+
9
+ const result = JSON.parse(execFileSyncEslintVueFiles(eslintrc, vueFile));
10
+
11
+ // 7 fixable warnings + 4 typography warnings = 8 total messages (typography classes are per-class)
12
+ expect(result[0].warningCount).toBeGreaterThan(0);
13
+
14
+ // Verify spacing replacement
15
+ const spacingMessage = result[0].messages.find(
16
+ (m: { ruleId: string; line: number }) => m.ruleId === '@adyen/bento/tailwind-v3-to-bento' && m.line === 3
17
+ );
18
+ expect(spacingMessage).toBeDefined();
19
+ expect(spacingMessage.messageId).toBe('updateTailwindClass');
20
+
21
+ // Verify typography warning includes suggested bento-typography usage
22
+ const typographyMessage = result[0].messages.find(
23
+ (m: { messageId: string }) => m.messageId === 'removeTailwindTypography'
24
+ );
25
+ expect(typographyMessage).toBeDefined();
26
+ expect(typographyMessage.message).toContain('<bento-typography');
27
+ expect(typographyMessage.message).toContain('variant=');
28
+ });
29
+ });