@o3r/eslint-plugin 9.6.0-alpha.3 → 9.6.0-alpha.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3r/eslint-plugin",
3
- "version": "9.6.0-alpha.3",
3
+ "version": "9.6.0-alpha.30",
4
4
  "description": "The module provides in-house eslint plugins to use in your own eslint configuration.",
5
5
  "main": "./src/public_api.js",
6
6
  "keywords": [
@@ -35,8 +35,8 @@
35
35
  }
36
36
  },
37
37
  "peerDependencies": {
38
- "@angular-eslint/template-parser": "~16.2.0",
39
- "@angular-eslint/utils": "~16.2.0",
38
+ "@angular-eslint/template-parser": "~16.3.0",
39
+ "@angular-eslint/utils": "~16.3.0",
40
40
  "@angular/compiler": "~16.2.0",
41
41
  "@typescript-eslint/eslint-plugin": "^5.60.1",
42
42
  "@typescript-eslint/parser": "^5.60.1",
@@ -46,16 +46,16 @@
46
46
  "devDependencies": {
47
47
  "@angular-devkit/core": "~16.2.0",
48
48
  "@angular-devkit/schematics": "~16.2.0",
49
- "@angular-eslint/eslint-plugin": "~16.2.0",
50
- "@angular-eslint/template-parser": "~16.2.0",
51
- "@angular-eslint/utils": "~16.2.0",
49
+ "@angular-eslint/eslint-plugin": "~16.3.0",
50
+ "@angular-eslint/template-parser": "~16.3.0",
51
+ "@angular-eslint/utils": "~16.3.0",
52
52
  "@angular/compiler": "~16.2.0",
53
53
  "@babel/core": "~7.23.0",
54
54
  "@babel/preset-typescript": "~7.23.0",
55
55
  "@compodoc/compodoc": "^1.1.19",
56
56
  "@nx/eslint-plugin": "~16.10.0",
57
57
  "@nx/jest": "~16.10.0",
58
- "@o3r/build-helpers": "^9.6.0-alpha.3",
58
+ "@o3r/build-helpers": "^9.6.0-alpha.30",
59
59
  "@types/jest": "~29.5.2",
60
60
  "@types/node": "^18.0.0",
61
61
  "@types/semver": "^7.3.13",
package/src/index.js CHANGED
@@ -3,25 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  /* eslint-disable @typescript-eslint/naming-convention */
4
4
  const no_folder_import_for_module_1 = require("./rules/typescript/no-folder-import-for-module/no-folder-import-for-module");
5
5
  const o3r_widget_tags_1 = require("./rules/typescript/o3r-widget-tags/o3r-widget-tags");
6
+ const no_inner_html_1 = require("./rules/template/no-inner-html/no-inner-html");
6
7
  const template_async_number_limitation_1 = require("./rules/template/template-async-number-limitation/template-async-number-limitation");
7
8
  const json_dependency_versions_harmonize_1 = require("./rules/json/json-dependency-versions-harmonize/json-dependency-versions-harmonize");
8
9
  const matching_configuration_name_1 = require("./rules/typescript/matching-configuration-name/matching-configuration-name");
10
+ const no_multiple_type_configuration_property_1 = require("./rules/typescript/no-multiple-type-configuration-property/no-multiple-type-configuration-property");
9
11
  module.exports = {
10
12
  rules: {
11
13
  'no-folder-import-for-module': no_folder_import_for_module_1.default,
14
+ 'no-inner-html': no_inner_html_1.default,
12
15
  'template-async-number-limitation': template_async_number_limitation_1.default,
13
16
  'o3r-widget-tags': o3r_widget_tags_1.default,
14
17
  'json-dependency-versions-harmonize': json_dependency_versions_harmonize_1.default,
15
- 'matching-configuration-name': matching_configuration_name_1.default
18
+ 'matching-configuration-name': matching_configuration_name_1.default,
19
+ 'no-multiple-type-configuration-property': no_multiple_type_configuration_property_1.default
16
20
  },
17
21
  configs: {
18
22
  '@o3r/no-folder-import-for-module': 'error',
19
23
  '@o3r/json-dependency-versions-harmonize': 'error',
24
+ '@o3r/no-multiple-type-configuration-property': 'error',
20
25
  '@o3r/template-async-number-limitation': 'warn',
21
26
  '@o3r/matching-configuration-name': 'warn',
22
27
  recommended: {
23
28
  rules: {
24
29
  '@o3r/matching-configuration-name': 'error',
30
+ '@o3r/no-multiple-type-configuration-property': 'error',
25
31
  '@o3r/no-folder-import-for-module': 'error',
26
32
  '@o3r/template-async-number-limitation': 'off'
27
33
  }
@@ -0,0 +1,5 @@
1
+ /** Rule Name */
2
+ export declare const name = "no-inner-html";
3
+ type Messages = 'error' | 'fix';
4
+ declare const _default: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<Messages, [], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
+ export default _default;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.name = void 0;
4
+ const utils_1 = require("../utils");
5
+ const utils_2 = require("../../utils");
6
+ /** Rule Name */
7
+ exports.name = 'no-inner-html';
8
+ exports.default = (0, utils_2.createRule)({
9
+ name: exports.name,
10
+ defaultOptions: [],
11
+ meta: {
12
+ type: 'problem',
13
+ hasSuggestions: true,
14
+ docs: {
15
+ description: 'Ensures that your template does not use innerHTML',
16
+ recommended: 'warn'
17
+ },
18
+ schema: [],
19
+ messages: {
20
+ error: 'Unexpected use of innerHTML',
21
+ fix: 'Replace innerHTML by innerText'
22
+ },
23
+ fixable: 'code'
24
+ },
25
+ create: (context) => {
26
+ // To throw error if use without @angular-eslint/template-parser
27
+ (0, utils_1.getTemplateParserServices)(context);
28
+ return {
29
+ // eslint-disable-next-line @typescript-eslint/naming-convention
30
+ 'Element$1': (node) => {
31
+ const innerHTMLAttribute = node.attributes.find((a) => /innerHTML/i.test(a.name));
32
+ if (innerHTMLAttribute && innerHTMLAttribute.keySpan) {
33
+ context.report({
34
+ messageId: 'error',
35
+ loc: {
36
+ column: innerHTMLAttribute.keySpan.start.col,
37
+ line: innerHTMLAttribute.keySpan.start.line,
38
+ end: {
39
+ column: innerHTMLAttribute.keySpan.end.col,
40
+ line: innerHTMLAttribute.keySpan.end.line
41
+ },
42
+ start: {
43
+ column: innerHTMLAttribute.keySpan.start.col,
44
+ line: innerHTMLAttribute.keySpan.start.line
45
+ }
46
+ },
47
+ fix: (fixer) => fixer.replaceTextRange([innerHTMLAttribute.keySpan.start.offset, innerHTMLAttribute.keySpan.end.offset], 'innerText'),
48
+ suggest: [{
49
+ messageId: 'fix',
50
+ fix: (fixer) => fixer.replaceTextRange([innerHTMLAttribute.keySpan.start.offset, innerHTMLAttribute.keySpan.end.offset], 'innerText')
51
+ }]
52
+ });
53
+ }
54
+ }
55
+ };
56
+ }
57
+ });
@@ -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", NoMultipleTypeConfigurationPropertyOption[], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
+ export default _default;
@@ -0,0 +1,69 @@
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
+ create: (context) => {
36
+ const supportedInterfaceNames = context.options.reduce((acc, option) => acc.concat(option.supportedInterfaceNames || []), []);
37
+ const sourceCode = context.getSourceCode();
38
+ const rule = (node) => {
39
+ const interfaceDeclNode = node.parent?.parent?.parent?.parent;
40
+ if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, supportedInterfaceNames)) {
41
+ return; // Not in a configuration interface
42
+ }
43
+ 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)
44
+ && [...(new Set(node.types.map((literalType) => typeof literalType.literal.value)))].length === 1) {
45
+ return; // Only the same literal type
46
+ }
47
+ const text = sourceCode.getText(node);
48
+ context.report({
49
+ messageId: 'error',
50
+ node,
51
+ loc: node.loc,
52
+ suggest: text.split(separatorRegExp).map((type) => ({
53
+ messageId: 'suggestion',
54
+ data: {
55
+ currentValue: text,
56
+ recommendedValue: type
57
+ },
58
+ fix: (fixer) => fixer.replaceTextRange(node.range, type)
59
+ }))
60
+ });
61
+ };
62
+ return {
63
+ // eslint-disable-next-line @typescript-eslint/naming-convention
64
+ TSUnionType: rule,
65
+ // eslint-disable-next-line @typescript-eslint/naming-convention
66
+ TSIntersectionType: rule
67
+ };
68
+ }
69
+ });
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
4
3
  const utils_1 = require("../../utils");
