@o3r/eslint-plugin 11.6.0-prerelease.6 → 11.6.0-prerelease.60

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 (33) hide show
  1. package/package.json +31 -31
  2. package/schematics/ng-add/index.d.ts.map +1 -1
  3. package/src/index.js +20 -6
  4. package/src/public_api.d.ts +3 -0
  5. package/src/public_api.js +1 -0
  6. package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.d.ts +3 -2
  7. package/src/rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize.js +60 -60
  8. package/src/rules/json/json-dependency-versions-harmonize/version-harmonize.js +1 -1
  9. package/src/rules/json/utils.js +2 -2
  10. package/src/rules/template/no-inner-html/no-inner-html.d.ts +1 -1
  11. package/src/rules/template/no-inner-html/no-inner-html.js +30 -31
  12. package/src/rules/template/template-async-number-limitation/template-async-number-limitation.d.ts +2 -2
  13. package/src/rules/template/template-async-number-limitation/template-async-number-limitation.js +24 -24
  14. package/src/rules/template/utils.js +3 -3
  15. package/src/rules/typescript/matching-configuration-name/matching-configuration-name.d.ts +1 -1
  16. package/src/rules/typescript/matching-configuration-name/matching-configuration-name.js +40 -40
  17. package/src/rules/typescript/no-folder-import-for-module/no-folder-import-for-module.d.ts +1 -1
  18. package/src/rules/typescript/no-folder-import-for-module/no-folder-import-for-module.js +28 -24
  19. package/src/rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property.d.ts +1 -1
  20. package/src/rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property.js +3 -5
  21. package/src/rules/typescript/o3r-categories-tags/o3r-categories-tags.d.ts +1 -1
  22. package/src/rules/typescript/o3r-categories-tags/o3r-categories-tags.js +82 -82
  23. package/src/rules/typescript/o3r-restriction-key-tags/o3r-restriction-key-tags.d.ts +8 -0
  24. package/src/rules/typescript/o3r-restriction-key-tags/o3r-restriction-key-tags.js +130 -0
  25. package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.d.ts +1 -1
  26. package/src/rules/typescript/o3r-widget-tags/o3r-widget-tags.js +142 -142
  27. package/src/rules/utils.d.ts +1 -1
  28. package/src/rules/utils.js +4 -7
  29. package/src/rules/yaml/utils.js +2 -2
  30. package/src/rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize.d.ts +2 -2
  31. package/src/rules/yaml/yarnrc-package-extensions-harmonize/yarnrc-package-extensions-harmonize.js +19 -14
  32. package/tsconfig.build.tsbuildinfo +1 -0
  33. package/tsconfig.tsbuildinfo +0 -1
@@ -10,8 +10,8 @@ exports.default = (0, utils_2.createRule)({
10
10
  fixable: 'code',
11
11
  type: 'problem',
12
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).'
13
+ description: 'Ensures that the configuration interface name matches the first parameter of `computeItemIdentifier`'
14
+ + ' (or `computeConfigurationName`) used beside the configuration interface to expose its ID (as generated by the configuration module).'
15
15
  },
16
16
  schema: [],
