@nextcloud/eslint-config 9.0.0-rc.4 → 9.0.0-rc.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/CHANGELOG.md +13 -3
- package/dist/configs/codeStyle.d.ts +1 -1
- package/dist/configs/documentation.js +20 -26
- package/dist/configs/vue.js +3 -0
- package/dist/globs.js +4 -2
- package/dist/index.d.ts +11 -6
- package/dist/index.js +4 -0
- package/dist/plugins/nextcloud/rules/no-deprecations.js +11 -1
- package/dist/plugins/nextcloud/rules/no-removed-apis.js +39 -0
- package/dist/plugins/nextcloud-vue/index.d.ts +8 -0
- package/dist/plugins/nextcloud-vue/rules/index.d.ts +8 -0
- package/dist/plugins/nextcloud-vue/rules/no-deprecated-exports.js +43 -2
- package/dist/plugins/nextcloud-vue/rules/no-deprecated-props.d.ts +8 -0
- package/dist/plugins/nextcloud-vue/rules/no-deprecated-props.js +178 -0
- package/dist/plugins/nextcloud-vue/utils/lib-version-parser.d.ts +6 -21
- package/dist/plugins/nextcloud-vue/utils/lib-version-parser.js +29 -74
- package/dist/plugins/packageJson.js +1 -0
- package/dist/utils.d.ts +1 -13
- package/package.json +19 -19
package/CHANGELOG.md
CHANGED
|
@@ -25,7 +25,10 @@ Please refer to the README on how to adjust your configuration for flat config.
|
|
|
25
25
|
* feat(no-deprecated-props): extend existing rules to support other components [\#1069](https://github.com/nextcloud-libraries/eslint-config/pull/1069) \([Antreesy](https://github.com/Antreesy)\)
|
|
26
26
|
* feat(imports): add custom plugin to suggest file extensions [\#1110](https://github.com/nextcloud-libraries/eslint-config/pull/1110) \([susnux](https://github.com/susnux)\)
|
|
27
27
|
* feat(filesystem): ignore all files within the `.gitignore` [\#1108](https://github.com/nextcloud-libraries/eslint-config/pull/1108) \([susnux](https://github.com/susnux)\)
|
|
28
|
-
* feat(l10n-plugin): also handle vue templates
|
|
28
|
+
* feat(l10n-plugin): also handle vue templates [\#1113](https://github.com/nextcloud-libraries/eslint-config/pull/1113) \([susnux](https://github.com/susnux)\)
|
|
29
|
+
* feat(nextcloud-vue-plugin): deprecate additional props [\#1163](https://github.com/nextcloud-libraries/eslint-config/pull/1163) \([Antreesy](https://github.com/Antreesy)\)
|
|
30
|
+
* feat(nextcloud-vue-plugin): deprecate additional exports [\#1162](https://github.com/nextcloud-libraries/eslint-config/pull/1162) \([Antreesy](https://github.com/Antreesy)\)
|
|
31
|
+
* feat(nextcloud-vue-plugin): deprecate NcPopover props [\#1165](https://github.com/nextcloud-libraries/eslint-config/pull/1165) \([Antreesy](https://github.com/Antreesy)\)
|
|
29
32
|
|
|
30
33
|
### Fixed
|
|
31
34
|
* fix(codestyle): do not require splitting chains [\#951](https://github.com/nextcloud-libraries/eslint-config/pull/951)
|
|
@@ -54,8 +57,12 @@ Please refer to the README on how to adjust your configuration for flat config.
|
|
|
54
57
|
* fix(vue): also ignore the global router link component [\#1097](https://github.com/nextcloud-libraries/eslint-config/pull/1097) \([susnux](https://github.com/susnux)\)
|
|
55
58
|
* fix(no-deprecated-props): respect nextcloud/vue library version for the rule [\#1084](https://github.com/nextcloud-libraries/eslint-config/pull/1084) \([Antreesy](https://github.com/Antreesy)\)
|
|
56
59
|
* fix(codestyle): replace deprecated config in `@stylistic/quotes` rule [\#1109](https://github.com/nextcloud-libraries/eslint-config/pull/1109) \([susnux](https://github.com/susnux)\)
|
|
57
|
-
* fix(l10n-plugin): also check translation strings in `n` method
|
|
58
|
-
* fix(filesystem): relax ignored files
|
|
60
|
+
* fix(l10n-plugin): also check translation strings in `n` method [\#1112](https://github.com/nextcloud-libraries/eslint-config/pull/1112) \([susnux](https://github.com/susnux)\)
|
|
61
|
+
* fix(filesystem): relax ignored files [\#1114](https://github.com/nextcloud-libraries/eslint-config/pull/1114) \([susnux](https://github.com/susnux)\)
|
|
62
|
+
* fix(globs): adjust globs for test related files [\#1128](https://github.com/nextcloud-libraries/eslint-config/pull/1128) \([susnux](https://github.com/susnux)\)
|
|
63
|
+
* fix(vue): use vue variant of `no-irregular-whitespace` [\#1129](https://github.com/nextcloud-libraries/eslint-config/pull/1129) \([susnux](https://github.com/susnux)\)
|
|
64
|
+
* fix(nextcloud): add missing deprecations and removals [\#1206](https://github.com/nextcloud-libraries/eslint-config/pull/1206) \([susnux](https://github.com/susnux)\)
|
|
65
|
+
* fix(plugin:nextcloud-vue): use resolved dependency for detecting nextcloud-vue version [\#1220](https://github.com/nextcloud-libraries/eslint-config/pull/1220) \([susnux](https://github.com/susnux)\)
|
|
59
66
|
|
|
60
67
|
### Changed
|
|
61
68
|
* Add SPDX header [#802](https://github.com/nextcloud-libraries/eslint-config/pull/802)
|
|
@@ -72,6 +79,9 @@ Please refer to the README on how to adjust your configuration for flat config.
|
|
|
72
79
|
* ci: update workflows from organization [#1047](https://github.com/nextcloud-libraries/eslint-config/pull/1047) ([susnux](https://github.com/susnux))
|
|
73
80
|
* chore: add active node version (24) to supported engines [#1066](https://github.com/nextcloud-libraries/eslint-config/pull/1066) ([susnux](https://github.com/susnux))
|
|
74
81
|
* build: add common changelog formatting and documentation for it [#1067](https://github.com/nextcloud-libraries/eslint-config/pull/1067) ([susnux](https://github.com/susnux))
|
|
82
|
+
* chore: lint this project as a library [\#1130](https://github.com/nextcloud-libraries/eslint-config/pull/1130) \([susnux](https://github.com/susnux)\)
|
|
83
|
+
* chore: update devEngines to align with apps [\#1204](https://github.com/nextcloud-libraries/eslint-config/pull/1204) \([susnux](https://github.com/susnux)\)
|
|
84
|
+
* build: disable libcheck for Typescript [\#1205](https://github.com/nextcloud-libraries/eslint-config/pull/1205) \([susnux](https://github.com/susnux)\)
|
|
75
85
|
* Updated `@eslint/json` to 0.12.0
|
|
76
86
|
* Updated `@stylistic/eslint-plugin` 4.2.0
|
|
77
87
|
* Updated `eslint-plugin-jsdoc` to 50.6.11
|
|
@@ -10,4 +10,4 @@ import type { ConfigOptions } from '../types.d.ts';
|
|
|
10
10
|
*
|
|
11
11
|
* @param options options defining the config preset flavor
|
|
12
12
|
*/
|
|
13
|
-
export declare function codeStyle(options: ConfigOptions):
|
|
13
|
+
export declare function codeStyle(options: ConfigOptions): Linter.Config[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsdoc } from 'eslint-plugin-jsdoc';
|
|
2
2
|
import { GLOB_FILES_JAVASCRIPT, GLOB_FILES_TESTING, GLOB_FILES_TYPESCRIPT, GLOB_FILES_VUE, } from "../globs.js";
|
|
3
3
|
const TS_FUNCTION_CONTEXTS = [
|
|
4
4
|
'FunctionDeclaration:has(TSTypeAnnotation)',
|
|
@@ -12,6 +12,12 @@ const JS_FUNCTION_CONTEXTS = [
|
|
|
12
12
|
'ArrowFunctionExpression:not(:has(TSTypeAnnotation))',
|
|
13
13
|
'MethodDefinition:not(:has(TSTypeAnnotation))',
|
|
14
14
|
];
|
|
15
|
+
const SHARED_JSDOC_SETTINGS = {
|
|
16
|
+
// We use the alias for legacy reasons to prevent unnecessary noise
|
|
17
|
+
tagNamePreference: {
|
|
18
|
+
returns: 'return',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
15
21
|
/**
|
|
16
22
|
* Config factory for code documentation related rules (JSDoc)
|
|
17
23
|
*
|
|
@@ -20,30 +26,26 @@ const JS_FUNCTION_CONTEXTS = [
|
|
|
20
26
|
export function documentation(options) {
|
|
21
27
|
return [
|
|
22
28
|
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
...jsdocPlugin.configs['flat/recommended-typescript-flavor'],
|
|
29
|
+
...jsdoc({
|
|
30
|
+
config: 'flat/recommended-typescript-flavor',
|
|
31
|
+
settings: {
|
|
32
|
+
...SHARED_JSDOC_SETTINGS,
|
|
33
|
+
mode: 'permissive',
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
36
|
+
name: 'nextcloud/documentation/javascript',
|
|
34
37
|
files: [
|
|
35
38
|
...GLOB_FILES_JAVASCRIPT,
|
|
36
39
|
...(options.vueIsTypescript ? [] : GLOB_FILES_VUE),
|
|
37
40
|
],
|
|
38
|
-
settings: {
|
|
39
|
-
jsdoc: {
|
|
40
|
-
mode: 'permissive',
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
41
|
ignores: GLOB_FILES_TESTING,
|
|
44
42
|
},
|
|
45
43
|
{
|
|
46
|
-
...
|
|
44
|
+
...jsdoc({
|
|
45
|
+
config: 'flat/recommended-typescript',
|
|
46
|
+
settings: SHARED_JSDOC_SETTINGS,
|
|
47
|
+
}),
|
|
48
|
+
name: 'nextcloud/documentation/typescript',
|
|
47
49
|
files: [
|
|
48
50
|
...GLOB_FILES_TYPESCRIPT,
|
|
49
51
|
...(options.vueIsTypescript ? GLOB_FILES_VUE : []),
|
|
@@ -71,14 +73,6 @@ export function documentation(options) {
|
|
|
71
73
|
{ startLines: 1 },
|
|
72
74
|
],
|
|
73
75
|
},
|
|
74
|
-
settings: {
|
|
75
|
-
jsdoc: {
|
|
76
|
-
// We use the alias for legacy reasons to prevent unnecessary noise
|
|
77
|
-
tagNamePreference: {
|
|
78
|
-
returns: 'return',
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
76
|
},
|
|
83
77
|
{
|
|
84
78
|
name: 'nextcloud/documentation/rules-typescript',
|
package/dist/configs/vue.js
CHANGED
|
@@ -99,6 +99,9 @@ export function vue(options) {
|
|
|
99
99
|
'vue/no-unused-refs': 'warn',
|
|
100
100
|
// Warn on unused props
|
|
101
101
|
'vue/no-unused-properties': 'warn',
|
|
102
|
+
// This rule does not work in vue files, we must use the vue one
|
|
103
|
+
'no-irregular-whitespace': 'off',
|
|
104
|
+
'vue/no-irregular-whitespace': 'error',
|
|
102
105
|
},
|
|
103
106
|
},
|
|
104
107
|
{
|
package/dist/globs.js
CHANGED
|
@@ -7,8 +7,10 @@ export const GLOB_FILES_TESTING = [
|
|
|
7
7
|
'**/*.test.*',
|
|
8
8
|
'**/*.spec.*',
|
|
9
9
|
'**/*.cy.*',
|
|
10
|
-
'**/test',
|
|
11
|
-
'**/tests',
|
|
10
|
+
'**/test/**',
|
|
11
|
+
'**/tests/**',
|
|
12
|
+
'**/__tests__/**',
|
|
13
|
+
'**/__mocks__/**',
|
|
12
14
|
];
|
|
13
15
|
/** Glob pattern for Typescript files */
|
|
14
16
|
export const GLOB_FILES_TYPESCRIPT = [
|
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
|
3
|
+
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
*/
|
|
5
|
+
import type { Linter } from 'eslint';
|
|
1
6
|
/**
|
|
2
7
|
* Nextcloud shared configuration for projects using Vue 2 with Javascript <script> blocks
|
|
3
8
|
*/
|
|
4
|
-
export declare const recommendedVue2Javascript:
|
|
9
|
+
export declare const recommendedVue2Javascript: Linter.Config[];
|
|
5
10
|
/**
|
|
6
11
|
* Nextcloud shared configuration for projects using Vue 2 with Typescript <script> blocks
|
|
7
12
|
*/
|
|
8
|
-
export declare const recommendedVue2:
|
|
13
|
+
export declare const recommendedVue2: Linter.Config[];
|
|
9
14
|
/**
|
|
10
15
|
* Nextcloud shared configuration for projects using Vue 3 with Javascript <script> blocks
|
|
11
16
|
*/
|
|
12
|
-
export declare const recommendedJavascript:
|
|
17
|
+
export declare const recommendedJavascript: Linter.Config[];
|
|
13
18
|
/**
|
|
14
19
|
* Nextcloud shared configuration for projects using Vue 3 with Typescript <script> blocks
|
|
15
20
|
*/
|
|
16
|
-
export declare const recommended:
|
|
21
|
+
export declare const recommended: Linter.Config[];
|
|
17
22
|
/**
|
|
18
23
|
* Nextcloud shared configuration for projects using Vue 3 with Typescript <script> blocks
|
|
19
24
|
*/
|
|
20
|
-
export declare const recommendedLibrary:
|
|
25
|
+
export declare const recommendedLibrary: Linter.Config[];
|
|
21
26
|
/**
|
|
22
27
|
* Nextcloud shared configuration for projects using Vue 3 with Typescript <script> blocks
|
|
23
28
|
*/
|
|
24
|
-
export declare const recommendedVue2Library:
|
|
29
|
+
export declare const recommendedVue2Library: Linter.Config[];
|
|
25
30
|
export { default as packageJsonPlugin } from './plugins/packageJson.ts';
|
|
26
31
|
export { default as nextcloudPlugin } from './plugins/nextcloud/index.ts';
|
|
27
32
|
export { default as l10nPlugin } from './plugins/l10n/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
|
3
|
+
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
*/
|
|
1
5
|
import { codeStyle } from "./configs/codeStyle.js";
|
|
2
6
|
import { documentation } from "./configs/documentation.js";
|
|
3
7
|
import { filesystem } from "./configs/filesystem.js";
|
|
@@ -31,15 +31,18 @@ const global = {
|
|
|
31
31
|
relative_modified_date: '16.0.0',
|
|
32
32
|
};
|
|
33
33
|
const oc = {
|
|
34
|
+
AppConfig: '16.0.0',
|
|
34
35
|
L10n: '26.0.0',
|
|
36
|
+
SystemTags: '32.0.0',
|
|
35
37
|
_capabilities: '17.0.0',
|
|
36
38
|
addTranslations: '17.0.0',
|
|
37
39
|
basename: '18.0.0',
|
|
38
40
|
coreApps: '17.0.0',
|
|
39
41
|
currentUser: '19.0.0',
|
|
42
|
+
dialogs: '30.0.0',
|
|
40
43
|
dirname: '18.0.0',
|
|
41
44
|
encodePath: '18.0.0',
|
|
42
|
-
fileIsBlacklisted: '
|
|
45
|
+
fileIsBlacklisted: '18.0.0',
|
|
43
46
|
filePath: '19.0.0',
|
|
44
47
|
generateUrl: '19.0.0',
|
|
45
48
|
get: '19.0.0',
|
|
@@ -71,6 +74,13 @@ const ocNested = {
|
|
|
71
74
|
humanFileSize: '20.0.0',
|
|
72
75
|
relativeModifiedDate: '20.0.0',
|
|
73
76
|
},
|
|
77
|
+
dialogs: {
|
|
78
|
+
fileexists: '29.0.0',
|
|
79
|
+
},
|
|
80
|
+
config: {
|
|
81
|
+
blacklist_files_regex: '30.0.0',
|
|
82
|
+
forbidden_filename_characters: '30.0.0',
|
|
83
|
+
},
|
|
74
84
|
};
|
|
75
85
|
const rule = {
|
|
76
86
|
meta: {
|
|
@@ -11,14 +11,26 @@ const global = {
|
|
|
11
11
|
getURLParameter: '19.0.0',
|
|
12
12
|
humanFileSize: '19.0.0',
|
|
13
13
|
marked: '19.0.0',
|
|
14
|
+
md5: '32.0.0',
|
|
14
15
|
relative_modified_date: '19.0.0',
|
|
15
16
|
};
|
|
16
17
|
const oc = {
|
|
18
|
+
AppConfig: '33.0.0',
|
|
19
|
+
SystemTags: '33.0.0',
|
|
17
20
|
getScrollBarWidth: '15.0.0',
|
|
18
21
|
addTranslations: '26.0.0',
|
|
19
22
|
appSettings: '28.0.0',
|
|
23
|
+
fileIsBlacklisted: '33.0.0',
|
|
24
|
+
get: '33.0.0',
|
|
25
|
+
getHost: '33.0.0',
|
|
26
|
+
getHostName: '33.0.0',
|
|
27
|
+
getPort: '33.0.0',
|
|
28
|
+
getProtocol: '33.0.0',
|
|
20
29
|
loadScript: '28.0.0',
|
|
21
30
|
loadStyle: '28.0.0',
|
|
31
|
+
redirect: '33.0.0',
|
|
32
|
+
reload: '33.0.0',
|
|
33
|
+
set: '33.0.0',
|
|
22
34
|
};
|
|
23
35
|
const ocNested = {
|
|
24
36
|
AppConfig: {
|
|
@@ -36,6 +48,12 @@ const ocNested = {
|
|
|
36
48
|
const oca = {
|
|
37
49
|
// ref: https://github.com/nextcloud/server/commit/6eced42b7a40f5b0ea0489244583219d0ee2e7af
|
|
38
50
|
Search: '20.0.0',
|
|
51
|
+
FilesSharingDrop: '31.0.0',
|
|
52
|
+
};
|
|
53
|
+
const ocaNested = {
|
|
54
|
+
Sharing: {
|
|
55
|
+
ExternalLinkActions: '33.0.0',
|
|
56
|
+
},
|
|
39
57
|
};
|
|
40
58
|
// TODO: handle OC.x.y.z like OC.Share.ShareConfigModel.areAvatarsEnabled()
|
|
41
59
|
// ref https://github.com/nextcloud/server/issues/11045
|
|
@@ -83,6 +101,27 @@ const rule = {
|
|
|
83
101
|
message: `The property or function OCA.${node.property.name} was removed in Nextcloud ${oca[node.property.name]}`,
|
|
84
102
|
});
|
|
85
103
|
}
|
|
104
|
+
// OCA.x.y
|
|
105
|
+
if (node.object.type === 'MemberExpression'
|
|
106
|
+
&& 'name' in node.object.object
|
|
107
|
+
&& node.object.object.name === 'OCA'
|
|
108
|
+
&& 'name' in node.object.property
|
|
109
|
+
&& ocaNested[node.object.property.name]
|
|
110
|
+
&& 'name' in node.property
|
|
111
|
+
&& ocaNested[node.object.property.name][node.property.name]) {
|
|
112
|
+
const version = ocaNested[node.object.property.name][node.property.name];
|
|
113
|
+
if (checkTargetVersion(version)) {
|
|
114
|
+
const prop = [
|
|
115
|
+
'OC',
|
|
116
|
+
node.object.property.name,
|
|
117
|
+
node.property.name,
|
|
118
|
+
].join('.');
|
|
119
|
+
context.report({
|
|
120
|
+
node,
|
|
121
|
+
message: `The property or function ${prop} was removed in Nextcloud ${version}`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
86
125
|
// OC.x
|
|
87
126
|
if ('name' in node.object
|
|
88
127
|
&& 'name' in node.property
|
|
@@ -21,13 +21,21 @@ declare const _default: {
|
|
|
21
21
|
useVerboseStatusInstead: string;
|
|
22
22
|
useNoPlaceholderInstead: string;
|
|
23
23
|
useFormatInstead: string;
|
|
24
|
+
useLocaleInstead: string;
|
|
24
25
|
useTypeDateRangeInstead: string;
|
|
25
26
|
useNoCloseInstead: string;
|
|
27
|
+
useNoCloseOnClickOutsideInstead: string;
|
|
26
28
|
useDisableSwipeForModalInstead: string;
|
|
27
29
|
useNoFocusTrapInstead: string;
|
|
28
30
|
useKeepOpenInstead: string;
|
|
29
31
|
useNcSelectUsersInstead: string;
|
|
32
|
+
useArrowEndInstead: string;
|
|
30
33
|
removeAriaHidden: string;
|
|
34
|
+
removeLimitWidth: string;
|
|
35
|
+
removeExact: string;
|
|
36
|
+
useCloseButtonOutsideInstead: string;
|
|
37
|
+
useModelValueInsteadChecked: string;
|
|
38
|
+
useModelValueInsteadValue: string;
|
|
31
39
|
};
|
|
32
40
|
};
|
|
33
41
|
create(context: import("eslint").Rule.RuleContext): any;
|
|
@@ -16,13 +16,21 @@ export declare const rules: {
|
|
|
16
16
|
useVerboseStatusInstead: string;
|
|
17
17
|
useNoPlaceholderInstead: string;
|
|
18
18
|
useFormatInstead: string;
|
|
19
|
+
useLocaleInstead: string;
|
|
19
20
|
useTypeDateRangeInstead: string;
|
|
20
21
|
useNoCloseInstead: string;
|
|
22
|
+
useNoCloseOnClickOutsideInstead: string;
|
|
21
23
|
useDisableSwipeForModalInstead: string;
|
|
22
24
|
useNoFocusTrapInstead: string;
|
|
23
25
|
useKeepOpenInstead: string;
|
|
24
26
|
useNcSelectUsersInstead: string;
|
|
27
|
+
useArrowEndInstead: string;
|
|
25
28
|
removeAriaHidden: string;
|
|
29
|
+
removeLimitWidth: string;
|
|
30
|
+
removeExact: string;
|
|
31
|
+
useCloseButtonOutsideInstead: string;
|
|
32
|
+
useModelValueInsteadChecked: string;
|
|
33
|
+
useModelValueInsteadValue: string;
|
|
26
34
|
};
|
|
27
35
|
};
|
|
28
36
|
create(context: import("eslint").Rule.RuleContext): any;
|
|
@@ -16,18 +16,59 @@ const rule = {
|
|
|
16
16
|
messages: {
|
|
17
17
|
outdatedVueLibrary: 'Installed @nextcloud/vue library is outdated and does not support all reported errors. Install latest compatible version',
|
|
18
18
|
deprecatedDist: 'Import from "@nextcloud/vue/dist" is deprecated',
|
|
19
|
+
deprecatedMixin: 'Mixins are no longer recommended by Vue. Consider using available alternatives',
|
|
20
|
+
deprecatedNcSettingsInputText: 'NcSettingsInputText is deprecated. Consider using available alternatives',
|
|
21
|
+
deprecatedTooltip: 'Tooltip directive is deprecated. use native title attribute or NcPopover instead',
|
|
19
22
|
},
|
|
20
23
|
},
|
|
21
24
|
create(context) {
|
|
22
25
|
const versionSatisfies = createLibVersionValidator(context);
|
|
23
|
-
const
|
|
26
|
+
const isVersionValidForDist = versionSatisfies('8.23.0');
|
|
24
27
|
const oldPattern = '@nextcloud/vue/dist/([^/]+)/([^/.]+)';
|
|
28
|
+
const mixinPattern = '@nextcloud/vue/mixins/([^/.]+)';
|
|
29
|
+
const isVersionValidForTooltip = versionSatisfies('8.25.0');
|
|
30
|
+
const tooltipPattern = '@nextcloud/vue/directives/Tooltip';
|
|
31
|
+
const isVersionValidForNcSettingsInputText = versionSatisfies('8.31.0');
|
|
32
|
+
const patternForNcSettingsInputText = '@nextcloud/vue/components/NcSettingsInputText';
|
|
25
33
|
return {
|
|
26
34
|
ImportDeclaration: function (node) {
|
|
27
35
|
const importPath = node.source.value;
|
|
36
|
+
const matchForNcSettingsInputText = importPath.match(new RegExp(patternForNcSettingsInputText));
|
|
37
|
+
if (matchForNcSettingsInputText) {
|
|
38
|
+
if (!isVersionValidForNcSettingsInputText) {
|
|
39
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
context.report({
|
|
43
|
+
node,
|
|
44
|
+
messageId: 'deprecatedNcSettingsInputText',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const mixinMatch = importPath.match(new RegExp(mixinPattern, 'i'));
|
|
48
|
+
if (mixinMatch) {
|
|
49
|
+
if (!isVersionValidForDist) {
|
|
50
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
context.report({
|
|
54
|
+
node,
|
|
55
|
+
messageId: 'deprecatedMixin',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const tooltipMatch = importPath.match(new RegExp(tooltipPattern));
|
|
59
|
+
if (tooltipMatch) {
|
|
60
|
+
if (!isVersionValidForTooltip) {
|
|
61
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
context.report({
|
|
65
|
+
node,
|
|
66
|
+
messageId: 'deprecatedTooltip',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
28
69
|
const match = importPath.match(new RegExp(oldPattern));
|
|
29
70
|
if (match) {
|
|
30
|
-
if (!
|
|
71
|
+
if (!isVersionValidForDist) {
|
|
31
72
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
32
73
|
return;
|
|
33
74
|
}
|
|
@@ -19,13 +19,21 @@ declare const _default: {
|
|
|
19
19
|
useVerboseStatusInstead: string;
|
|
20
20
|
useNoPlaceholderInstead: string;
|
|
21
21
|
useFormatInstead: string;
|
|
22
|
+
useLocaleInstead: string;
|
|
22
23
|
useTypeDateRangeInstead: string;
|
|
23
24
|
useNoCloseInstead: string;
|
|
25
|
+
useNoCloseOnClickOutsideInstead: string;
|
|
24
26
|
useDisableSwipeForModalInstead: string;
|
|
25
27
|
useNoFocusTrapInstead: string;
|
|
26
28
|
useKeepOpenInstead: string;
|
|
27
29
|
useNcSelectUsersInstead: string;
|
|
30
|
+
useArrowEndInstead: string;
|
|
28
31
|
removeAriaHidden: string;
|
|
32
|
+
removeLimitWidth: string;
|
|
33
|
+
removeExact: string;
|
|
34
|
+
useCloseButtonOutsideInstead: string;
|
|
35
|
+
useModelValueInsteadChecked: string;
|
|
36
|
+
useModelValueInsteadValue: string;
|
|
29
37
|
};
|
|
30
38
|
};
|
|
31
39
|
create(context: Rule.RuleContext): any;
|
|
@@ -16,18 +16,28 @@ export default {
|
|
|
16
16
|
useVerboseStatusInstead: 'Using `show-user-status-compact` is deprecated - use `verbose-status` instead',
|
|
17
17
|
useNoPlaceholderInstead: 'Using `allow-placeholder` is deprecated - use `no-placeholder` instead',
|
|
18
18
|
useFormatInstead: 'Using `formatter` is deprecated - use `format` instead',
|
|
19
|
+
useLocaleInstead: 'Using `lang` is deprecated - use `locale` instead',
|
|
19
20
|
useTypeDateRangeInstead: 'Using `range` is deprecated - use `type` with `date-range` or `datetime-range` instead',
|
|
20
21
|
useNoCloseInstead: 'Using `can-close` is deprecated - use `no-close` instead',
|
|
22
|
+
useNoCloseOnClickOutsideInstead: 'Using `close-on-click-outside` is deprecated - use `no-close-on-click-outside` instead',
|
|
21
23
|
useDisableSwipeForModalInstead: 'Using `enable-swipe` is deprecated - use `disable-swipe` instead',
|
|
22
24
|
useNoFocusTrapInstead: 'Using `focus-trap` is deprecated - use `no-focus-trap` instead',
|
|
23
25
|
useKeepOpenInstead: 'Using `close-on-select` is deprecated - use `keep-open` instead',
|
|
24
26
|
useNcSelectUsersInstead: 'Using `user-select` is deprecated - use `NcSelectUsers` component instead',
|
|
27
|
+
useArrowEndInstead: 'Using `arrow-right` is deprecated - use `arrow-end` instead',
|
|
25
28
|
removeAriaHidden: 'Using `aria-hidden` is deprecated - remove prop from components, otherwise root element will inherit incorrect attribute.',
|
|
29
|
+
removeLimitWidth: 'Using `limit-width` is deprecated - remove prop from components, otherwise root element will inherit incorrect attribute.',
|
|
30
|
+
removeExact: 'Using `exact` is deprecated - consult Vue Router documentation for alternatives.',
|
|
31
|
+
useCloseButtonOutsideInstead: 'Using `close-button-contained` is deprecated - use `close-button-outside` instead',
|
|
32
|
+
useModelValueInsteadChecked: 'Using `checked` is deprecated - use `model-value` or `v-model` instead',
|
|
33
|
+
useModelValueInsteadValue: 'Using `value` is deprecated - use `model-value` or `v-model` instead',
|
|
26
34
|
},
|
|
27
35
|
},
|
|
28
36
|
create(context) {
|
|
29
37
|
const versionSatisfies = createLibVersionValidator(context);
|
|
38
|
+
const isVue3Valid = versionSatisfies('9.0.0'); // #6651
|
|
30
39
|
const isAriaHiddenValid = versionSatisfies('8.2.0'); // #4835
|
|
40
|
+
const isModelValueValid = versionSatisfies('8.20.0'); // #6172
|
|
31
41
|
const isDisableSwipeValid = versionSatisfies('8.23.0'); // #6452
|
|
32
42
|
const isVariantTypeValid = versionSatisfies('8.24.0'); // #6472
|
|
33
43
|
const isDefaultBooleanFalseValid = versionSatisfies('8.24.0'); // #6656
|
|
@@ -35,6 +45,8 @@ export default {
|
|
|
35
45
|
const isNcSelectKeepOpenValid = versionSatisfies('8.25.0'); // #6791
|
|
36
46
|
const isNcPopoverNoFocusTrapValid = versionSatisfies('8.26.0'); // #6808
|
|
37
47
|
const isNcSelectUsersValid = versionSatisfies('8.27.1'); // #7032
|
|
48
|
+
const isNcTextFieldArrowEndValid = versionSatisfies('8.28.0'); // #7002
|
|
49
|
+
const isCloseButtonOutsideValid = versionSatisfies('8.32.0'); // #7553
|
|
38
50
|
const legacyTypes = ['primary', 'error', 'warning', 'success', 'secondary', 'tertiary', 'tertiary-no-background'];
|
|
39
51
|
return vueUtils.defineTemplateBodyVisitor(context, {
|
|
40
52
|
'VElement VAttribute:has(VIdentifier[name="type"])': function (node) {
|
|
@@ -165,6 +177,16 @@ export default {
|
|
|
165
177
|
messageId: 'useFormatInstead',
|
|
166
178
|
});
|
|
167
179
|
},
|
|
180
|
+
'VElement[name="ncdatetimepicker"] VAttribute:has(VIdentifier[name="lang"])': function (node) {
|
|
181
|
+
if (!isVue3Valid) {
|
|
182
|
+
// Do not throw for v8.X.X
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
context.report({
|
|
186
|
+
node,
|
|
187
|
+
messageId: 'useLocaleInstead',
|
|
188
|
+
});
|
|
189
|
+
},
|
|
168
190
|
'VElement[name="ncdatetimepicker"] VAttribute:has(VIdentifier[name="range"])': function (node) {
|
|
169
191
|
if (!isDateTimePickerFormatValid) {
|
|
170
192
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
@@ -191,6 +213,16 @@ export default {
|
|
|
191
213
|
messageId: 'useNoCloseInstead',
|
|
192
214
|
});
|
|
193
215
|
},
|
|
216
|
+
'VElement[name="ncpopover"] VAttribute:has(VIdentifier[name="close-on-click-outside"])': function (node) {
|
|
217
|
+
if (!isVue3Valid) {
|
|
218
|
+
// Do not throw for v8.X.X
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
context.report({
|
|
222
|
+
node,
|
|
223
|
+
messageId: 'useNoCloseOnClickOutsideInstead',
|
|
224
|
+
});
|
|
225
|
+
},
|
|
194
226
|
'VElement[name="ncmodal"] VAttribute:has(VIdentifier[name="enable-swipe"])': function (node) {
|
|
195
227
|
if (!isDisableSwipeValid) {
|
|
196
228
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
@@ -201,6 +233,16 @@ export default {
|
|
|
201
233
|
messageId: 'useDisableSwipeForModalInstead',
|
|
202
234
|
});
|
|
203
235
|
},
|
|
236
|
+
'VElement[name="ncmodal"] VAttribute:has(VIdentifier[name="close-button-contained"])': function (node) {
|
|
237
|
+
if (!isCloseButtonOutsideValid) {
|
|
238
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
context.report({
|
|
242
|
+
node,
|
|
243
|
+
messageId: 'useCloseButtonOutsideInstead',
|
|
244
|
+
});
|
|
245
|
+
},
|
|
204
246
|
'VElement[name="ncpopover"] VAttribute:has(VIdentifier[name="focus-trap"])': function (node) {
|
|
205
247
|
if (!isNcPopoverNoFocusTrapValid) {
|
|
206
248
|
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
@@ -231,6 +273,142 @@ export default {
|
|
|
231
273
|
messageId: 'useNcSelectUsersInstead',
|
|
232
274
|
});
|
|
233
275
|
},
|
|
276
|
+
'VElement VAttribute:has(VIdentifier[name="trailing-button-icon"])': function (node) {
|
|
277
|
+
if (node.parent.parent.name !== 'nctextfield') {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (!isNcTextFieldArrowEndValid) {
|
|
281
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const isLiteral = node.value.type === 'VLiteral' && node.value.value === 'arrowRight';
|
|
285
|
+
const isExpression = node.value.type === 'VExpressionContainer' && node.value.expression?.type === 'ConditionalExpression'
|
|
286
|
+
&& (node.value.expression.consequent.value === 'arrowRight' || node.value.expression.alternate.value === 'arrowRight');
|
|
287
|
+
/**
|
|
288
|
+
* if it is a literal with a deprecated value -> we migrate
|
|
289
|
+
* if it is an expression with a defined deprecated value -> we migrate
|
|
290
|
+
*/
|
|
291
|
+
if (isLiteral || isExpression) {
|
|
292
|
+
context.report({
|
|
293
|
+
node,
|
|
294
|
+
messageId: 'useArrowEndInstead',
|
|
295
|
+
fix: (fixer) => {
|
|
296
|
+
if (node.key.type === 'VIdentifier') {
|
|
297
|
+
return fixer.replaceTextRange(node.value.range, '"arrowEnd"');
|
|
298
|
+
}
|
|
299
|
+
else if (node.key.type === 'VDirectiveKey') {
|
|
300
|
+
return (node.value.expression.consequent.value === 'arrowRight')
|
|
301
|
+
? fixer.replaceTextRange(node.value.expression.consequent.range, '\'arrowEnd\'')
|
|
302
|
+
: fixer.replaceTextRange(node.value.expression.alternate.range, '\'arrowEnd\'');
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
'VElement[name="ncsettingssection"] VAttribute:has(VIdentifier[name="limit-width"])': function (node) {
|
|
309
|
+
// This was deprecated in 8.13.0 (Nextcloud 30+), before first supported version by plugin
|
|
310
|
+
context.report({
|
|
311
|
+
node,
|
|
312
|
+
messageId: 'removeLimitWidth',
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
'VElement VAttribute:has(VIdentifier[name="exact"])': function (node) {
|
|
316
|
+
if (![
|
|
317
|
+
'ncactionrouter',
|
|
318
|
+
'ncappnavigationitem',
|
|
319
|
+
'ncbreadcrumb',
|
|
320
|
+
'ncbutton',
|
|
321
|
+
'nclistitem',
|
|
322
|
+
].includes(node.parent.parent.name)) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (!isVue3Valid) {
|
|
326
|
+
// Do not throw for v8.X.X
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
context.report({
|
|
330
|
+
node,
|
|
331
|
+
messageId: 'removeExact',
|
|
332
|
+
});
|
|
333
|
+
},
|
|
334
|
+
'VElement VAttribute:has(VIdentifier[name="checked"])': function (node) {
|
|
335
|
+
if (![
|
|
336
|
+
'ncactioncheckbox',
|
|
337
|
+
'ncactionradio',
|
|
338
|
+
'nccheckboxradioswitch',
|
|
339
|
+
].includes(node.parent.parent.name)) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (!isModelValueValid) {
|
|
343
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
context.report({
|
|
347
|
+
node,
|
|
348
|
+
messageId: 'useModelValueInsteadChecked',
|
|
349
|
+
fix: (fixer) => {
|
|
350
|
+
if (node.key.type === 'VIdentifier') {
|
|
351
|
+
return fixer.replaceTextRange(node.key.range, 'model-value');
|
|
352
|
+
}
|
|
353
|
+
else if (node.key.type === 'VDirectiveKey') {
|
|
354
|
+
if (node.key.name.name === 'model') {
|
|
355
|
+
return fixer.replaceTextRange(node.key.range, 'v-model');
|
|
356
|
+
}
|
|
357
|
+
else if (node.key.modifiers.some((m) => m.name === 'sync')) {
|
|
358
|
+
return fixer.replaceTextRange(node.key.range, 'v-model');
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
return fixer.replaceTextRange(node.key.argument.range, 'model-value');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
},
|
|
367
|
+
'VElement VAttribute:has(VIdentifier[name="value"])': function (node) {
|
|
368
|
+
if (![
|
|
369
|
+
'ncactioninput',
|
|
370
|
+
'ncactiontexteditable',
|
|
371
|
+
'nccolorpicker',
|
|
372
|
+
'ncdatetimepicker',
|
|
373
|
+
'ncdatetimepickernative',
|
|
374
|
+
'ncinputfield',
|
|
375
|
+
'nctextfield',
|
|
376
|
+
'ncpasswordfield',
|
|
377
|
+
'ncrichcontenteditable',
|
|
378
|
+
'ncselecttags',
|
|
379
|
+
'ncselect',
|
|
380
|
+
'ncsettingsinputtext',
|
|
381
|
+
'ncsettingsselectgroup',
|
|
382
|
+
'nctextarea',
|
|
383
|
+
'nctimezonepicker',
|
|
384
|
+
].includes(node.parent.parent.name)) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (!isModelValueValid) {
|
|
388
|
+
context.report({ node, messageId: 'outdatedVueLibrary' });
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
context.report({
|
|
392
|
+
node,
|
|
393
|
+
messageId: 'useModelValueInsteadValue',
|
|
394
|
+
fix: (fixer) => {
|
|
395
|
+
if (node.key.type === 'VIdentifier') {
|
|
396
|
+
return fixer.replaceTextRange(node.key.range, 'model-value');
|
|
397
|
+
}
|
|
398
|
+
else if (node.key.type === 'VDirectiveKey') {
|
|
399
|
+
if (node.key.name.name === 'model') {
|
|
400
|
+
return fixer.replaceTextRange(node.key.range, 'v-model');
|
|
401
|
+
}
|
|
402
|
+
else if (node.key.modifiers.some((m) => m.name === 'sync')) {
|
|
403
|
+
return fixer.replaceTextRange(node.key.range, 'v-model');
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
return fixer.replaceTextRange(node.key.argument.range, 'model-value');
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
},
|
|
234
412
|
});
|
|
235
413
|
},
|
|
236
414
|
};
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Check if a given path exists and is a file
|
|
3
|
-
*
|
|
4
|
-
* @param filePath The path
|
|
5
|
-
*/
|
|
6
|
-
export declare function isFile(filePath: string): boolean;
|
|
7
|
-
/**
|
|
8
|
-
* Find the path of nearest `package.json` relative to given path
|
|
9
|
-
*
|
|
10
|
-
* @param currentPath Path to lookup
|
|
11
|
-
* @return Either the full path where `package.json` is located or `undefined` if no found
|
|
12
|
-
*/
|
|
13
|
-
export declare function findPackageJsonDir(currentPath: string): string | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* Make sure that versions like '25' can be handled by semver
|
|
16
|
-
*
|
|
17
|
-
* @param version The pure version string
|
|
18
|
-
* @return Sanitized version string
|
|
19
|
-
*/
|
|
20
|
-
export declare function sanitizeTargetVersion(version: string): string;
|
|
21
1
|
/**
|
|
22
2
|
* Create a callback that takes a version number and checks if the version
|
|
23
3
|
* is valid compared to configured version / detected version.
|
|
@@ -25,9 +5,14 @@ export declare function sanitizeTargetVersion(version: string): string;
|
|
|
25
5
|
* @param options Options
|
|
26
6
|
* @param options.cwd The current working directory
|
|
27
7
|
* @param options.physicalFilename The real filename where ESLint is linting currently
|
|
8
|
+
* @param importResolve Optional custom import resolver function (for testing purposes)
|
|
28
9
|
* @return Function validator, return a boolean whether current version satisfies minimal required for the rule
|
|
29
10
|
*/
|
|
30
11
|
export declare function createLibVersionValidator({ cwd, physicalFilename }: {
|
|
31
12
|
cwd: any;
|
|
32
13
|
physicalFilename: any;
|
|
33
|
-
}): ((version: string) => boolean);
|
|
14
|
+
}, importResolve?: (specifier: string, parent?: string | import("url").URL) => string): ((version: string) => boolean);
|
|
15
|
+
/**
|
|
16
|
+
* Clear the module cache
|
|
17
|
+
*/
|
|
18
|
+
export declare function clearCache(): void;
|
|
@@ -2,56 +2,14 @@
|
|
|
2
2
|
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
|
3
3
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
8
|
+
import { gte } from 'semver';
|
|
8
9
|
/**
|
|
9
10
|
* Cached map of paths: Reco <path_to_package.json, validator>
|
|
10
11
|
*/
|
|
11
|
-
const cachedMap =
|
|
12
|
-
/**
|
|
13
|
-
* Check if a given path exists and is a file
|
|
14
|
-
*
|
|
15
|
-
* @param filePath The path
|
|
16
|
-
*/
|
|
17
|
-
export function isFile(filePath) {
|
|
18
|
-
const stats = lstatSync(filePath, { throwIfNoEntry: false });
|
|
19
|
-
return stats !== undefined && stats.isFile();
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Find the path of nearest `package.json` relative to given path
|
|
23
|
-
*
|
|
24
|
-
* @param currentPath Path to lookup
|
|
25
|
-
* @return Either the full path where `package.json` is located or `undefined` if no found
|
|
26
|
-
*/
|
|
27
|
-
export function findPackageJsonDir(currentPath) {
|
|
28
|
-
for (const cachedDirPath of Object.keys(cachedMap)) {
|
|
29
|
-
if (currentPath.startsWith(cachedDirPath)) {
|
|
30
|
-
return cachedDirPath;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
while (currentPath && currentPath !== sep) {
|
|
34
|
-
if (isFile(join(currentPath, 'package.json'))) {
|
|
35
|
-
return currentPath;
|
|
36
|
-
}
|
|
37
|
-
currentPath = resolve(currentPath, '..');
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Make sure that versions like '25' can be handled by semver
|
|
43
|
-
*
|
|
44
|
-
* @param version The pure version string
|
|
45
|
-
* @return Sanitized version string
|
|
46
|
-
*/
|
|
47
|
-
export function sanitizeTargetVersion(version) {
|
|
48
|
-
const sanitizedVersion = minVersion(version)?.version;
|
|
49
|
-
// now version should look like '23.0.0'
|
|
50
|
-
if (!valid(sanitizedVersion)) {
|
|
51
|
-
throw Error(`[@nextcloud/eslint-plugin] Invalid target version ${version} found`);
|
|
52
|
-
}
|
|
53
|
-
return sanitizedVersion;
|
|
54
|
-
}
|
|
12
|
+
const cachedMap = new Map();
|
|
55
13
|
/**
|
|
56
14
|
* Create a callback that takes a version number and checks if the version
|
|
57
15
|
* is valid compared to configured version / detected version.
|
|
@@ -59,36 +17,33 @@ export function sanitizeTargetVersion(version) {
|
|
|
59
17
|
* @param options Options
|
|
60
18
|
* @param options.cwd The current working directory
|
|
61
19
|
* @param options.physicalFilename The real filename where ESLint is linting currently
|
|
20
|
+
* @param importResolve Optional custom import resolver function (for testing purposes)
|
|
62
21
|
* @return Function validator, return a boolean whether current version satisfies minimal required for the rule
|
|
63
22
|
*/
|
|
64
|
-
export function createLibVersionValidator({ cwd, physicalFilename }) {
|
|
65
|
-
// Try to find package.json
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return () => false;
|
|
23
|
+
export function createLibVersionValidator({ cwd, physicalFilename }, importResolve = import.meta.resolve) {
|
|
24
|
+
// Try to find package.json of the nextcloud-vue package
|
|
25
|
+
const sourceFile = isAbsolute(physicalFilename)
|
|
26
|
+
? resolve(physicalFilename)
|
|
27
|
+
: resolve(cwd, physicalFilename);
|
|
28
|
+
let packageJsonDir;
|
|
29
|
+
try {
|
|
30
|
+
const modulePath = fileURLToPath(importResolve('@nextcloud/vue', pathToFileURL(sourceFile)));
|
|
31
|
+
const idx = modulePath.lastIndexOf('/dist/');
|
|
32
|
+
packageJsonDir = modulePath.substring(0, idx);
|
|
75
33
|
}
|
|
76
|
-
|
|
77
|
-
return cachedMap[packageJsonDir];
|
|
78
|
-
}
|
|
79
|
-
const json = JSON.parse(readFileSync(join(packageJsonDir, 'package.json'), 'utf-8'));
|
|
80
|
-
const libVersions = [
|
|
81
|
-
json?.dependencies?.['@nextcloud/vue'],
|
|
82
|
-
json?.devDependencies?.['@nextcloud/vue'],
|
|
83
|
-
json?.peerDependencies?.['@nextcloud/vue'],
|
|
84
|
-
]
|
|
85
|
-
.filter((version) => typeof version === 'string' && !!version)
|
|
86
|
-
.map(sanitizeTargetVersion)
|
|
87
|
-
.sort((a, b) => gte(a, b) ? 1 : -1);
|
|
88
|
-
if (!libVersions.length) {
|
|
89
|
-
// Skip the rule
|
|
34
|
+
catch {
|
|
90
35
|
return () => false;
|
|
91
36
|
}
|
|
92
|
-
|
|
93
|
-
|
|
37
|
+
if (!cachedMap[packageJsonDir]) {
|
|
38
|
+
const json = JSON.parse(readFileSync(join(packageJsonDir, 'package.json'), 'utf-8'));
|
|
39
|
+
const libVersion = json.version;
|
|
40
|
+
cachedMap[packageJsonDir] = (version) => gte(libVersion, version);
|
|
41
|
+
}
|
|
42
|
+
return cachedMap[packageJsonDir];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Clear the module cache
|
|
46
|
+
*/
|
|
47
|
+
export function clearCache() {
|
|
48
|
+
cachedMap.clear();
|
|
94
49
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -9,16 +9,4 @@ import type { Linter } from 'eslint';
|
|
|
9
9
|
* @param configs The configs to restrict
|
|
10
10
|
* @param files The glob pattern to assign
|
|
11
11
|
*/
|
|
12
|
-
export declare function restrictConfigFiles(configs: Linter.Config[], files: string[]):
|
|
13
|
-
files: (string | string[])[];
|
|
14
|
-
name?: string;
|
|
15
|
-
basePath?: string;
|
|
16
|
-
ignores?: string[];
|
|
17
|
-
language?: string;
|
|
18
|
-
languageOptions?: Linter.LanguageOptions;
|
|
19
|
-
linterOptions?: Linter.LinterOptions;
|
|
20
|
-
processor?: string | Linter.Processor;
|
|
21
|
-
plugins?: Record<string, import("eslint").ESLint.Plugin>;
|
|
22
|
-
rules?: Partial<Linter.RulesRecord>;
|
|
23
|
-
settings?: Record<string, unknown>;
|
|
24
|
-
}[];
|
|
12
|
+
export declare function restrictConfigFiles(configs: Linter.Config[], files: string[]): Linter.Config[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextcloud/eslint-config",
|
|
3
|
-
"version": "9.0.0-rc.
|
|
3
|
+
"version": "9.0.0-rc.6",
|
|
4
4
|
"description": "Eslint shared config for nextcloud apps and libraries",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -37,31 +37,31 @@
|
|
|
37
37
|
"build": "npm run build:cleanup && npm run build:source",
|
|
38
38
|
"build:cleanup": "tsc --build --clean",
|
|
39
39
|
"build:source": "tsc",
|
|
40
|
-
"lint": "
|
|
41
|
-
"lint:fix": "
|
|
40
|
+
"lint": "eslint --flag unstable_native_nodejs_ts_config",
|
|
41
|
+
"lint:fix": "eslint --flag unstable_native_nodejs_ts_config --fix",
|
|
42
42
|
"prerelease:format-changelog": "node build/format-changelog.mjs",
|
|
43
43
|
"test": "vitest run"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@eslint/json": "^0.
|
|
47
|
-
"@stylistic/eslint-plugin": "^5.
|
|
46
|
+
"@eslint/json": "^0.14.0",
|
|
47
|
+
"@stylistic/eslint-plugin": "^5.5.0",
|
|
48
48
|
"eslint-config-flat-gitignore": "^2.1.0",
|
|
49
49
|
"eslint-plugin-antfu": "^3.1.1",
|
|
50
|
-
"eslint-plugin-jsdoc": "^
|
|
51
|
-
"eslint-plugin-perfectionist": "^4.15.
|
|
52
|
-
"eslint-plugin-vue": "^10.
|
|
53
|
-
"fast-xml-parser": "^5.2
|
|
54
|
-
"globals": "^16.
|
|
55
|
-
"semver": "^7.7.
|
|
50
|
+
"eslint-plugin-jsdoc": "^61.2.1",
|
|
51
|
+
"eslint-plugin-perfectionist": "^4.15.1",
|
|
52
|
+
"eslint-plugin-vue": "^10.5.1",
|
|
53
|
+
"fast-xml-parser": "^5.3.2",
|
|
54
|
+
"globals": "^16.5.0",
|
|
55
|
+
"semver": "^7.7.3",
|
|
56
56
|
"sort-package-json": "^3.4.0",
|
|
57
|
-
"typescript-eslint": "^8.
|
|
57
|
+
"typescript-eslint": "^8.46.4"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@types/node": "^24.1
|
|
61
|
-
"@types/semver": "^7.7.
|
|
62
|
-
"eslint": "^9.
|
|
63
|
-
"memfs": "^4.
|
|
64
|
-
"vitest": "^
|
|
60
|
+
"@types/node": "^24.10.1",
|
|
61
|
+
"@types/semver": "^7.7.1",
|
|
62
|
+
"eslint": "^9.39.1",
|
|
63
|
+
"memfs": "^4.51.0",
|
|
64
|
+
"vitest": "^4.0.13"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"eslint": ">=9"
|
|
@@ -73,12 +73,12 @@
|
|
|
73
73
|
"packageManager": [
|
|
74
74
|
{
|
|
75
75
|
"name": "npm",
|
|
76
|
-
"version": "^
|
|
76
|
+
"version": "^11.3.0"
|
|
77
77
|
}
|
|
78
78
|
],
|
|
79
79
|
"runtime": {
|
|
80
80
|
"name": "node",
|
|
81
|
-
"version": "^
|
|
81
|
+
"version": "^24.3.0"
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
}
|