eslint-plugin-crisp 1.1.9 → 1.1.11

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/index.js CHANGED
@@ -28,6 +28,7 @@ import ruleNoSpaceInOptionalArguments from "./rules/no-space-in-optional-argumen
28
28
  import ruleNoUselessTemplateLiterals from "./rules/no-useless-template-literals.js";
29
29
  import ruleNoVarInBlocks from "./rules/no-var-in-blocks.js";
30
30
  import ruleNoShortParameters from "./rules/no-short-parameters.js";
31
+ import ruleNoSnakeCase from "./rules/no-snake-case.js";
31
32
  import ruleOneSpaceAfterOperator from "./rules/one-space-after-operator.js";
32
33
  import ruleRegexInConstructor from "./rules/regex-in-constructor.js";
33
34
  import ruleTernaryParenthesis from "./rules/ternary-parenthesis.js";
@@ -85,6 +86,7 @@ const plugin = {
85
86
  "no-var-in-blocks": ruleNoVarInBlocks,
86
87
  "no-useless-template-literals": ruleNoUselessTemplateLiterals,
87
88
  "no-short-parameters": ruleNoShortParameters,
89
+ "no-snake-case": ruleNoSnakeCase,
88
90
  "one-space-after-operator": ruleOneSpaceAfterOperator,
89
91
  "regex-in-constructor": ruleRegexInConstructor,
90
92
  "ternary-parenthesis": ruleTernaryParenthesis,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-crisp",
3
- "version": "1.1.9",
3
+ "version": "1.1.11",
4
4
  "description": "Custom ESLint Rules for Crisp",
5
5
  "author": "Crisp IM SAS",
6
6
  "main": "index.js",
@@ -27,8 +27,8 @@ export default function configRecommendedVue(pluginCrisp) {
27
27
  },
28
28
 
29
29
  plugins: {
30
- "jsdoc": pluginJSDoc,
31
- "crisp": pluginCrisp
30
+ jsdoc: pluginJSDoc,
31
+ crisp: pluginCrisp
32
32
  },
33
33
 
34
34
  settings: {
@@ -376,7 +376,8 @@ export default function configRecommendedVue(pluginCrisp) {
376
376
  "crisp/vue-props-declaration-line-break": "error",
377
377
  "crisp/vue-props-declaration-multiline": "error",
378
378
  "crisp/vue-props-declaration-order": "error",
379
- "crisp/vue-ref-case": "error"
379
+ "crisp/vue-ref-case": "error",
380
+ "crisp/no-snake-case": "error"
380
381
  }
381
382
  }
382
383
  ];
package/recommended.js CHANGED
@@ -20,8 +20,8 @@ export default function configRecommended(pluginCrisp) {
20
20
  },
21
21
 
22
22
  plugins: {
23
- "jsdoc": pluginJSDoc,
24
- "crisp": pluginCrisp
23
+ jsdoc: pluginJSDoc,
24
+ crisp: pluginCrisp
25
25
  },
26
26
 