17
17
  messages: {
@@ -21,49 +21,49 @@ exports.default = (0, utils_2.createRule)({
21
21
  },
22
22
  defaultOptions: [],
23
23
  create: (context) => {
24
- return {
25
- // eslint-disable-next-line @typescript-eslint/naming-convention
26
- CallExpression: (node) => {
27
- if (node.callee.type !== utils_1.TSESTree.AST_NODE_TYPES.Identifier
28
- || !nameDeterminingFunctionNames.includes(node.callee.name)
29
- || !node.arguments.length
30
- || node.arguments[0].type !== utils_1.TSESTree.AST_NODE_TYPES.Literal
31
- || typeof node.arguments[0].value !== 'string') {
32
- return;
33
- }
34
- const sourceCode = context.getSourceCode();
35
- const interfaceNames = sourceCode.ast.body
36
- .filter((statement) => statement.type === utils_1.TSESTree.AST_NODE_TYPES.ExportNamedDeclaration
37
- && statement.declaration?.type === utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
38
- && (statement.declaration.extends || []).some((heritageClause) => heritageClause.expression.type === utils_1.TSESTree.AST_NODE_TYPES.Identifier
39
- && heritageClause.expression.name === 'Configuration'))
40
- .map((statement) => statement.declaration.id.name);
41
- const fnArgInterfaceName = node.arguments[0].value;
42
- if (interfaceNames.length && !interfaceNames.includes(fnArgInterfaceName)) {
43
- return context.report({
44
- node: node.arguments[0],
45
- loc: node.arguments[0].loc,
46
- messageId: 'error',
24
+ const rule = (node) => {
25
+ if (node.callee.type !== utils_1.TSESTree.AST_NODE_TYPES.Identifier
26
+ || !nameDeterminingFunctionNames.includes(node.callee.name)
27
+ || node.arguments.length === 0
28
+ || node.arguments[0].type !== utils_1.TSESTree.AST_NODE_TYPES.Literal
29
+ || typeof node.arguments[0].value !== 'string') {
30
+ return;
31
+ }
32
+ const { sourceCode } = context;
33
+ const interfaceNames = sourceCode.ast.body
34
+ .filter((statement) => statement.type === utils_1.TSESTree.AST_NODE_TYPES.ExportNamedDeclaration
35
+ && statement.declaration?.type === utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
36
+ && (statement.declaration.extends || []).some((heritageClause) => heritageClause.expression.type === utils_1.TSESTree.AST_NODE_TYPES.Identifier
37
+ && heritageClause.expression.name === 'Configuration'))
38
+ .map((statement) => statement.declaration.id.name);
39
+ const fnArgInterfaceName = node.arguments[0].value;
40
+ if (interfaceNames.length > 0 && !interfaceNames.includes(fnArgInterfaceName)) {
41
+ return context.report({
42
+ node: node.arguments[0],
43
+ loc: node.arguments[0].loc,
44
+ messageId: 'error',
45
+ data: {
46
+ currentValue: fnArgInterfaceName,
47
+ possibleValues: interfaceNames.join(', ')
48
+ },
49
+ fix: (fixer) => {
50
+ return fixer.replaceText(node.arguments[0], `'${interfaceNames[0]}'`);
51
+ },
52
+ suggest: interfaceNames.map((interfaceName) => ({
53
+ messageId: 'suggestion',
47
54
  data: {
48
55
  currentValue: fnArgInterfaceName,
49
- possibleValues: interfaceNames.join(', ')
56
+ recommendedValue: interfaceName
50
57
  },
51
58
  fix: (fixer) => {
52
- return fixer.replaceText(node.arguments[0], `'${interfaceNames[0]}'`);
53
- },
54
- suggest: interfaceNames.map((interfaceName) => ({
55
- messageId: 'suggestion',
56
- data: {
57
- currentValue: fnArgInterfaceName,
58
- recommendedValue: interfaceName
59
- },
60
- fix: (fixer) => {
61
- return fixer.replaceText(node.arguments[0], `'${interfaceName}'`);
62
- }
63
- }))
64
- });
65
- }
59
+ return fixer.replaceText(node.arguments[0], `'${interfaceName}'`);
60
+ }
61
+ }))
62
+ });
66
63
  }
67
64
  };
65
+ return {
66
+ CallExpression: rule
67
+ };
68
68
  }
69
69
  });
@@ -1,2 +1,2 @@
1
- declare const _default: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"error" | "indexFile", [], import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
1
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"error" | "indexFile", [], unknown, import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
2
2
  export default _default;
@@ -20,30 +20,31 @@ exports.default = (0, utils_1.createRule)({
20
20
  },
21
21
  defaultOptions: [],
22
22
  create: (context) => {
23
- return {
24
- // eslint-disable-next-line @typescript-eslint/naming-convention
25
- ImportDeclaration: (node) => {
26
- const importedModules = node.specifiers.filter((specifier) => specifier.local.name.endsWith('Module'));
27
- const importPath = node.source.value?.toString();
28
- if (importedModules.length && importPath && importPath.startsWith('.') && !importPath.endsWith('.module') && !importPath.endsWith('index')) {
29
- const dirname = path.dirname(context.getFilename());
30
- const importTarget = path.resolve(dirname, importPath);
31
- if (!fs.existsSync(importTarget) || !fs.statSync(importTarget).isDirectory()) {
32
- return;
33
- }
34
- const indexPath = path.resolve(importTarget, 'index.ts');
35
- const indexFileExist = fs.existsSync(indexPath);
36
- const newIndexFilePath = path.join(importPath, 'index')
37
- .replace(/[\\/]/g, '/')
38
- .replace(/^([^.])/, './$1');
39
- context.report({
40
- node,
41
- messageId: 'error',
42
- fix: !indexFileExist ? undefined : (fixer) => {
23
+ const rule = (node) => {
24
+ const importedModules = node.specifiers.filter((specifier) => specifier.local.name.endsWith('Module'));
25
+ const importPath = node.source.value?.toString();
26
+ if (importedModules.length > 0 && importPath && importPath.startsWith('.') && !importPath.endsWith('.module') && !importPath.endsWith('index')) {
27
+ const dirname = path.dirname(context.filename);
28
+ const importTarget = path.resolve(dirname, importPath);
29
+ if (!fs.existsSync(importTarget) || !fs.statSync(importTarget).isDirectory()) {
30
+ return;
31
+ }
32
+ const indexPath = path.resolve(importTarget, 'index.ts');
33
+ const indexFileExist = fs.existsSync(indexPath);
34
+ const newIndexFilePath = path.join(importPath, 'index')
35
+ .replace(/[/\\]/g, '/')
36
+ .replace(/^([^.])/, './$1');
37
+ context.report({
38
+ node,
39
+ messageId: 'error',
40
+ fix: indexFileExist
41
+ ? (fixer) => {
43
42
  return fixer.replaceText(node.source, node.source.raw
44
43
  .replace(importPath, newIndexFilePath));
45
- },
46
- suggest: !indexFileExist ? undefined : [
44
+ }
45
+ : undefined,
46
+ suggest: indexFileExist
47
+ ? [
47
48
  {
48
49
  messageId: 'indexFile',
49
50
  fix: (fixer) => {
@@ -55,9 +56,12 @@ exports.default = (0, utils_1.createRule)({
55
56
  }
56
57
  }
57
58
  ]
58
- });
59
- }
59
+ : undefined
60
+ });
60
61
  }
61
62
  };
63
+ return {
64
+ ImportDeclaration: rule
65
+ };
62
66
  }
63
67
  });
@@ -1,5 +1,5 @@
1
1
  export interface NoMultipleTypeConfigurationPropertyOption {
2
2
  supportedInterfaceNames?: string[];
3
3
  }
4
- declare const _default: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"suggestion" | "error", [Required<NoMultipleTypeConfigurationPropertyOption>, ...any[]], import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
4
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"error" | "suggestion", [Required<NoMultipleTypeConfigurationPropertyOption>, ...any[]], unknown, import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
5
5
  export default _default;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const utils_1 = require("@typescript-eslint/utils");
4
4
  const utils_2 = require("../../utils");
5
- const separatorRegExp = /\s*[|&]\s*/;
5
+ const separatorRegExp = /\s*[&|]\s*/;
6
6
  exports.default = (0, utils_2.createRule)({
7
7
  name: 'no-multiple-type-configuration-property',
8
8
  meta: {
@@ -35,14 +35,14 @@ exports.default = (0, utils_2.createRule)({
35
35
  }],
36
36
  create: (context, [options]) => {
37
37
  const supportedInterfaceNames = options.supportedInterfaceNames;
38
- const sourceCode = context.getSourceCode();
38
+ const { sourceCode } = context;
39
39
  const rule = (node) => {
40
40
  const interfaceDeclNode = node.parent?.parent?.parent?.parent;
41
41
  if (!(0, utils_2.isExtendingConfiguration)(interfaceDeclNode, supportedInterfaceNames)) {
42
42
  return; // Not in a configuration interface
43
43
  }
44
44
  if (node.types.every((type) => type.type === utils_1.TSESTree.AST_NODE_TYPES.TSLiteralType && type.literal.type === utils_1.TSESTree.AST_NODE_TYPES.Literal)
45
- && [...(new Set(node.types.map((literalType) => typeof literalType.literal.value)))].length === 1) {
45
+ && new Set(node.types.map((literalType) => typeof literalType.literal.value)).size === 1) {
46
46
  return; // Only the same literal type
47
47
  }
48
48
  const text = sourceCode.getText(node);
@@ -61,9 +61,7 @@ exports.default = (0, utils_2.createRule)({
61
61
  });
62
62
  };
63
63
  return {
64
- // eslint-disable-next-line @typescript-eslint/naming-convention
65
64
  TSUnionType: rule,
66
- // eslint-disable-next-line @typescript-eslint/naming-convention
67
65
  TSIntersectionType: rule
68
66
  };
69
67
  }
@@ -3,5 +3,5 @@ export interface O3rCategoriesTagsRuleOption {
3
3
  globalConfigCategories?: string[];
4
4
  }
5
5
  type Messages = 'alreadyDefined' | 'undefinedCategory' | 'onlyOneCategoryAllowed' | 'notInConfigurationInterface' | 'suggestReplaceO3rCategory';
6
- declare const _default: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<Messages, readonly [O3rCategoriesTagsRuleOption, ...any[]], import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
6
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<Messages, readonly [O3rCategoriesTagsRuleOption, ...any[]], unknown, import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
7
7
  export default _default;
@@ -45,92 +45,92 @@ exports.default = (0, utils_1.createRule)({
45
45
  }],
46
46
  create: (context, [options]) => {
47
47
  const globalConfigCategories = new Set(options.globalConfigCategories);
48
- return {
49
- // eslint-disable-next-line @typescript-eslint/naming-convention
50
- TSPropertySignature: (node) => {
51
- const sourceCode = context.getSourceCode();
52
- const comment = (0, utils_1.getNodeComment)(node, sourceCode);
53
- if (!comment || !comment.value.length) {
54
- return;
55
- }
56
- const { loc, value: docText } = comment;
57
- const categories = Array.from(docText.matchAll(/@o3rCategory (\w+)/g)).map((match) => match[1]);
58
- if (categories.length < 1) {
59
- return;
60
- }
61
- else if (categories.length > 1) {
62
- return context.report({
63
- messageId: 'onlyOneCategoryAllowed',
64
- node,
65
- loc
66
- });
67
- }
68
- const category = categories[0];
69
- const interfaceDeclNode = node.parent?.parent;
70
- if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, options.supportedInterfaceNames)) {
71
- return context.report({
72
- messageId: 'notInConfigurationInterface',
73
- node,
74
- loc
75
- });
76
- }
77
- const interfaceComment = (0, utils_1.getNodeComment)(interfaceDeclNode, sourceCode);
78
- const supportedO3rCategories = new Set(options.globalConfigCategories);
79
- Array.from(interfaceComment?.value.matchAll(/@o3rCategories (\w+)/g) || []).forEach((match) => supportedO3rCategories.add(match[1]));
80
- if (!supportedO3rCategories.has(category)) {
81
- return context.report({
82
- messageId: 'undefinedCategory',
83
- node,
84
- loc,
48
+ const ruleForProperties = (node) => {
49
+ const { sourceCode } = context;
50
+ const comment = (0, utils_1.getNodeComment)(node, sourceCode);
51
+ if (!comment || comment.value.length === 0) {
52
+ return;
53
+ }
54
+ const { loc, value: docText } = comment;
55
+ const categories = Array.from(docText.matchAll(/@o3rCategory (\w+)/g)).map((match) => match[1]);
56
+ if (categories.length === 0) {
57
+ return;
58
+ }
59
+ else if (categories.length > 1) {
60
+ return context.report({
61
+ messageId: 'onlyOneCategoryAllowed',
62
+ node,
63
+ loc
64
+ });
65
+ }
66
+ const category = categories[0];
67
+ const interfaceDeclNode = node.parent?.parent;
68
+ if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, options.supportedInterfaceNames)) {
69
+ return context.report({
70
+ messageId: 'notInConfigurationInterface',
71
+ node,
72
+ loc
73
+ });
74
+ }
75
+ const interfaceComment = (0, utils_1.getNodeComment)(interfaceDeclNode, sourceCode);
76
+ const supportedO3rCategories = new Set(options.globalConfigCategories);
77
+ Array.from(interfaceComment?.value.matchAll(/@o3rCategories (\w+)/g) || []).forEach((match) => supportedO3rCategories.add(match[1]));
78
+ if (!supportedO3rCategories.has(category)) {
79
+ return context.report({
80
+ messageId: 'undefinedCategory',
81
+ node,
82
+ loc,
83
+ data: {
84
+ currentCategory: category,
85
+ supportedCategories: Array.from(supportedO3rCategories).join(', ')
86
+ },
87
+ suggest: Array.from(supportedO3rCategories).map((suggestedCategory) => ({
88
+ messageId: 'suggestReplaceO3rCategory',
85
89
  data: {
86
90
  currentCategory: category,
87
- supportedCategories: Array.from(supportedO3rCategories).join(', ')
91
+ suggestedCategory
88
92
  },
89
- suggest: Array.from(supportedO3rCategories).map((suggestedCategory) => ({
90
- messageId: 'suggestReplaceO3rCategory',
91
- data: {
92
- currentCategory: category,
93
- suggestedCategory: suggestedCategory
94
- },
95
- fix: (fixer) => {
96
- return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(`@o3rCategory ${category}`, `@o3rCategory ${suggestedCategory}`)));
97
- }
98
- }))
99
- });
100
- }
101
- },
102
- // eslint-disable-next-line @typescript-eslint/naming-convention
103
- TSInterfaceDeclaration: (node) => {
104
- const sourceCode = context.getSourceCode();
105
- const comment = (0, utils_1.getNodeComment)(node, sourceCode);
106
- if (!comment || !comment.value.length) {
107
- return;
108
- }
109
- const { loc, value: docText } = comment;
110
- const categories = Array.from(docText.matchAll(/@o3rCategories (\w+)/g)).map((match) => match[1]);
111
- if (categories.length < 1) {
112
- return;
113
- }
114
- if (!(0, utils_1.isExtendingConfiguration)(node, options.supportedInterfaceNames)) {
115
- return context.report({
116
- messageId: 'notInConfigurationInterface',
117
- node,
118
- loc
119
- });
120
- }
121
- const alreadyDefined = categories.find((category) => globalConfigCategories.has(category));
122
- if (alreadyDefined) {
123
- return context.report({
124
- messageId: 'alreadyDefined',
125
- fix: (fixer) => fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(new RegExp(`.*@o3rCategories ${alreadyDefined}.*\n`), ''))),
126
- data: {
127
- currentCategory: alreadyDefined
128
- },
129
- node,
130
- loc
131
- });
132
- }
93
+ fix: (fixer) => {
94
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(`@o3rCategory ${category}`, `@o3rCategory ${suggestedCategory}`)));
95
+ }
96
+ }))
97
+ });
98
+ }
99
+ };
100
+ const ruleForInterface = (node) => {
101
+ const { sourceCode } = context;
102
+ const comment = (0, utils_1.getNodeComment)(node, sourceCode);
103
+ if (!comment || comment.value.length === 0) {
104
+ return;
133
105
  }
106
+ const { loc, value: docText } = comment;
107
+ const categories = Array.from(docText.matchAll(/@o3rCategories (\w+)/g)).map((match) => match[1]);
108
+ if (categories.length === 0) {
109
+ return;
110
+ }
111
+ if (!(0, utils_1.isExtendingConfiguration)(node, options.supportedInterfaceNames)) {
112
+ return context.report({
113
+ messageId: 'notInConfigurationInterface',
114
+ node,
115
+ loc
116
+ });
117
+ }
118
+ const alreadyDefined = categories.find((category) => globalConfigCategories.has(category));
119
+ if (alreadyDefined) {
120
+ return context.report({
121
+ messageId: 'alreadyDefined',
122
+ fix: (fixer) => fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(new RegExp(`.*@o3rCategories ${alreadyDefined}.*\n`), ''))),
123
+ data: {
124
+ currentCategory: alreadyDefined
125
+ },
126
+ node,
127
+ loc
128
+ });
129
+ }
130
+ };
131
+ return {
132
+ TSPropertySignature: ruleForProperties,
133
+ TSInterfaceDeclaration: ruleForInterface
134
134
  };