5
4
  const o3rWidgetParameterPattern = '^[a-zA-Z0-9-_:.]+$';
6
5
  const o3rWidgetParamTypes = ['string', 'number', 'boolean', 'string[]', 'number[]', 'boolean[]'];
@@ -24,7 +23,8 @@ exports.default = (0, utils_1.createRule)({
24
23
  type: 'array',
25
24
  items: {
26
25
  type: 'string'
27
- }
26
+ },
27
+ default: utils_1.defaultSupportedInterfaceNames
28
28
  },
29
29
  widgets: {
30
30
  additionalProperties: {
@@ -76,7 +76,7 @@ exports.default = (0, utils_1.createRule)({
76
76
  ...option.widgets
77
77
  };
78
78
  return acc;
79
- }, { widgets: {}, supportedInterfaceNames: ['Configuration', 'NestedConfiguration'] });
79
+ }, { widgets: {}, supportedInterfaceNames: [] });
80
80
  const supportedO3rWidgets = new Set(Object.keys(options.widgets));
81
81
  return {
82
82
  // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -125,10 +125,7 @@ exports.default = (0, utils_1.createRule)({
125
125
  return;
126
126
  }
127
127
  const interfaceDeclNode = node.parent?.parent;
128
- if (interfaceDeclNode?.type !== experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
129
- || !interfaceDeclNode.extends?.some((ext) => ext.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceHeritage
130
- && ext.expression.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
131
- && options.supportedInterfaceNames.includes(ext.expression.name))) {
128
+ if (!(0, utils_1.isExtendingConfiguration)(interfaceDeclNode, options.supportedInterfaceNames)) {
132
129
  return context.report({
133
130
  messageId: 'notInConfigurationInterface',
134
131
  node,
@@ -1,3 +1,11 @@
1
- import { ESLintUtils } from '@typescript-eslint/experimental-utils';
1
+ import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils';
2
2
  /** ESLint rule generator */
3
3
  export declare const createRule: <TOptions extends readonly unknown[], TMessageIds extends string, TRuleListener extends import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener = import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>({ name, meta, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<TOptions, TMessageIds, TRuleListener>>) => import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<TMessageIds, TOptions, TRuleListener>;
4
+ /** Default supported interface names */
5
+ export declare const defaultSupportedInterfaceNames: string[];
6
+ /**
7
+ * Returns true if the node extends one of the `supportedInterfaceNames`
8
+ * @param interfaceDeclNode
9
+ * @param supportedInterfaceNames
10
+ */
11
+ export declare const isExtendingConfiguration: (interfaceDeclNode: TSESTree.Node | undefined, supportedInterfaceNames?: string[]) => boolean | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createRule = void 0;
3
+ exports.isExtendingConfiguration = exports.defaultSupportedInterfaceNames = exports.createRule = void 0;
4
4
  const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
5
5
  const path = require("node:path");
6
6
  /** Current package version (format: <major>.<minor>)*/
@@ -13,3 +13,18 @@ exports.createRule = experimental_utils_1.ESLintUtils.RuleCreator((name) => {
13
13
  }
14
14
  return `https://github.com/AmadeusITGroup/otter/tree/release/${version}/docs/linter/eslint-plugin/rules/${name}.md`;
15
15
  });
16
+ /** Default supported interface names */
17
+ exports.defaultSupportedInterfaceNames = ['Configuration', 'NestedConfiguration'];
18
+ /**
19
+ * Returns true if the node extends one of the `supportedInterfaceNames`
20
+ * @param interfaceDeclNode
21
+ * @param supportedInterfaceNames
22
+ */
23
+ const isExtendingConfiguration = (interfaceDeclNode, supportedInterfaceNames = []) => {
24
+ const supportedInterfaceNamesSet = new Set(supportedInterfaceNames.length > 0 ? supportedInterfaceNames : exports.defaultSupportedInterfaceNames);
25
+ return interfaceDeclNode?.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration
26
+ && interfaceDeclNode.extends?.some((ext) => ext.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.TSInterfaceHeritage
27
+ && ext.expression.type === experimental_utils_1.TSESTree.AST_NODE_TYPES.Identifier
28
+ && supportedInterfaceNamesSet.has(ext.expression.name));
29
+ };
30
+ exports.isExtendingConfiguration = isExtendingConfiguration;