@agilebot/eslint-plugin 0.3.6 → 0.3.8

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/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- export default plugin;
1
+ import * as eslint from 'eslint';
2
+
2
3
  declare namespace plugin {
3
- let rules: import('eslint').Linter.RulesRecord;
4
+ let rules: eslint.Linter.RulesRecord;
4
5
  namespace configs {
5
6
  namespace recommended {
6
7
  export let plugins: string[];
7
- let rules_1: import('eslint').Linter.RulesRecord;
8
+ let rules_1: eslint.Linter.RulesRecord;
8
9
  export { rules_1 as rules };
9
10
  export namespace settings {
10
11
  namespace react {
@@ -14,3 +15,5 @@ declare namespace plugin {
14
15
  }
15
16
  }
16
17
  }
18
+
19
+ export { plugin as default };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license @agilebot/eslint-plugin v0.3.6
2
+ * @license @agilebot/eslint-plugin v0.3.8
3
3
  *
4
4
  * Copyright (c) Agilebot, Inc. and its affiliates.
5
5
  *
@@ -8,9 +8,9 @@
8
8
  */
9
9
  'use strict';
10
10
 
11
+ var eslintUtils = require('@agilebot/eslint-utils');
11
12
  var fs = require('node:fs');
12
13
  var path = require('node:path');
13
- var eslintUtils = require('@agilebot/eslint-utils');
14
14
  var utils = require('@typescript-eslint/utils');
15
15
 
16
16
  function _interopNamespaceDefault(e) {
@@ -72,11 +72,136 @@ var enforceMuiIconAlias = {
72
72
  }
73
73
  };
74
74
 
75
+ var funcNaming = {
76
+ meta: {
77
+ docs: {
78
+ description: 'Enforce function naming convention'
79
+ },
80
+ schema: [{
81
+ type: 'object',
82
+ properties: {
83
+ format: {
84
+ "enum": ['camelCase', 'PascalCase']
85
+ }
86
+ }
87
+ }],
88
+ messages: {
89
+ invalidFuncNaming: 'Invalid function naming for non-React component, expected {{format}}',
90
+ invalidReactFCNaming: 'Invalid naming convention for React functional component, expected PascalCase'
91
+ }
92
+ },
93
+ create(context) {
94
+ if (!context.options[0]) {
95
+ throw new Error('Missing options');
96
+ }
97
+ const format = context.options[0].format;
98
+ function validate({
99
+ node,
100
+ fnName
101
+ }) {
102
+ let isPass;
103
+ switch (format) {
104
+ case 'camelCase':
105
+ if (!eslintUtils.isCamelCase(fnName)) {
106
+ isPass = false;
107
+ }
108
+ break;
109
+ case 'PascalCase':
110
+ if (!eslintUtils.isPascalCase(fnName)) {
111
+ isPass = false;
112
+ }
113
+ break;
114
+ }
115
+ if (isPass === false) {
116
+ context.report({
117
+ node: node,
118
+ messageId: 'invalidFuncNaming',
119
+ data: {
120
+ format
121
+ }
122
+ });
123
+ }
124
+ }
125
+ function checkJSXElement(node) {
126
+ if (!node) {
127
+ return false;
128
+ }
129
+ if (node.type === 'JSXElement' || node.type === 'JSXFragment') {
130
+ return true;
131
+ }
132
+ if (node.type === 'BlockStatement') {
133
+ for (const statement of node.body) {
134
+ if (statement.type === 'ReturnStatement') {
135
+ if (checkJSXElement(statement.argument)) {
136
+ return true;
137
+ }
138
+ } else if (checkJSXElement(statement)) {
139
+ return true;
140
+ }
141
+ }
142
+ }
143
+ if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') {
144
+ return checkJSXElement(node.body);
145
+ }
146
+ return false;
147
+ }
148
+ return {
149
+ MethodDefinition(node) {
150
+ if (node.kind === 'method') ;
151
+ },
152
+ FunctionDeclaration(node) {
153
+ if (node.type === 'FunctionDeclaration' && node.id) {
154
+ const fnName = node.id.name;
155
+ const isReactComponent = checkJSXElement(node.body);
156
+ if (!isReactComponent) {
157
+ validate({
158
+ node,
159
+ fnName
160
+ });
161
+ }
162
+ }
163
+ },
164
+ VariableDeclarator(node) {
165
+ if (node.init && ['FunctionExpression', 'ArrowFunctionExpression'].includes(node.init.type)) {
166
+ const fnName = node.id.name;
167
+ let isReactComponent = checkJSXElement(node.init.body);
168
+ if (node.id.typeAnnotation && node.id.typeAnnotation.typeAnnotation) {
169
+ const typeAnnotation = node.id.typeAnnotation.typeAnnotation;
170
+ if (typeAnnotation.type === 'TSTypeReference' && typeAnnotation.typeName.type === 'Identifier') {
171
+ const typeName = typeAnnotation.typeName.name;
172
+ if (['FC', 'React.FC', 'FunctionComponent', 'React.FunctionComponent'].includes(typeName)) {
173
+ isReactComponent = true;
174
+ }
175
+ }
176
+ }
177
+ if (!isReactComponent) {
178
+ validate({
179
+ node,
180
+ fnName
181
+ });
182
+ }
183
+ }
184
+ },
185
+ Property(node) {
186
+ if (node.value.type === 'FunctionExpression') ;
187
+ }
188
+ };
189
+ }
190
+ };
191
+
75
192
  function getSetting(context, name) {
76
193
  return context.settings["agilebot/".concat(name)];
77
194
  }
78
195
 
79
- let warnedForMissingPrefix = false;
196
+ const warned = new Set();
197
+ function warnOnce(message) {
198
+ if (warned.has(message)) {
199
+ return;
200
+ }
201
+ warned.add(message);
202
+ console.warn("Warning: ".concat(message));
203
+ }
204
+
80
205
  var importMonorepo = {
81
206
  meta: {
82
207
  type: 'problem',
@@ -95,10 +220,7 @@ var importMonorepo = {
95
220
  ImportDeclaration(node) {
96
221
  let prefix = getSetting(context, 'monorepo-scope');
97
222
  if (!prefix) {
98
- if (!warnedForMissingPrefix) {
99
- console.error('Warning: agilebot/monorepo-scope is not set.');
100
- warnedForMissingPrefix = true;
101
- }
223
+ warnOnce('agilebot/monorepo-scope is not set.');
102
224
  return;
103
225
  }
104
226
  prefix = "".concat(prefix, "/");
@@ -269,6 +391,98 @@ var intlIdMissing = {
269
391
  }
270
392
  };
271
393
 
394
+ var intlIdNaming = {
395
+ meta: {
396
+ docs: {
397
+ description: 'Validates intl message ids naming convention',
398
+ category: 'Intl'
399
+ },
400
+ fixable: undefined,
401
+ schema: [{
402
+ type: 'object',
403
+ properties: {
404
+ format: {
405
+ "enum": ['camelCase', 'PascalCase']
406
+ }
407
+ }
408
+ }],
409
+ messages: {
410
+ invalidIdNaming: "Invalid id naming, expected {{format}}"
411
+ }
412
+ },
413
+ create: function (context) {
414
+ if (!context.options[0]) {
415
+ throw new Error('Missing options');
416
+ }
417
+ const format = context.options[0].format;
418
+ function report(node, value) {
419
+ const values = value.split('.');
420
+ let isPass;
421
+ for (const v of values) {
422
+ switch (format) {
423
+ case 'camelCase':
424
+ if (!eslintUtils.isCamelCase(v)) {
425
+ isPass = false;
426
+ }
427
+ break;
428
+ case 'PascalCase':
429
+ if (!eslintUtils.isPascalCase(v)) {
430
+ isPass = false;
431
+ }
432
+ break;
433
+ }
434
+ }
435
+ if (isPass === false) {
436
+ context.report({
437
+ node: node,
438
+ messageId: 'invalidIdNaming',
439
+ data: {
440
+ format
441
+ }
442
+ });
443
+ }
444
+ }
445
+ function processLiteral(node) {
446
+ report(node, node.value);
447
+ }
448
+ function processTemplateLiteral(node) {
449
+ const displayStr = templateLiteralDisplayStr(node);
450
+ report(node, displayStr);
451
+ }
452
+ function processAttrNode(node) {
453
+ if (node.value.type === 'Literal') {
454
+ return processLiteral(node.value);
455
+ }
456
+ if (node.value.type === 'JSXExpressionContainer' && node.value.expression.type === 'TemplateLiteral') {
457
+ return processTemplateLiteral(node.value.expression);
458
+ }
459
+ if (node.value.type === 'TemplateLiteral') {
460
+ return processTemplateLiteral(node.value);
461
+ }
462
+ }
463
+ return {
464
+ JSXIdentifier: function (node) {
465
+ const attrNode = findFormattedMessageAttrNode(node, 'id');
466
+ if (attrNode) {
467
+ return processAttrNode(attrNode);
468
+ }
469
+ },
470
+ CallExpression: function (node) {
471
+ const attrNode = findFormatMessageAttrNode(node, 'id');
472
+ if (attrNode) {
473
+ return processAttrNode(attrNode);
474
+ }
475
+ },
476
+ Property: function (node) {
477
+ const attrNode = findAttrNodeInDefineMessages(node, 'id') || findAttrNodeInDefineMessage(node, 'id');
478
+ if (attrNode) {
479
+ return processAttrNode(attrNode);
480
+ }
481
+ }
482
+ };
483
+ }
484
+ };
485
+
272
486
  var intlIdPrefix = {
273
487
  meta: {
274
488
  docs: {
@@ -2414,8 +2628,10 @@ var tssUnusedClasses = {
2414
2628
  var ruleFiles = /*#__PURE__*/Object.freeze({
2415
2629
  __proto__: null,
2416
2630
  rules_enforce_mui_icon_alias: enforceMuiIconAlias,
2631
+ rules_func_naming: funcNaming,
2417
2632
  rules_import_monorepo: importMonorepo,
2418
2633
  rules_intl_id_missing: intlIdMissing,
2634
+ rules_intl_id_naming: intlIdNaming,
2419
2635
  rules_intl_id_prefix: intlIdPrefix,
2420
2636
  rules_intl_id_unused: intlIdUnused,
2421
2637
  rules_intl_no_default: intlNoDefault,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agilebot/eslint-plugin",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Agilebot's ESLint plugin",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "@typescript-eslint/utils": "~7.9.0",
22
22
  "eslint-plugin-react": "^7.34.1",
23
- "@agilebot/eslint-utils": "0.3.6"
23
+ "@agilebot/eslint-utils": "0.3.8"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "eslint": "^7.0.0 || ^8.0.0"
@@ -35,8 +35,7 @@
35
35
  "eslint-vitest-rule-tester": "^0.3.2"
36
36
  },
37
37
  "scripts": {
38
- "build": "rollup -c rollup.config.mjs && nr dts",
39
- "dts": "tsc -p tsconfig.dts.json",
38
+ "build": "rollup -c rollup.config.mjs",
40
39
  "lint": "eslint src --fix"
41
40
  }
42
41
  }