@nextcloud/eslint-config 9.0.0 → 9.0.1
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/CHANGELOG.md +8 -1
- package/dist/configs/vue.js +4 -0
- package/dist/plugins/nextcloud/rules/no-deprecated-library-exports.js +9 -1
- package/dist/plugins/nextcloud/rules/no-deprecated-library-props.js +117 -28
- package/dist/plugins/nextcloud/utils/lib-version-parser.d.ts +3 -4
- package/dist/plugins/nextcloud/utils/lib-version-parser.js +13 -12
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,15 @@
|
|
|
4
4
|
-->
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
-
## [v9.0.
|
|
7
|
+
## [v9.0.1](https://github.com/nextcloud-libraries/eslint-config/tree/v9.0.1) (2026-07-07)
|
|
8
|
+
### Fixed
|
|
9
|
+
* fix(vue): error on `vue/attributes-order` and `vue/order-in-components` instead of warn [\#1445](https://github.com/nextcloud-libraries/eslint-config/pull/1445) \([susnux](https://github.com/susnux)\)
|
|
10
|
+
* fix: `no-deprecated-library-*` rules incorrectly behave for `nextcloud/vue` syntax [\#1452](https://github.com/nextcloud-libraries/eslint-config/pull/1452) \([Antreesy](https://github.com/Antreesy)\)
|
|
11
|
+
* fix(no-deprecated-library-props): support win32 filesystem and different `@nextcloud/vue` directory structures [\#1454](https://github.com/nextcloud-libraries/eslint-config/pull/1454) \([ShGKme](https://github.com/ShGKme)\)
|
|
12
|
+
* fix(no-deprecated-library-props): support camelCase attributes [\#1453](https://github.com/nextcloud-libraries/eslint-config/pull/1453) \([Antreesy](https://github.com/Antreesy)\)
|
|
13
|
+
* fix: increase min. Node version to 22.14 [\#1455](https://github.com/nextcloud-libraries/eslint-config/pull/1455) \([susnux](https://github.com/susnux)\)
|
|
8
14
|
|
|
15
|
+
## [v9.0.0](https://github.com/nextcloud-libraries/eslint-config/tree/v9.0.0) (2026-06-26)
|
|
9
16
|
### Breaking
|
|
10
17
|
This package now is using ESLint v10 and requires ESLint flat configurations.
|
|
11
18
|
Please refer to the README on how to adjust your configuration for flat config.
|
package/dist/configs/vue.js
CHANGED
|
@@ -123,7 +123,11 @@ export function vue(options) {
|
|
|
123
123
|
'vue/padding-line-between-blocks': 'error',
|
|
124
124
|
// Prefer separated static and dynamic class attributes
|
|
125
125
|
'vue/prefer-separate-static-class': 'error',
|
|
126
|
+
// For consistent layout of the template
|
|
127
|
+
'vue/attributes-order': 'error',
|
|
126
128
|
// For consistent layout of components
|
|
129
|
+
'vue/order-in-components': 'error',
|
|
130
|
+
// For consistent layout of script-setup components
|
|
127
131
|
'vue/define-macros-order': [
|
|
128
132
|
'error',
|
|
129
133
|
{
|
|
@@ -26,7 +26,11 @@ const rule = {
|
|
|
26
26
|
const versionSatisfies = createLibVersionValidator(context);
|
|
27
27
|
const isVersionValidForDist = versionSatisfies('8.23.0');
|
|
28
28
|
const oldPattern = '@nextcloud/vue/dist/([^/]+)/([^/.]+)';
|
|
29
|
-
|
|
29
|
+
// Matches both the legacy `dist/Mixins/*` path and a bare `mixins/*` path.
|
|
30
|
+
// There is no clean `@nextcloud/vue/mixins/*` subpath export (only components,
|
|
31
|
+
// composables, directives and functions), so mixins must be migrated to
|
|
32
|
+
// composables rather than have their import path rewritten.
|
|
33
|
+
const mixinPattern = '@nextcloud/vue/(?:dist/)?mixins/([^/.]+)';
|
|
30
34
|
const isVersionValidForTooltip = versionSatisfies('8.25.0');
|
|
31
35
|
const tooltipPattern = '@nextcloud/vue/directives/Tooltip';
|
|
32
36
|
const isVersionValidForNcSettingsInputText = versionSatisfies('8.31.0');
|
|
@@ -73,6 +77,10 @@ const rule = {
|
|
|
73
77
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
74
78
|
return;
|
|
75
79
|
}
|
|
80
|
+
// Mixins removed in v9 and already reported as `deprecatedMixin`
|
|
81
|
+
if (match[1].toLowerCase() === 'mixins') {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
76
84
|
const newImportPath = `'@nextcloud/vue/${match[1].toLowerCase()}/${match[2]}'`;
|
|
77
85
|
context.report({
|
|
78
86
|
node,
|
|
@@ -4,6 +4,37 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createLibVersionValidator } from "../utils/lib-version-parser.js";
|
|
6
6
|
import { defineTemplateBodyVisitor } from "../utils/vue-template-visitor.js";
|
|
7
|
+
/*
|
|
8
|
+
* Deprecated props can be authored in either kebab-case or camelCase:
|
|
9
|
+
* - camelCase is forced by `vue/attribute-hyphenation: never` shipped rule;
|
|
10
|
+
* - kebab-case might come from legacy code and other presets.
|
|
11
|
+
* A single `VAttribute` visitor normalizes the raw attribute name with `toCamelCase()`
|
|
12
|
+
* and dispatches to the handler registered under the canonical camelCase name.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Convert an attribute name to camelCase, matching Vue's own prop normalization,
|
|
16
|
+
* so a template attribute written in either casing maps to a single canonical name.
|
|
17
|
+
*
|
|
18
|
+
* @param name - the raw attribute name as written in the template
|
|
19
|
+
*/
|
|
20
|
+
const toCamelCase = (name) => name.replace(/-(\w)/g, (_, char) => char.toUpperCase());
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the raw (case-preserving) name of a template attribute: the argument
|
|
23
|
+
* for a directive binding (`:foo` / `v-model:foo`), or the key otherwise.
|
|
24
|
+
* Returns `undefined` when there is no static name (e.g. a dynamic argument).
|
|
25
|
+
*
|
|
26
|
+
* Must use `rawName`, not `name`: Vue lowercases `name` in the AST (`focusTrap`
|
|
27
|
+
* becomes `focustrap`), which `toCamelCase()` cannot restore, so it would no
|
|
28
|
+
* longer match the camelCase handler key. `rawName` keeps the original casing.
|
|
29
|
+
*
|
|
30
|
+
* @param node - the attribute or directive node
|
|
31
|
+
*/
|
|
32
|
+
function getRawName(node) {
|
|
33
|
+
if (node.key.type === 'VDirectiveKey') {
|
|
34
|
+
return node.key.argument?.type === 'VIdentifier' ? node.key.argument.rawName : undefined;
|
|
35
|
+
}
|
|
36
|
+
return node.key.rawName;
|
|
37
|
+
}
|
|
7
38
|
export default {
|
|
8
39
|
meta: {
|
|
9
40
|
docs: {
|
|
@@ -28,7 +59,7 @@ export default {
|
|
|
28
59
|
useNoFocusTrapInstead: 'Using `focus-trap` is deprecated - use `no-focus-trap` instead',
|
|
29
60
|
useKeepOpenInstead: 'Using `close-on-select` is deprecated - use `keep-open` instead',
|
|
30
61
|
useNcSelectUsersInstead: 'Using `user-select` is deprecated - use `NcSelectUsers` component instead',
|
|
31
|
-
useArrowEndInstead: 'Using `
|
|
62
|
+
useArrowEndInstead: 'Using `arrowRight` as `trailing-button-icon` value is deprecated - use `arrowEnd` instead',
|
|
32
63
|
removeAriaHidden: 'Using `aria-hidden` is deprecated - remove prop from components, otherwise root element will inherit incorrect attribute.',
|
|
33
64
|
removeLimitWidth: 'Using `limit-width` is deprecated - remove prop from components, otherwise root element will inherit incorrect attribute.',
|
|
34
65
|
removeExact: 'Using `exact` is deprecated - consult Vue Router documentation for alternatives.',
|
|
@@ -48,7 +79,7 @@ export default {
|
|
|
48
79
|
const isDateTimePickerFormatValid = versionSatisfies('8.25.0'); // #6738
|
|
49
80
|
const isNcSelectKeepOpenValid = versionSatisfies('8.25.0'); // #6791
|
|
50
81
|
const isNcPopoverNoFocusTrapValid = versionSatisfies('8.26.0'); // #6808
|
|
51
|
-
const isNcSelectUsersValid = versionSatisfies('8.
|
|
82
|
+
const isNcSelectUsersValid = versionSatisfies('8.25.0'); // #6791
|
|
52
83
|
const isNcTextFieldArrowEndValid = versionSatisfies('8.28.0'); // #7002
|
|
53
84
|
const isCloseButtonOutsideValid = versionSatisfies('8.32.0'); // #7553
|
|
54
85
|
const legacyTypes = [
|
|
@@ -60,8 +91,13 @@ export default {
|
|
|
60
91
|
'tertiary',
|
|
61
92
|
'tertiary-no-background',
|
|
62
93
|
];
|
|
63
|
-
|
|
64
|
-
|
|
94
|
+
/*
|
|
95
|
+
* Deprecated prop handlers keyed by their canonical camelCase name. Each
|
|
96
|
+
* handler receives the matched attribute node and verifies the owning
|
|
97
|
+
* component and installed library version itself.
|
|
98
|
+
*/
|
|
99
|
+
const handlers = {
|
|
100
|
+
type: function (node) {
|
|
65
101
|
if (![
|
|
66
102
|
'ncactions',
|
|
67
103
|
'ncappnavigationnew',
|
|
@@ -75,8 +111,10 @@ export default {
|
|
|
75
111
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
76
112
|
return;
|
|
77
113
|
}
|
|
78
|
-
const hasNativeType = node.parent.attributes.
|
|
79
|
-
|
|
114
|
+
const hasNativeType = node.parent.attributes.some((attr) => {
|
|
115
|
+
const rawName = getRawName(attr);
|
|
116
|
+
return rawName !== undefined && toCamelCase(rawName) === 'nativeType';
|
|
117
|
+
});
|
|
80
118
|
const isLiteral = node.value.type === 'VLiteral' && legacyTypes.includes(node.value.value);
|
|
81
119
|
const isExpression = node.value.type === 'VExpressionContainer'
|
|
82
120
|
&& node.value.expression.type === 'ConditionalExpression'
|
|
@@ -102,7 +140,7 @@ export default {
|
|
|
102
140
|
});
|
|
103
141
|
}
|
|
104
142
|
},
|
|
105
|
-
|
|
143
|
+
nativeType: function (node) {
|
|
106
144
|
if (![
|
|
107
145
|
'ncbutton',
|
|
108
146
|
'ncdialogbutton',
|
|
@@ -126,7 +164,7 @@ export default {
|
|
|
126
164
|
},
|
|
127
165
|
});
|
|
128
166
|
},
|
|
129
|
-
|
|
167
|
+
ariaHidden: function (node) {
|
|
130
168
|
if (node.parent.parent.name.startsWith('ncaction')
|
|
131
169
|
|| node.parent.parent.name === 'ncbutton') {
|
|
132
170
|
if (!isAriaHiddenValid) {
|
|
@@ -139,7 +177,10 @@ export default {
|
|
|
139
177
|
});
|
|
140
178
|
}
|
|
141
179
|
},
|
|
142
|
-
|
|
180
|
+
allowSwipeNavigation: function (node) {
|
|
181
|
+
if (node.parent.parent.name !== 'ncappcontent') {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
143
184
|
if (!isDisableSwipeValid) {
|
|
144
185
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
145
186
|
return;
|
|
@@ -149,7 +190,10 @@ export default {
|
|
|
149
190
|
messageId: 'useDisableSwipeForNavInstead',
|
|
150
191
|
});
|
|
151
192
|
},
|
|
152
|
-
|
|
193
|
+
showUserStatus: function (node) {
|
|
194
|
+
if (node.parent.parent.name !== 'ncavatar') {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
153
197
|
if (!isDefaultBooleanFalseValid) {
|
|
154
198
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
155
199
|
return;
|
|
@@ -159,7 +203,10 @@ export default {
|
|
|
159
203
|
messageId: 'useHideStatusInstead',
|
|
160
204
|
});
|
|
161
205
|
},
|
|
162
|
-
|
|
206
|
+
showUserStatusCompact: function (node) {
|
|
207
|
+
if (node.parent.parent.name !== 'ncavatar') {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
163
210
|
if (!isDefaultBooleanFalseValid) {
|
|
164
211
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
165
212
|
return;
|
|
@@ -169,7 +216,10 @@ export default {
|
|
|
169
216
|
messageId: 'useVerboseStatusInstead',
|
|
170
217
|
});
|
|
171
218
|
},
|
|
172
|
-
|
|
219
|
+
allowPlaceholder: function (node) {
|
|
220
|
+
if (node.parent.parent.name !== 'ncavatar') {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
173
223
|
if (!isDefaultBooleanFalseValid) {
|
|
174
224
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
175
225
|
return;
|
|
@@ -179,7 +229,10 @@ export default {
|
|
|
179
229
|
messageId: 'useNoPlaceholderInstead',
|
|
180
230
|
});
|
|
181
231
|
},
|
|
182
|
-
|
|
232
|
+
formatter: function (node) {
|
|
233
|
+
if (node.parent.parent.name !== 'ncdatetimepicker') {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
183
236
|
if (!isDateTimePickerFormatValid) {
|
|
184
237
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
185
238
|
return;
|
|
@@ -189,7 +242,10 @@ export default {
|
|
|
189
242
|
messageId: 'useFormatInstead',
|
|
190
243
|
});
|
|
191
244
|
},
|
|
192
|
-
|
|
245
|
+
lang: function (node) {
|
|
246
|
+
if (node.parent.parent.name !== 'ncdatetimepicker') {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
193
249
|
if (!isVue3Valid) {
|
|
194
250
|
// Do not throw for v8.X.X
|
|
195
251
|
return;
|
|
@@ -199,7 +255,10 @@ export default {
|
|
|
199
255
|
messageId: 'useLocaleInstead',
|
|
200
256
|
});
|
|
201
257
|
},
|
|
202
|
-
|
|
258
|
+
range: function (node) {
|
|
259
|
+
if (node.parent.parent.name !== 'ncdatetimepicker') {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
203
262
|
if (!isDateTimePickerFormatValid) {
|
|
204
263
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
205
264
|
return;
|
|
@@ -209,7 +268,7 @@ export default {
|
|
|
209
268
|
messageId: 'useTypeDateRangeInstead',
|
|
210
269
|
});
|
|
211
270
|
},
|
|
212
|
-
|
|
271
|
+
canClose: function (node) {
|
|
213
272
|
if (![
|
|
214
273
|
'ncdialog',
|
|
215
274
|
'ncmodal',
|
|
@@ -225,7 +284,10 @@ export default {
|
|
|
225
284
|
messageId: 'useNoCloseInstead',
|
|
226
285
|
});
|
|
227
286
|
},
|
|
228
|
-
|
|
287
|
+
closeOnClickOutside: function (node) {
|
|
288
|
+
if (node.parent.parent.name !== 'ncpopover') {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
229
291
|
if (!isVue3Valid) {
|
|
230
292
|
// Do not throw for v8.X.X
|
|
231
293
|
return;
|
|
@@ -235,7 +297,10 @@ export default {
|
|
|
235
297
|
messageId: 'useNoCloseOnClickOutsideInstead',
|
|
236
298
|
});
|
|
237
299
|
},
|
|
238
|
-
|
|
300
|
+
enableSwipe: function (node) {
|
|
301
|
+
if (node.parent.parent.name !== 'ncmodal') {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
239
304
|
if (!isDisableSwipeValid) {
|
|
240
305
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
241
306
|
return;
|
|
@@ -245,7 +310,10 @@ export default {
|
|
|
245
310
|
messageId: 'useDisableSwipeForModalInstead',
|
|
246
311
|
});
|
|
247
312
|
},
|
|
248
|
-
|
|
313
|
+
closeButtonContained: function (node) {
|
|
314
|
+
if (node.parent.parent.name !== 'ncmodal') {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
249
317
|
if (!isCloseButtonOutsideValid) {
|
|
250
318
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
251
319
|
return;
|
|
@@ -255,7 +323,10 @@ export default {
|
|
|
255
323
|
messageId: 'useCloseButtonOutsideInstead',
|
|
256
324
|
});
|
|
257
325
|
},
|
|
258
|
-
|
|
326
|
+
focusTrap: function (node) {
|
|
327
|
+
if (node.parent.parent.name !== 'ncpopover') {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
259
330
|
if (!isNcPopoverNoFocusTrapValid) {
|
|
260
331
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
261
332
|
return;
|
|
@@ -265,7 +336,10 @@ export default {
|
|
|
265
336
|
messageId: 'useNoFocusTrapInstead',
|
|
266
337
|
});
|
|
267
338
|
},
|
|
268
|
-
|
|
339
|
+
closeOnSelect: function (node) {
|
|
340
|
+
if (node.parent.parent.name !== 'ncselect') {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
269
343
|
if (!isNcSelectKeepOpenValid) {
|
|
270
344
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
271
345
|
return;
|
|
@@ -275,7 +349,10 @@ export default {
|
|
|
275
349
|
messageId: 'useKeepOpenInstead',
|
|
276
350
|
});
|
|
277
351
|
},
|
|
278
|
-
|
|
352
|
+
userSelect: function (node) {
|
|
353
|
+
if (node.parent.parent.name !== 'ncselect') {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
279
356
|
if (!isNcSelectUsersValid) {
|
|
280
357
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
281
358
|
return;
|
|
@@ -285,7 +362,7 @@ export default {
|
|
|
285
362
|
messageId: 'useNcSelectUsersInstead',
|
|
286
363
|
});
|
|
287
364
|
},
|
|
288
|
-
|
|
365
|
+
trailingButtonIcon: function (node) {
|
|
289
366
|
if (node.parent.parent.name !== 'nctextfield') {
|
|
290
367
|
return;
|
|
291
368
|
}
|
|
@@ -320,14 +397,17 @@ export default {
|
|
|
320
397
|
});
|
|
321
398
|
}
|
|
322
399
|
},
|
|
323
|
-
|
|
324
|
-
|
|
400
|
+
limitWidth: function (node) {
|
|
401
|
+
if (node.parent.parent.name !== 'ncsettingssection') {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
// This was deprecated in 8.12.0 (Nextcloud 30+), before first supported version by plugin
|
|
325
405
|
context.report({
|
|
326
406
|
node,
|
|
327
407
|
messageId: 'removeLimitWidth',
|
|
328
408
|
});
|
|
329
409
|
},
|
|
330
|
-
|
|
410
|
+
exact: function (node) {
|
|
331
411
|
if (![
|
|
332
412
|
'ncactionrouter',
|
|
333
413
|
'ncappnavigationitem',
|
|
@@ -346,7 +426,7 @@ export default {
|
|
|
346
426
|
messageId: 'removeExact',
|
|
347
427
|
});
|
|
348
428
|
},
|
|
349
|
-
|
|
429
|
+
checked: function (node) {
|
|
350
430
|
if (![
|
|
351
431
|
'ncactioncheckbox',
|
|
352
432
|
'ncactionradio',
|
|
@@ -379,7 +459,7 @@ export default {
|
|
|
379
459
|
},
|
|
380
460
|
});
|
|
381
461
|
},
|
|
382
|
-
|
|
462
|
+
value: function (node) {
|
|
383
463
|
if (![
|
|
384
464
|
'ncactioninput',
|
|
385
465
|
'ncactiontexteditable',
|
|
@@ -424,6 +504,15 @@ export default {
|
|
|
424
504
|
},
|
|
425
505
|
});
|
|
426
506
|
},
|
|
507
|
+
};
|
|
508
|
+
return defineTemplateBodyVisitor(context, {
|
|
509
|
+
VAttribute(node) {
|
|
510
|
+
const rawName = getRawName(node);
|
|
511
|
+
if (rawName === undefined) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
handlers[toCamelCase(rawName)]?.(node);
|
|
515
|
+
},
|
|
427
516
|
});
|
|
428
517
|
},
|
|
429
518
|
};
|
|
@@ -5,13 +5,12 @@
|
|
|
5
5
|
* @param options Options
|
|
6
6
|
* @param options.cwd The current working directory
|
|
7
7
|
* @param options.physicalFilename The real filename where ESLint is linting currently
|
|
8
|
-
* @param importResolve Optional custom import resolver function (for testing purposes)
|
|
9
8
|
* @return Function validator, return a boolean whether current version satisfies minimal required for the rule
|
|
10
9
|
*/
|
|
11
10
|
export declare function createLibVersionValidator({ cwd, physicalFilename }: {
|
|
12
|
-
cwd:
|
|
13
|
-
physicalFilename:
|
|
14
|
-
}
|
|
11
|
+
cwd: string;
|
|
12
|
+
physicalFilename: string;
|
|
13
|
+
}): ((version: string) => boolean);
|
|
15
14
|
/**
|
|
16
15
|
* Clear the module cache
|
|
17
16
|
*/
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
*/
|
|
5
5
|
import { readFileSync } from 'node:fs';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { findPackageJSON } from 'node:module';
|
|
7
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
8
|
+
import { pathToFileURL } from 'node:url';
|
|
8
9
|
import { gte } from 'semver';
|
|
9
10
|
/**
|
|
10
11
|
* Cached map of paths: Reco <path_to_package.json, validator>
|
|
@@ -17,29 +18,29 @@ const cachedMap = new Map();
|
|
|
17
18
|
* @param options Options
|
|
18
19
|
* @param options.cwd The current working directory
|
|
19
20
|
* @param options.physicalFilename The real filename where ESLint is linting currently
|
|
20
|
-
* @param importResolve Optional custom import resolver function (for testing purposes)
|
|
21
21
|
* @return Function validator, return a boolean whether current version satisfies minimal required for the rule
|
|
22
22
|
*/
|
|
23
|
-
export function createLibVersionValidator({ cwd, physicalFilename }
|
|
23
|
+
export function createLibVersionValidator({ cwd, physicalFilename }) {
|
|
24
24
|
// Try to find package.json of the nextcloud-vue package
|
|
25
25
|
const sourceFile = isAbsolute(physicalFilename)
|
|
26
26
|
? resolve(physicalFilename)
|
|
27
27
|
: resolve(cwd, physicalFilename);
|
|
28
|
-
let
|
|
28
|
+
let packageJsonPath;
|
|
29
29
|
try {
|
|
30
|
-
|
|
31
|
-
const idx = modulePath.lastIndexOf('/dist/');
|
|
32
|
-
packageJsonDir = modulePath.substring(0, idx);
|
|
30
|
+
packageJsonPath = findPackageJSON('@nextcloud/vue', pathToFileURL(sourceFile));
|
|
33
31
|
}
|
|
34
32
|
catch {
|
|
33
|
+
packageJsonPath = undefined;
|
|
34
|
+
}
|
|
35
|
+
if (!packageJsonPath) {
|
|
35
36
|
return () => false;
|
|
36
37
|
}
|
|
37
|
-
if (!cachedMap
|
|
38
|
-
const json = JSON.parse(readFileSync(
|
|
38
|
+
if (!cachedMap.has(packageJsonPath)) {
|
|
39
|
+
const json = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
39
40
|
const libVersion = json.version;
|
|
40
|
-
cachedMap
|
|
41
|
+
cachedMap.set(packageJsonPath, (version) => gte(libVersion, version));
|
|
41
42
|
}
|
|
42
|
-
return cachedMap
|
|
43
|
+
return cachedMap.get(packageJsonPath);
|
|
43
44
|
}
|
|
44
45
|
/**
|
|
45
46
|
* Clear the module cache
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextcloud/eslint-config",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.1",
|
|
4
4
|
"description": "Eslint shared config for nextcloud apps and libraries",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -48,19 +48,19 @@
|
|
|
48
48
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
49
49
|
"eslint-config-flat-gitignore": "^2.3.0",
|
|
50
50
|
"eslint-plugin-antfu": "^3.2.3",
|
|
51
|
-
"eslint-plugin-jsdoc": "^63.0.
|
|
51
|
+
"eslint-plugin-jsdoc": "^63.0.10",
|
|
52
52
|
"eslint-plugin-perfectionist": "^5.9.1",
|
|
53
53
|
"eslint-plugin-vue": "^10.9.2",
|
|
54
54
|
"fast-xml-parser": "^5.9.3",
|
|
55
55
|
"globals": "^17.7.0",
|
|
56
56
|
"semver": "^7.8.5",
|
|
57
57
|
"sort-package-json": "^4.0.0",
|
|
58
|
-
"typescript-eslint": "^8.62.
|
|
58
|
+
"typescript-eslint": "^8.62.1"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@types/node": "^26.0.
|
|
61
|
+
"@types/node": "^26.0.1",
|
|
62
62
|
"@types/semver": "^7.7.1",
|
|
63
|
-
"eslint": "^10.
|
|
63
|
+
"eslint": "^10.6.0",
|
|
64
64
|
"memfs": "^4.57.8",
|
|
65
65
|
"vitest": "^4.1.9"
|
|
66
66
|
},
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"eslint": ">=10"
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
|
-
"node": "^22.
|
|
71
|
+
"node": "^22.14 || ^24 || >=26"
|
|
72
72
|
},
|
|
73
73
|
"devEngines": {
|
|
74
74
|
"packageManager": [
|