135
135
  }
136
136
  });
@@ -0,0 +1,8 @@
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ export interface O3rRestrictionKeyTagsRuleOption {
3
+ supportedInterfaceNames?: string[];
4
+ supportedKeys?: string[];
5
+ }
6
+ type O3rWidgetRuleErrorId = 'notSupportedKey' | 'notWrapWithQuotes' | 'suggestWrapWithQuotes' | 'suggestUseSupportedKey' | 'noRestrictionKeyProvided' | 'notInConfigurationInterface';
7
+ declare const _default: TSESLint.RuleModule<O3rWidgetRuleErrorId, [Readonly<O3rRestrictionKeyTagsRuleOption>, ...any[]], unknown, TSESLint.RuleListener>;
8
+ export default _default;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../../utils");
4
+ const defaultOptions = [{
5
+ supportedInterfaceNames: utils_1.defaultSupportedInterfaceNames,
6
+ supportedKeys: []
7
+ }];
8
+ exports.default = (0, utils_1.createRule)({
9
+ name: 'o3r-restriction-key-tags',
10
+ meta: {
11
+ hasSuggestions: true,
12
+ fixable: 'code',
13
+ type: 'problem',
14
+ docs: {
15
+ description: 'Ensures that @o3rRestrictionKey is used with a correct value'
16
+ },
17
+ schema: [
18
+ {
19
+ type: 'object',
20
+ properties: {
21
+ supportedInterfaceNames: {
22
+ type: 'array',
23
+ items: {
24
+ type: 'string'
25
+ }
26
+ },
27
+ supportedKeys: {
28
+ type: 'array',
29
+ items: {
30
+ type: 'string'
31
+ },
32
+ minItems: 1
33
+ }
34
+ }
35
+ }
36
+ ],
37
+ messages: {
38
+ notSupportedKey: '{{ actualKey }} is not supported. Supported restriction keys: {{ supportedKeys }}.',
39
+ suggestUseSupportedKey: '{{ actualKey }} is not supported. Replace with {{ supportedKey }}.',
40
+ notWrapWithQuotes: '`{{ actualKey }}` is not wrapped with quotes.',
41
+ suggestWrapWithQuotes: 'Wrap `{{ actualKey }}` with quotes.',
42
+ notInConfigurationInterface: '@o3rRestrictionKey can only be used in a `Configuration` interface.',
43
+ noRestrictionKeyProvided: 'You must have at least one restriction key.'
44
+ }
45
+ },
46
+ defaultOptions,
47
+ create: (context, [options]) => {
48
+ const rule = (node) => {
49
+ const { sourceCode } = context;
50
+ const comment = (0, utils_1.getNodeComment)(node, sourceCode);
51
+ if (!comment || comment.value.length === 0) {
52
+ return;
53
+ }
54
+ const { loc, value: docText } = comment;
55
+ const supportedKeys = options.supportedKeys || defaultOptions[0].supportedKeys;
56
+ const supportedKeysSet = new Set(supportedKeys);
57
+ if (supportedKeys.length === 0) {
58
+ return context.report({
59
+ messageId: 'noRestrictionKeyProvided',
60
+ node,
61
+ loc
62
+ });
63
+ }
64
+ const actualKeys = Array.from(docText.matchAll(/@o3rRestrictionKey\s+(.*)/g)).map((match) => match[1]);
65
+ if (actualKeys.length === 0) {
66
+ return;
67
+ }
68
+ const interfaceDeclNode = node.parent?.parent;
69
+ if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, options.supportedInterfaceNames)) {
70
+ return context.report({
71
+ messageId: 'notInConfigurationInterface',
72
+ node,
73
+ loc
74
+ });
75
+ }
76
+ actualKeys.forEach((actualKey) => {
77
+ if (!supportedKeysSet.has(actualKey)) {
78
+ if (/((["']).*?\2)/.test(actualKey)
79
+ && supportedKeysSet.has(actualKey.replace(/(^["']|["']$)/g, ''))) {
80
+ return;
81
+ }
82
+ const fix = (key) => (fixer) => {
83
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(actualKey, /[^\w]/.test(key) ? `"${key}"` : key)));
84
+ };
85
+ return context.report({
86
+ messageId: 'notSupportedKey',
87
+ node,
88
+ loc,
89
+ data: {
90
+ actualKey,
91
+ supportedKeys: supportedKeys.join(', ')
92
+ },
93
+ suggest: supportedKeys.map((supportedKey) => ({
94
+ messageId: 'suggestUseSupportedKey',
95
+ data: {
96
+ actualKey,
97
+ supportedKey
98
+ },
99
+ fix: fix(supportedKey)
100
+ }))
101
+ });
102
+ }
103
+ if (/[^\w]/.test(actualKey)) {
104
+ const fix = (fixer) => {
105
+ return fixer.replaceTextRange(comment.range, (0, utils_1.createCommentString)(comment.value.replace(actualKey, `"${actualKey}"`)));
106
+ };
107
+ return context.report({
108
+ messageId: 'notWrapWithQuotes',
109
+ data: {
110
+ actualKey
111
+ },
112
+ node,
113
+ loc,
114
+ fix,
115
+ suggest: [{
116
+ messageId: 'suggestWrapWithQuotes',
117
+ data: {
118
+ actualKey
119
+ },
120
+ fix
121
+ }]
122
+ });
123
+ }
124
+ });
125
+ };
126
+ return {
127
+ TSPropertySignature: rule
128
+ };
129
+ }
130
+ });
@@ -12,5 +12,5 @@ export interface O3rWidgetTagsRuleOption {
12
12
  };
13
13
  }
14
14
  type O3rWidgetRuleErrorId = 'notInConfigurationInterface' | 'notSupportedType' | 'notSupportedParamForType' | 'invalidParamValueType' | 'noParamWithoutWidget' | 'onlyOneWidgetAllowed' | 'duplicatedParam' | 'requiredParamMissing' | 'suggestParamMissing' | 'suggestRemoveDuplicatedO3rWidget' | 'suggestRemoveDuplicatedO3rWidgetParam' | 'suggestAddO3rWidgetTag' | 'suggestReplaceO3rWidgetType';
15
- declare const _default: TSESLint.RuleModule<O3rWidgetRuleErrorId, [Readonly<O3rWidgetTagsRuleOption>, ...any[]], TSESLint.RuleListener>;
15
+ declare const _default: TSESLint.RuleModule<O3rWidgetRuleErrorId, [Readonly<O3rWidgetTagsRuleOption>, ...any[]], unknown, TSESLint.RuleListener>;
16
16
  export default _default;