27
27
  settings: {
@@ -19,7 +19,7 @@ export default {
19
19
  comment.type === "Block" && comment.value.startsWith("*")
20
20
  );
21
21
 
22
- if (jsDocComment) {
22
+ if (jsDocComment && node.key?.name) {
23
23
  const isPrivate = node.key.name.startsWith("__");
24
24
  const isProtected = node.key.name.startsWith("_") && !node.key.name.startsWith("__");
25
25
  const isPublicJsDoc = jsDocComment.value.includes("@public");
@@ -0,0 +1,158 @@
1
+ export default {
2
+ meta: {
3
+ type: "suggestion",
4
+ docs: {
5
+ description: "disallow snake_case in declared arguments, variables, and methods (allows _ or __ prefixes)",
6
+ category: "Stylistic Issues",
7
+ recommended: false
8
+ },
9
+ schema: [] // no options
10
+ },
11
+
12
+ create(context) {
13
+ /**
14
+ * Check if a name is snake_case (after removing allowed prefixes)
15
+ * @param {string} name - The identifier name to check
16
+ * @param {boolean} isConstant - Whether this is a constant declaration
17
+ * @returns {boolean} - True if the name is snake_case
18
+ */
19
+ function isSnakeCase(name, isConstant = false) {
20
+ // Remove allowed prefixes (_ or __)
21
+ let cleanName = name;
22
+ if (name.startsWith('__')) {
23
+ cleanName = name.slice(2);
24
+ } else if (name.startsWith('_')) {
25
+ cleanName = name.slice(1);
26
+ }
27
+
28
+ // Allow UPPER_SNAKE_CASE for constants
29
+ if (isConstant && cleanName === cleanName.toUpperCase() && /^[A-Z][A-Z0-9_]*$/.test(cleanName)) {
30
+ return false;
31
+ }
32
+
33
+ // Check if the remaining name contains underscores (indicating snake_case)
34
+ return cleanName.includes('_');
35
+ }
36
+
37
+ /**
38
+ * Report snake_case violation
39
+ * @param {Object} node - The AST node
40
+ * @param {string} name - The identifier name
41
+ * @param {string} type - The type of identifier (variable, parameter, method, etc.)
42
+ */
43
+ function reportSnakeCase(node, name, type) {
44
+ context.report({
45
+ node: node,
46
+ message: `${type} '${name}' should not use snake_case. Use camelCase instead.`
47
+ });
48
+ }
49
+
50
+ return {
51
+ // Check variable declarations
52
+ VariableDeclaration(node) {
53
+ node.declarations.forEach((declaration) => {
54
+ if (declaration.id && declaration.id.name) {
55
+ const name = declaration.id.name;
56
+ const isConstant = node.kind === 'const';
57
+ if (isSnakeCase(name, isConstant)) {
58
+ reportSnakeCase(declaration, name, 'Variable');
59
+ }
60
+ }
61
+ });
62
+ },
63
+
64
+ // Check function declarations
65
+ FunctionDeclaration(node) {
66
+ if (node.id && node.id.name) {
67
+ const name = node.id.name;
68
+ if (isSnakeCase(name)) {
69
+ reportSnakeCase(node, name, 'Function');
70
+ }
71
+ }
72
+
73
+ // Check function parameters
74
+ node.params.forEach((param) => {
75
+ if (param.type === 'Identifier' && param.name) {
76
+ const name = param.name;
77
+ if (isSnakeCase(name)) {
78
+ reportSnakeCase(param, name, 'Parameter');
79
+ }
80
+ }
81
+ });
82
+ },
83
+
84
+ // Check method definitions (class methods)
85
+ MethodDefinition(node) {
86
+ if (node.key && node.key.name) {
87
+ const name = node.key.name;
88
+ if (isSnakeCase(name)) {
89
+ reportSnakeCase(node, name, 'Method');
90
+ }
91
+ }
92
+
93
+ // Check method parameters
94
+ if (node.value && node.value.params) {
95
+ node.value.params.forEach((param) => {
96
+ if (param.type === 'Identifier' && param.name) {
97
+ const name = param.name;
98
+ if (isSnakeCase(name)) {
99
+ reportSnakeCase(param, name, 'Parameter');
100
+ }
101
+ }
102
+ });
103
+ }
104
+ },
105
+
106
+ // Check function expressions
107
+ FunctionExpression(node) {
108
+ // Check function parameters
109
+ node.params.forEach((param) => {
110
+ if (param.type === 'Identifier' && param.name) {
111
+ const name = param.name;
112
+ if (isSnakeCase(name)) {
113
+ reportSnakeCase(param, name, 'Parameter');
114
+ }
115
+ }
116
+ });
117
+ },
118
+
119
+ // Check arrow function expressions
120
+ ArrowFunctionExpression(node) {
121
+ // Check function parameters
122
+ node.params.forEach((param) => {
123
+ if (param.type === 'Identifier' && param.name) {
124
+ const name = param.name;
125
+ if (isSnakeCase(name)) {
126
+ reportSnakeCase(param, name, 'Parameter');
127
+ }
128
+ }
129
+ });
130
+ },
131
+
132
+ // Check object method properties
133
+ Property(node) {
134
+ // Check if it's a method property
135
+ if (node.method || (node.value && (node.value.type === 'FunctionExpression' || node.value.type === 'ArrowFunctionExpression'))) {
136
+ if (node.key && node.key.name) {
137
+ const name = node.key.name;
138
+ if (isSnakeCase(name)) {
139
+ reportSnakeCase(node, name, 'Method');
140
+ }
141
+ }
142
+
143
+ // Check method parameters
144
+ if (node.value && node.value.params) {
145
+ node.value.params.forEach((param) => {
146
+ if (param.type === 'Identifier' && param.name) {
147
+ const name = param.name;
148
+ if (isSnakeCase(name)) {
149
+ reportSnakeCase(param, name, 'Parameter');
150
+ }
151
+ }
152
+ });
153
+ }
154
+ }
155
+ }
156
+ };
157
+ }
158
+ };