@o3r/eslint-plugin 10.0.0-next.9 → 11.0.0-next.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.
- package/README.md +1 -1
- package/package.json +44 -29
- package/src/index.d.ts +1 -0
- package/src/index.js +34 -3
- package/src/public_api.d.ts +1 -0
- package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.d.ts +15 -0
- package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.js +123 -0
- package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.d.ts +40 -0
- package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.js +96 -0
- package/src/rules/json/utils.d.ts +39 -0
- package/src/rules/json/utils.js +60 -0
- package/src/rules/template/no-inner-html/no-inner-html.d.ts +5 -0
- package/src/rules/template/no-inner-html/no-inner-html.js +57 -0
- package/src/rules/template/template-async-number-limitation/template-async-number-limitation.d.ts +7 -0
- package/src/rules/{template-async-number-limitation → template/template-async-number-limitation}/template-async-number-limitation.js +4 -5
- package/src/rules/template/utils.d.ts +38 -0
- package/src/rules/{template-utils.js → template/utils.js} +0 -3
- package/src/rules/typescript/matching-configuration-name/matching-configuration-name.d.ts +5 -0
- package/src/rules/typescript/matching-configuration-name/matching-configuration-name.js +70 -0
- package/src/rules/typescript/no-folder-import-for-module/no-folder-import-for-module.d.ts +4 -0
- package/src/rules/{no-folder-import-for-module → typescript/no-folder-import-for-module}/no-folder-import-for-module.js +1 -1
- package/src/rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property.d.ts +5 -0
- package/src/rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property.js +71 -0
- package/src/rules/typescript/o3r-categories-tags/o3r-categories-tags.d.ts +7 -0
- package/src/rules/typescript/o3r-categories-tags/o3r-categories-tags.js +137 -0
- package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.d.ts +16 -0
- package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.js +255 -0
- package/src/rules/utils.d.ts +22 -0
- package/src/rules/utils.js +34 -1
- package/src/rules/yaml/utils.d.ts +22 -0
- package/src/rules/yaml/utils.js +42 -0
- package/src/rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize.d.ts +12 -0
- package/src/rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize.js +122 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/schematics/ng-add/schema.json +0 -18
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.name = void 0;
|
|
4
|
-
const template_utils_1 = require("../template-utils");
|
|
5
4
|
const utils_1 = require("../utils");
|
|
5
|
+
const utils_2 = require("../../utils");
|
|
6
6
|
/** Rule Name */
|
|
7
7
|
exports.name = 'template-async-number-limitation';
|
|
8
8
|
const defaultOptions = [{
|
|
9
9
|
maximumAsyncOnTag: 5
|
|
10
10
|
}];
|
|
11
|
-
exports.default = (0,
|
|
11
|
+
exports.default = (0, utils_2.createRule)({
|
|
12
12
|
name: exports.name,
|
|
13
13
|
meta: {
|
|
14
14
|
type: 'problem',
|
|
@@ -35,9 +35,8 @@ exports.default = (0, utils_1.createRule)({
|
|
|
35
35
|
fixable: undefined
|
|
36
36
|
},
|
|
37
37
|
defaultOptions,
|
|
38
|
-
create: (context) => {
|
|
39
|
-
const parserServices = (0,
|
|
40
|
-
const options = context.options[0] || defaultOptions[0];
|
|
38
|
+
create: (context, [options]) => {
|
|
39
|
+
const parserServices = (0, utils_1.getTemplateParserServices)(context);
|
|
41
40
|
const asyncRegExp = /\| *async\b/g;
|
|
42
41
|
return {
|
|
43
42
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ParserServices, TSESLint } from '@typescript-eslint/experimental-utils';
|
|
2
|
+
/** Position in source code */
|
|
3
|
+
interface SourceSpan {
|
|
4
|
+
/** starting position */
|
|
5
|
+
start: {
|
|
6
|
+
line: number;
|
|
7
|
+
col: any;
|
|
8
|
+
};
|
|
9
|
+
/** ending position */
|
|
10
|
+
end: {
|
|
11
|
+
line: number;
|
|
12
|
+
col: any;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Basic interface for the Parser Services object provided by @angular-eslint/template-parser */
|
|
16
|
+
interface TemplateParserServices extends ParserServices {
|
|
17
|
+
/** Set body visitor rule runner */
|
|
18
|
+
convertElementSourceSpanToLoc: (listenerObj: any) => any;
|
|
19
|
+
/** Determine the linter notification position based on the node */
|
|
20
|
+
convertNodeSourceSpanToLoc: (sourceSpan: SourceSpan) => any;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Determine if @angular-eslint/template-parser is used
|
|
24
|
+
* @param parserServices Parser services object
|
|
25
|
+
*/
|
|
26
|
+
export declare function isTemplateParserServices(parserServices: any): parserServices is TemplateParserServices;
|
|
27
|
+
/**
|
|
28
|
+
* Retrieve the template parser services object or throw if the invalid parser is used
|
|
29
|
+
* @param context Rule context
|
|
30
|
+
*/
|
|
31
|
+
export declare function getTemplateParserServices(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): TemplateParserServices;
|
|
32
|
+
/**
|
|
33
|
+
* Utility for rule authors to ensure that their rule is correctly being used with @angular-eslint/template-parser
|
|
34
|
+
* If @angular-eslint/template-parser is not the configured parser when the function is invoked it will throw
|
|
35
|
+
* @param context
|
|
36
|
+
*/
|
|
37
|
+
export declare function ensureTemplateParser(context: Readonly<TSESLint.RuleContext<string, readonly unknown[]>>): void;
|
|
38
|
+
export {};
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ensureTemplateParser = exports.getTemplateParserServices = exports.isTemplateParserServices = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Determine if @angular-eslint/template-parser is used
|
|
6
|
-
*
|
|
7
6
|
* @param parserServices Parser services object
|
|
8
7
|
*/
|
|
9
8
|
function isTemplateParserServices(parserServices) {
|
|
@@ -13,7 +12,6 @@ function isTemplateParserServices(parserServices) {
|
|
|
13
12
|
exports.isTemplateParserServices = isTemplateParserServices;
|
|
14
13
|
/**
|
|
15
14
|
* Retrieve the template parser services object or throw if the invalid parser is used
|
|
16
|
-
*
|
|
17
15
|
* @param context Rule context
|
|
18
16
|
*/
|
|
19
17
|
function getTemplateParserServices(context) {
|
|
@@ -31,7 +29,6 @@ exports.getTemplateParserServices = getTemplateParserServices;
|
|
|
31
29
|
/**
|
|
32
30
|
* Utility for rule authors to ensure that their rule is correctly being used with @angular-eslint/template-parser
|
|
33
31
|
* If @angular-eslint/template-parser is not the configured parser when the function is invoked it will throw
|
|
34
|
-
*
|
|
35
32
|
* @param context
|
|
36
33
|
*/
|
|
37
34
|
function ensureTemplateParser(context) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
|
2
|
+
declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"suggestion" | "error", never[], {
|
|
3
|
+
CallExpression: (node: TSESTree.CallExpression) => void;
|
|
4
|
+
}>;
|
|
5
|
+
export default _default;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const nameDeterminingFunctionNames = ['computeItemIdentifier', 'computeConfigurationName'];
|
|
6
|
+
exports.default = (0, utils_1.createRule)({
|
|
7
|
+
name: 'matching-configuration-name',
|
|
8
|
+
meta: {
|
|
9
|
+
hasSuggestions: true,
|
|
10
|
+
fixable: 'code',
|
|
11
|
+
type: 'problem',
|
|
12
|
+
docs: {
|
|
13
|
+
// eslint-disable-next-line max-len
|
|
14
|
+
description: 'Ensures that the configuration interface name matches the first parameter of `computeItemIdentifier` (or `computeConfigurationName`) used beside the configuration interface to expose its ID (as generated by the configuration module).',
|
|
15
|
+
recommended: 'error'
|
|
16
|
+
},
|
|
17
|
+
schema: [],
|
|
18
|
+
messages: {
|
|
19
|
+
error: '{{currentValue}} does not match: {{possibleValues}}',
|
|
20
|
+
suggestion: 'Replace {{currentValue}} by {{recommendedValue}}'
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create: (context) => {
|
|
25
|
+
return {
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
27
|
+
CallExpression: (node) => {
|
|
28
|
+
if (node.callee.type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
|
|
29
|
+
|| !nameDeterminingFunctionNames.includes(node.callee.name)
|
|
30
|
+
|| !node.arguments.length
|
|
31
|
+
|| node.arguments[0].type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.Literal
|
|
32
|
+
|| typeof node.arguments[0].value !== 'string') {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const sourceCode = context.getSourceCode();
|
|
36
|
+
const interfaceNames = sourceCode.ast.body
|
|
37
|
+
.filter((statement) => statement.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.ExportNamedDeclaration
|
|
38
|
+
&& statement.declaration?.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
|
|
39
|
+
&& (statement.declaration.extends || []).some((heritageClause) => heritageClause.expression.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
|
|
40
|
+
&& heritageClause.expression.name === 'Configuration'))
|
|
41
|
+
.map((statement) => statement.declaration.id.name);
|
|
42
|
+
const fnArgInterfaceName = node.arguments[0].value;
|
|
43
|
+
if (interfaceNames.length && !interfaceNames.includes(fnArgInterfaceName)) {
|
|
44
|
+
return context.report({
|
|
45
|
+
node: node.arguments[0],
|
|
46
|
+
loc: node.arguments[0].loc,
|
|
47
|
+
messageId: 'error',
|
|
48
|
+
data: {
|
|
49
|
+
currentValue: fnArgInterfaceName,
|
|
50
|
+
possibleValues: interfaceNames.join(', ')
|
|
51
|
+
},
|
|
52
|
+
fix: (fixer) => {
|
|
53
|
+
return fixer.replaceText(node.arguments[0], `'${interfaceNames[0]}'`);
|
|
54
|
+
},
|
|
55
|
+
suggest: interfaceNames.map((interfaceName) => ({
|
|
56
|
+
messageId: 'suggestion',
|
|
57
|
+
data: {
|
|
58
|
+
currentValue: fnArgInterfaceName,
|
|
59
|
+
recommendedValue: interfaceName
|
|
60
|
+
},
|
|
61
|
+
fix: (fixer) => {
|
|
62
|
+
return fixer.replaceText(node.arguments[0], `'${interfaceName}'`);
|
|
63
|
+
}
|
|
64
|
+
}))
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const fs = require("node:fs");
|
|
4
4
|
const path = require("node:path");
|
|
5
|
-
const utils_1 = require("
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
6
|
exports.default = (0, utils_1.createRule)({
|
|
7
7
|
name: 'no-folder-import-for-module',
|
|
8
8
|
meta: {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export interface NoMultipleTypeConfigurationPropertyOption {
|
|
2
|
+
supportedInterfaceNames?: string[];
|
|
3
|
+
}
|
|
4
|
+
declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"suggestion" | "error", [Required<NoMultipleTypeConfigurationPropertyOption>, ...any[]], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
|
|
5
|
+
export default _default;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const separatorRegExp = /\s*[|&]\s*/;
|
|
6
|
+
exports.default = (0, utils_1.createRule)({
|
|
7
|
+
name: 'no-multiple-type-configuration-property',
|
|
8
|
+
meta: {
|
|
9
|
+
hasSuggestions: true,
|
|
10
|
+
type: 'problem',
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Ensures that the configuration property does not accept multiple types.',
|
|
13
|
+
recommended: 'error'
|
|
14
|
+
},
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
supportedInterfaceNames: {
|
|
20
|
+
type: 'array',
|
|
21
|
+
items: {
|
|
22
|
+
type: 'string'
|
|
23
|
+
},
|
|
24
|
+
default: utils_1.defaultSupportedInterfaceNames
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
messages: {
|
|
30
|
+
error: 'Configuration cannot be the union of multiple type',
|
|
31
|
+
suggestion: 'Replace {{currentValue}} by {{recommendedValue}}'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
defaultOptions: [{
|
|
35
|
+
supportedInterfaceNames: utils_1.defaultSupportedInterfaceNames
|
|
36
|
+
}],
|
|
37
|
+
create: (context, [options]) => {
|
|
38
|
+
const supportedInterfaceNames = options.supportedInterfaceNames;
|
|
39
|
+
const sourceCode = context.getSourceCode();
|
|
40
|
+
const rule = (node) => {
|
|
41
|
+
const interfaceDeclNode = node.parent?.parent?.parent?.parent;
|
|
42
|
+
if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, supportedInterfaceNames)) {
|
|
43
|
+
return; // Not in a configuration interface
|
|
44
|
+
}
|
|
45
|
+
if (node.types.every((type) => type.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSLiteralType && type.literal.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Literal)
|
|
46
|
+
&& [...(new Set(node.types.map((literalType) => typeof literalType.literal.value)))].length === 1) {
|
|
47
|
+
return; // Only the same literal type
|
|
48
|
+
}
|
|
49
|
+
const text = sourceCode.getText(node);
|
|
50
|
+
context.report({
|
|
51
|
+
messageId: 'error',
|
|
52
|
+
node,
|
|
53
|
+
loc: node.loc,
|
|
54
|
+
suggest: text.split(separatorRegExp).map((type) => ({
|
|
55
|
+
messageId: 'suggestion',
|
|
56
|
+
data: {
|
|
57
|
+
currentValue: text,
|
|
58
|
+
recommendedValue: type
|
|
59
|
+
},
|
|
60
|
+
fix: (fixer) => fixer.replaceTextRange(node.range, type)
|
|
61
|
+
}))
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
66
|
+
TSUnionType: rule,
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
68
|
+
TSIntersectionType: rule
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface O3rCategoriesTagsRuleOption {
|
|
2
|
+
supportedInterfaceNames?: string[];
|
|
3
|
+
globalConfigCategories?: string[];
|
|
4
|
+
}
|
|
5
|
+
type Messages = 'alreadyDefined' | 'undefinedCategory' | 'onlyOneCategoryAllowed' | 'notInConfigurationInterface' | 'suggestReplaceO3rCategory';
|
|
6
|
+
declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<Messages, [O3rCategoriesTagsRuleOption, ...any[]], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("../../utils");
|
|
4
|
+
exports.default = (0, utils_1.createRule)({
|
|
5
|
+
name: 'o3r-categories-tags',
|
|
6
|
+
meta: {
|
|
7
|
+
hasSuggestions: true,
|
|
8
|
+
fixable: 'code',
|
|
9
|
+
type: 'problem',
|
|
10
|
+
docs: {
|
|
11
|
+
description: 'Ensures that @o3rCategories and @o3rCategory are used with correct value',
|
|
12
|
+
recommended: 'error'
|
|
13
|
+
},
|
|
14
|
+
schema: [
|
|
15
|
+
{
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
supportedInterfaceNames: {
|
|
19
|
+
type: 'array',
|
|
20
|
+
items: {
|
|
21
|
+
type: 'string'
|
|
22
|
+
},
|
|
23
|
+
default: utils_1.defaultSupportedInterfaceNames
|
|
24
|
+
},
|
|
25
|
+
globalConfigCategories: {
|
|
26
|
+
type: 'array',
|
|
27
|
+
items: {
|
|
28
|
+
type: 'string'
|
|
29
|
+
},
|
|
30
|
+
default: []
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
messages: {
|
|
36
|
+
alreadyDefined: '{{ currentCategory }} is already defined globally.',
|
|
37
|
+
undefinedCategory: '{{ currentCategory }} is not supported. Supported @o3rCategory: {{ supportedCategories }}.',
|
|
38
|
+
onlyOneCategoryAllowed: '@o3rCategory must be defined only once.',
|
|
39
|
+
notInConfigurationInterface: '@o3rCategory and @o3rCategories can only be used in `Configuration` interface.',
|
|
40
|
+
suggestReplaceO3rCategory: 'Replace {{ currentCategory }} by {{ suggestedCategory }}.'
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
defaultOptions: [{
|
|
44
|
+
supportedInterfaceNames: utils_1.defaultSupportedInterfaceNames,
|
|
45
|
+
globalConfigCategories: []
|
|
46
|
+
}],
|
|
47
|
+
create: (context, [options]) => {
|
|
48
|
+
const globalConfigCategories = new Set(options.globalConfigCategories);
|
|
49
|
+
return {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
51
|
+
TSPropertySignature: (node) => {
|
|
52
|
+
const sourceCode = context.getSourceCode();
|
|
53
|
+
const comment = (0, utils_1.getNodeComment)(node, sourceCode);
|
|
54
|
+
if (!comment || !comment.value.length) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const { loc, value: docText } = comment;
|
|
58
|
+
const categories = Array.from(docText.matchAll(/@o3rCategory (\w+)/g)).map((match) => match[1]);
|
|
59
|
+
if (categories.length < 1) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
else if (categories.length > 1) {
|
|
63
|
+
return context.report({
|
|
64
|
+
messageId: 'onlyOneCategoryAllowed',
|
|
65
|
+
node,
|
|
66
|
+
loc
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const category = categories[0];
|
|
70
|
+
const interfaceDeclNode = node.parent?.parent;
|
|
71
|
+
if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, options.supportedInterfaceNames)) {
|
|
72
|
+
return context.report({
|
|
73
|
+
messageId: 'notInConfigurationInterface',
|
|
74
|
+
node,
|
|
75
|
+
loc
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const interfaceComment = (0, utils_1.getNodeComment)(interfaceDeclNode, sourceCode);
|
|
79
|
+
const supportedO3rCategories = new Set(options.globalConfigCategories);
|
|
80
|
+
Array.from(interfaceComment?.value.matchAll(/@o3rCategories (\w+)/g) || []).forEach((match) => supportedO3rCategories.add(match[1]));
|
|
81
|
+
if (!supportedO3rCategories.has(category)) {
|
|
82
|
+
return context.report({
|
|
83
|
+
messageId: 'undefinedCategory',
|
|
84
|
+
node,
|
|
85
|
+
loc,
|
|
86
|
+
data: {
|
|
87
|
+
currentCategory: category,
|
|
88
|
+
supportedCategories: Array.from(supportedO3rCategories).join(', ')
|
|
89
|
+
},
|
|
90
|
+
suggest: Array.from(supportedO3rCategories).map((suggestedCategory) => ({
|
|
91
|
+
messageId: 'suggestReplaceO3rCategory',
|
|
92
|
+
data: {
|
|
93
|
+
currentCategory: category,
|
|
94
|
+
suggestedCategory: suggestedCategory
|
|
95
|
+
},
|
|
96
|
+
fix: (fixer) => {
|
|
97
|
+
return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(`@o3rCategory ${category}`, `@o3rCategory ${suggestedCategory}`)));
|
|
98
|
+
}
|
|
99
|
+
}))
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
104
|
+
TSInterfaceDeclaration: (node) => {
|
|
105
|
+
const sourceCode = context.getSourceCode();
|
|
106
|
+
const comment = (0, utils_1.getNodeComment)(node, sourceCode);
|
|
107
|
+
if (!comment || !comment.value.length) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const { loc, value: docText } = comment;
|
|
111
|
+
const categories = Array.from(docText.matchAll(/@o3rCategories (\w+)/g)).map((match) => match[1]);
|
|
112
|
+
if (categories.length < 1) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (!(0, utils_1.isExtendingConfiguration)(node, options.supportedInterfaceNames)) {
|
|
116
|
+
return context.report({
|
|
117
|
+
messageId: 'notInConfigurationInterface',
|
|
118
|
+
node,
|
|
119
|
+
loc
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
const alreadyDefined = categories.find((category) => globalConfigCategories.has(category));
|
|
123
|
+
if (alreadyDefined) {
|
|
124
|
+
return context.report({
|
|
125
|
+
messageId: 'alreadyDefined',
|
|
126
|
+
fix: (fixer) => fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(new RegExp(`.*@o3rCategories ${alreadyDefined}.*\n`), ''))),
|
|
127
|
+
data: {
|
|
128
|
+
currentCategory: alreadyDefined
|
|
129
|
+
},
|
|
130
|
+
node,
|
|
131
|
+
loc
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/experimental-utils';
|
|
2
|
+
type O3rWidgetParamType = 'string' | 'number' | 'boolean' | 'string[]' | 'number[]' | 'boolean[]';
|
|
3
|
+
export interface O3rWidgetTagsRuleOption {
|
|
4
|
+
supportedInterfaceNames?: string[];
|
|
5
|
+
widgets: {
|
|
6
|
+
[widgetName: string]: {
|
|
7
|
+
[paramName: string]: {
|
|
8
|
+
type: O3rWidgetParamType;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
type O3rWidgetRuleErrorId = 'notInConfigurationInterface' | 'notSupportedType' | 'notSupportedParamForType' | 'invalidParamValueType' | 'noParamWithoutWidget' | 'onlyOneWidgetAllowed' | 'duplicatedParam' | 'requiredParamMissing' | 'suggestParamMissing' | 'suggestRemoveDuplicatedO3rWidget' | 'suggestRemoveDuplicatedO3rWidgetParam' | 'suggestAddO3rWidgetTag' | 'suggestReplaceO3rWidgetType';
|
|
15
|
+
declare const _default: TSESLint.RuleModule<O3rWidgetRuleErrorId, [Required<O3rWidgetTagsRuleOption>, ...any[]], TSESLint.RuleListener>;
|
|
16
|
+
export default _default;
|