eslint-plugin-crisp 1.3.6 → 1.4.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/package.json +1 -1
- package/recommended.js +1 -1
- package/rules/align-comments.js +1 -1
- package/rules/enforce-optional.js +7 -3
- package/rules/header-check.js +2 -4
- package/rules/header-comments-check.js +17 -3
- package/rules/import-group-comment.js +9 -4
- package/rules/jsdoc-enforce-access.js +12 -7
- package/rules/methods-ordering.js +6 -2
- package/rules/no-snake-case.js +4 -1
- package/rules/one-space-after-operator.js +1 -1
- package/rules/vue-ref-case.js +4 -1
package/package.json
CHANGED
package/recommended.js
CHANGED
|
@@ -94,7 +94,7 @@ export default function configRecommended(pluginCrisp) {
|
|
|
94
94
|
"linebreak-style": ["error", "unix"],
|
|
95
95
|
"max-len": ["error", {
|
|
96
96
|
"code": 80,
|
|
97
|
-
"ignorePattern": "
|
|
97
|
+
"ignorePattern": "^\\/\\*\\* \@import"
|
|
98
98
|
}],
|
|
99
99
|
"no-console": "warn",
|
|
100
100
|
"no-debugger": "warn",
|
package/rules/align-comments.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Pre-compiled patterns for exclusion checks (avoid creating regex in loop)
|
|
2
|
+
const OBJECT_METHODS_PATTERN = /Object\.(keys|values|entries)\(/;
|
|
3
|
+
const ARRAY_METHODS_PATTERN = /Array\.(from)\(/;
|
|
4
|
+
|
|
1
5
|
export default {
|
|
2
6
|
meta: {
|
|
3
7
|
type: "problem",
|
|
@@ -10,7 +14,7 @@ export default {
|
|
|
10
14
|
},
|
|
11
15
|
|
|
12
16
|
create(context) {
|
|
13
|
-
const sourceCode = context.getSourceCode();
|
|
17
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
14
18
|
|
|
15
19
|
const patterns = [
|
|
16
20
|
// Search for `foo && foo.` or `foo && foo[`
|
|
@@ -44,8 +48,8 @@ export default {
|
|
|
44
48
|
|
|
45
49
|
if (
|
|
46
50
|
index === 1 &&
|
|
47
|
-
(
|
|
48
|
-
|
|
51
|
+
(OBJECT_METHODS_PATTERN.test(match[1]) ||
|
|
52
|
+
ARRAY_METHODS_PATTERN.test(match[1]))
|
|
49
53
|
) {
|
|
50
54
|
// Ignore `Object.keys(foo || {})` (and others) as it cannot be \
|
|
51
55
|
// safely transformed to optional chaining
|
package/rules/header-check.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
1
|
import path from "path";
|
|
3
2
|
|
|
4
3
|
export default {
|
|
@@ -29,10 +28,9 @@ export default {
|
|
|
29
28
|
Program(node) {
|
|
30
29
|
const options = context.options[0] || {};
|
|
31
30
|
const fileName = context.getFilename();
|
|
31
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
32
32
|
|
|
33
|
-
let fileContent =
|
|
34
|
-
|
|
35
|
-
fileContent = fileContent.trim();
|
|
33
|
+
let fileContent = sourceCode.getText().trim();
|
|
36
34
|
|
|
37
35
|
// Determine the file extension
|
|
38
36
|
const fileExtension = path.extname(fileName);
|
|
@@ -20,6 +20,12 @@ export default {
|
|
|
20
20
|
let lastNode = null;
|
|
21
21
|
let groupStart = null;
|
|
22
22
|
|
|
23
|
+
// Cache all block comments once at start (sorted by position for fast lookup)
|
|
24
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
25
|
+
const allBlockComments = sourceCode.getAllComments()
|
|
26
|
+
.filter(c => c.type === "Block")
|
|
27
|
+
.sort((a, b) => a.range[0] - b.range[0]);
|
|
28
|
+
|
|
23
29
|
// This function formats the section string into a comment block header
|
|
24
30
|
const COMMENT_HEADER_FORMAT = (section) => {
|
|
25
31
|
return `/**************************************************************************\n * ${section.toUpperCase()}\n ***************************************************************************/`;
|
|
@@ -79,9 +85,17 @@ export default {
|
|
|
79
85
|
return;
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
// Find the nearest Block Comment before the startNode
|
|
83
|
-
const
|
|
84
|
-
|
|
88
|
+
// Find the nearest Block Comment before the startNode (using cached comments)
|
|
89
|
+
const nodeStart = startNode.range[0];
|
|
90
|
+
let comment = null;
|
|
91
|
+
|
|
92
|
+
for (let i = allBlockComments.length - 1; i >= 0; i--) {
|
|
93
|
+
if (allBlockComments[i].range[1] < nodeStart) {
|
|
94
|
+
comment = allBlockComments[i];
|
|
95
|
+
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
85
99
|
|
|
86
100
|
// Different types of nodes require different comment blocks
|
|
87
101
|
switch (nodeType) {
|
|
@@ -20,6 +20,11 @@ export default {
|
|
|
20
20
|
create(context) {
|
|
21
21
|
const customGroups = context.options[0] || {}; // Get custom groups from options
|
|
22
22
|
|
|
23
|
+
// Pre-compile custom regexes once instead of on every import
|
|
24
|
+
const compiledCustomGroups = Object.entries(customGroups).map(
|
|
25
|
+
([regexStr, group]) => [new RegExp(regexStr), group]
|
|
26
|
+
);
|
|
27
|
+
|
|
23
28
|
let currentGroupComment = null;
|
|
24
29
|
|
|
25
30
|
// Extract the directory name from the file path
|
|
@@ -29,10 +34,10 @@ export default {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
function extractGroupFromPath(path, filePath) {
|
|
32
|
-
// Check custom regexes first
|
|
33
|
-
for (const
|
|
34
|
-
if (
|
|
35
|
-
return
|
|
37
|
+
// Check custom regexes first (using pre-compiled patterns)
|
|
38
|
+
for (const [regex, group] of compiledCustomGroups) {
|
|
39
|
+
if (regex.test(path)) {
|
|
40
|
+
return group;
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
43
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Pre-compiled regex for access modifier check
|
|
2
|
+
const ACCESS_MODIFIER_PATTERN = /@(public|protected|private)/;
|
|
3
|
+
|
|
1
4
|
export default {
|
|
2
5
|
meta: {
|
|
3
6
|
type: "problem",
|
|
@@ -9,14 +12,16 @@ export default {
|
|
|
9
12
|
},
|
|
10
13
|
|
|
11
14
|
create: function(context) {
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
16
|
+
|
|
17
|
+
function checkNodeForJSDoc(node) {
|
|
18
|
+
const comments = sourceCode.getCommentsBefore(node);
|
|
14
19
|
|
|
15
20
|
if (comments.length > 0) {
|
|
16
21
|
const lastComment = comments[comments.length - 1];
|
|
17
22
|
|
|
18
23
|
if (lastComment.type === "Block" && lastComment.value.startsWith("*")) {
|
|
19
|
-
if (
|
|
24
|
+
if (!ACCESS_MODIFIER_PATTERN.test(lastComment.value)) {
|
|
20
25
|
context.report({
|
|
21
26
|
node,
|
|
22
27
|
message: "JSDoc comment should contain @public, @protected or @private",
|
|
@@ -33,20 +38,20 @@ export default {
|
|
|
33
38
|
Property(node) {
|
|
34
39
|
if (node.value.type === "FunctionExpression" ||
|
|
35
40
|
node.value.type === "ArrowFunctionExpression") {
|
|
36
|
-
checkNodeForJSDoc(node
|
|
41
|
+
checkNodeForJSDoc(node);
|
|
37
42
|
}
|
|
38
43
|
},
|
|
39
44
|
|
|
40
45
|
MethodDefinition(node) {
|
|
41
|
-
checkNodeForJSDoc(node
|
|
46
|
+
checkNodeForJSDoc(node);
|
|
42
47
|
},
|
|
43
48
|
|
|
44
49
|
FunctionDeclaration(node) {
|
|
45
|
-
checkNodeForJSDoc(node
|
|
50
|
+
checkNodeForJSDoc(node);
|
|
46
51
|
},
|
|
47
52
|
|
|
48
53
|
FunctionExpression(node) {
|
|
49
|
-
checkNodeForJSDoc(node
|
|
54
|
+
checkNodeForJSDoc(node);
|
|
50
55
|
},
|
|
51
56
|
};
|
|
52
57
|
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import doctrine from "doctrine";
|
|
2
2
|
|
|
3
|
+
// Pre-compiled regex for section comment matching
|
|
4
|
+
const SECTION_COMMENT_PATTERN = /--> (.*) <--/;
|
|
5
|
+
|
|
3
6
|
export default {
|
|
4
7
|
create(context) {
|
|
5
8
|
let methodOrder = []; // Keep track of method order
|
|
9
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
6
10
|
|
|
7
11
|
return {
|
|
8
12
|
MethodDefinition(node) {
|
|
9
|
-
const commentsBefore =
|
|
13
|
+
const commentsBefore = sourceCode.getCommentsBefore(node);
|
|
10
14
|
|
|
11
15
|
// Check if there is a comment matching `--> {VALUE} <--` before the node
|
|
12
|
-
const nodeComment = commentsBefore.find(comment => comment.type === "Line" &&
|
|
16
|
+
const nodeComment = commentsBefore.find(comment => comment.type === "Line" && SECTION_COMMENT_PATTERN.test(comment.value));
|
|
13
17
|
|
|
14
18
|
// Reset methodOrder if a matching comment was found
|
|
15
19
|
if (nodeComment) {
|
package/rules/no-snake-case.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Pre-compiled regex for constant naming check
|
|
2
|
+
const UPPER_SNAKE_CASE_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
3
|
+
|
|
1
4
|
export default {
|
|
2
5
|
meta: {
|
|
3
6
|
type: "suggestion",
|
|
@@ -26,7 +29,7 @@ export default {
|
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
// Allow UPPER_SNAKE_CASE for constants
|
|
29
|
-
if (isConstant && cleanName === cleanName.toUpperCase() &&
|
|
32
|
+
if (isConstant && cleanName === cleanName.toUpperCase() && UPPER_SNAKE_CASE_PATTERN.test(cleanName)) {
|
|
30
33
|
return false;
|
|
31
34
|
}
|
|
32
35
|
|
|
@@ -23,7 +23,7 @@ export default {
|
|
|
23
23
|
]
|
|
24
24
|
},
|
|
25
25
|
create(context) {
|
|
26
|
-
const sourceCode = context.getSourceCode();
|
|
26
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
27
27
|
const config = context.options[0] || {};
|
|
28
28
|
const checkColon = config.checkColon !== false;
|
|
29
29
|
|
package/rules/vue-ref-case.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import utils from "eslint-plugin-vue/dist/utils/index.js";
|
|
2
2
|
|
|
3
|
+
// Pre-compiled regex for snake_case ref validation
|
|
4
|
+
const SNAKE_CASE_REF_PATTERN = /^[a-z]+(_[a-z]+)*$/;
|
|
5
|
+
|
|
3
6
|
export default {
|
|
4
7
|
meta: {
|
|
5
8
|
type: "layout",
|
|
@@ -18,7 +21,7 @@ export default {
|
|
|
18
21
|
if (node.value && node.value.type === "VLiteral") {
|
|
19
22
|
const refValue = node.value.value;
|
|
20
23
|
|
|
21
|
-
if (refValue &&
|
|
24
|
+
if (refValue && !SNAKE_CASE_REF_PATTERN.test(refValue)) {
|
|
22
25
|
context.report({
|
|
23
26
|
node,
|
|
24
27
|
message: "Ref attribute \"{{refValue}}\" should be snake-cased.",
|