eslint-plugin-crisp 1.5.13 → 1.6.1

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 (88) hide show
  1. package/.github/workflows/build.yml +6 -0
  2. package/README.md +2 -1
  3. package/index.js +2 -0
  4. package/package.json +9 -1
  5. package/recommended-vue.js +1 -0
  6. package/rules/align-comments.js +6 -3
  7. package/rules/constructor-variables.js +17 -2
  8. package/rules/header-check.js +8 -2
  9. package/rules/header-comments-check.js +10 -13
  10. package/rules/import-group-comment.js +13 -4
  11. package/rules/jsdoc-enforce-access.js +16 -10
  12. package/rules/no-extra-line-within-function.js +8 -5
  13. package/rules/no-short-parameters.js +1 -1
  14. package/rules/no-snake-case.js +0 -24
  15. package/rules/no-space-in-optional-arguments.js +5 -2
  16. package/rules/one-space-after-operator.js +59 -14
  17. package/rules/vue-header-check.js +4 -3
  18. package/rules/vue-no-regex-data.js +1 -2
  19. package/rules/vue-pinia-action-single-parameter.js +158 -0
  20. package/rules/vue-props-declaration-line-break.js +8 -3
  21. package/rules/vue-watch-handler.js +34 -1
  22. package/tests/fixtures/vue-header-check/missing-script-style/TestComponent.vue +19 -0
  23. package/tests/fixtures/vue-header-check/missing-template/TestComponent.vue +3 -0
  24. package/tests/fixtures/vue-header-check/valid/TestComponent.vue +27 -0
  25. package/tests/rule-tester.js +78 -0
  26. package/tests/rules/align-comments.test.js +25 -0
  27. package/tests/rules/align-consecutive-class-assignements.test.js +24 -0
  28. package/tests/rules/align-one-var.test.js +31 -0
  29. package/tests/rules/align-requires.test.js +27 -0
  30. package/tests/rules/arrow-block-newline.test.js +23 -0
  31. package/tests/rules/consecutive-line-comments.test.js +27 -0
  32. package/tests/rules/const.test.js +52 -0
  33. package/tests/rules/constructor-variables.test.js +52 -0
  34. package/tests/rules/enforce-optional.test.js +24 -0
  35. package/tests/rules/header-check.test.js +69 -0
  36. package/tests/rules/header-comments-check.test.js +89 -0
  37. package/tests/rules/import-group-comment.test.js +88 -0
  38. package/tests/rules/import-group-order.test.js +58 -0
  39. package/tests/rules/jsdoc-align-params.test.js +32 -0
  40. package/tests/rules/jsdoc-check-indentation.test.js +45 -0
  41. package/tests/rules/jsdoc-check-optional-params.test.js +40 -0
  42. package/tests/rules/jsdoc-description-length.test.js +60 -0
  43. package/tests/rules/jsdoc-description-multiline.test.js +34 -0
  44. package/tests/rules/jsdoc-enforce-access.test.js +66 -0
  45. package/tests/rules/jsdoc-enforce-classdesc.test.js +39 -0
  46. package/tests/rules/jsdoc-no-param-return.test.js +47 -0
  47. package/tests/rules/jsdoc-require-description-uppercase.test.js +52 -0
  48. package/tests/rules/methods-naming.test.js +70 -0
  49. package/tests/rules/methods-ordering.test.js +75 -0
  50. package/tests/rules/multiline-comment-end-backslash.test.js +52 -0
  51. package/tests/rules/newline-after-switch-case.test.js +75 -0
  52. package/tests/rules/no-async.test.js +57 -0
  53. package/tests/rules/no-extra-line-within-function.test.js +87 -0
  54. package/tests/rules/no-inline-function-in-ternary.test.js +59 -0
  55. package/tests/rules/no-short-parameters.test.js +62 -0
  56. package/tests/rules/no-snake-case.test.js +81 -0
  57. package/tests/rules/no-space-in-optional-arguments.test.js +40 -0
  58. package/tests/rules/no-useless-template-literals.test.js +36 -0
  59. package/tests/rules/no-var-in-blocks.test.js +40 -0
  60. package/tests/rules/one-space-after-operator.test.js +69 -0
  61. package/tests/rules/regex-in-constructor.test.js +40 -0
  62. package/tests/rules/ternary-parenthesis.test.js +34 -0
  63. package/tests/rules/two-lines-between-class-members.test.js +62 -0
  64. package/tests/rules/variable-names.test.js +60 -0
  65. package/tests/rules/vue-attribute-comma.test.js +43 -0
  66. package/tests/rules/vue-attribute-linebreak.test.js +54 -0
  67. package/tests/rules/vue-class-attribute-last.test.js +59 -0
  68. package/tests/rules/vue-class-shorthand-max-len.test.js +67 -0
  69. package/tests/rules/vue-computed-order.test.js +27 -0
  70. package/tests/rules/vue-data-comment.test.js +61 -0
  71. package/tests/rules/vue-define-component.test.js +45 -0
  72. package/tests/rules/vue-emits-order.test.js +27 -0
  73. package/tests/rules/vue-header-check.test.js +49 -0
  74. package/tests/rules/vue-html-indent.test.js +77 -0
  75. package/tests/rules/vue-html-quotes.test.js +71 -0
  76. package/tests/rules/vue-methods-separator.test.js +55 -0
  77. package/tests/rules/vue-name-prop.test.js +59 -0
  78. package/tests/rules/vue-no-component-class-shorthand.test.js +49 -0
  79. package/tests/rules/vue-no-mixed-class.test.js +56 -0
  80. package/tests/rules/vue-no-name-option.test.js +44 -0
  81. package/tests/rules/vue-no-regex-data.test.js +39 -0
  82. package/tests/rules/vue-pinia-action-single-parameter.test.js +234 -0
  83. package/tests/rules/vue-props-declaration-line-break.test.js +68 -0
  84. package/tests/rules/vue-props-declaration-multiline.test.js +40 -0
  85. package/tests/rules/vue-props-declaration-order.test.js +27 -0
  86. package/tests/rules/vue-ref-case.test.js +40 -0
  87. package/tests/rules/vue-watch-handler.test.js +89 -0
  88. package/tests/rules-coverage.test.js +19 -0
@@ -28,9 +28,14 @@ export default {
28
28
  fix(fixer) {
29
29
  const typeToken = sourceCode.getLastToken(typeProperty);
30
30
  const defaultToken = sourceCode.getFirstToken(defaultProperty);
31
- const textBetween = sourceCode.text.slice(typeToken.range[1], defaultToken.range[0]);
32
- const newTextBetween = textBetween.replace(/,?\s*/, ",\n\n");
33
- return fixer.replaceTextRange([typeToken.range[1], defaultToken.range[0]], newTextBetween);
31
+ const typeLine = sourceCode.lines[typeProperty.loc.start.line - 1];
32
+ const leadingText = typeLine.slice(0, typeProperty.loc.start.column);
33
+ const indent = leadingText.trim() === "" ? leadingText : "";
34
+
35
+ return fixer.replaceTextRange(
36
+ [typeToken.range[1], defaultToken.range[0]],
37
+ `,\n\n${indent}`
38
+ );
34
39
  }
35
40
  });
36
41
  }
@@ -30,6 +30,29 @@ function hasValidSignature(handler) {
30
30
  });
31
31
  }
32
32
 
33
+ function isDefineComponentCall(node) {
34
+ if (!node || node.type !== "CallExpression") {
35
+ return false;
36
+ }
37
+
38
+ return (
39
+ (node.callee.type === "Identifier" && node.callee.name === "defineComponent") ||
40
+ (
41
+ node.callee.type === "MemberExpression" &&
42
+ !node.callee.computed &&
43
+ node.callee.property.type === "Identifier" &&
44
+ node.callee.property.name === "defineComponent"
45
+ )
46
+ );
47
+ }
48
+
49
+ function isVueOptionsObject(node) {
50
+ return (
51
+ node.parent.type === "ExportDefaultDeclaration" ||
52
+ isDefineComponentCall(node.parent)
53
+ );
54
+ }
55
+
33
56
  export default {
34
57
  meta: {
35
58
  type: "suggestion",
@@ -52,7 +75,17 @@ export default {
52
75
 
53
76
  create(context) {
54
77
  return {
55
- 'Property[key.name="watch"] > ObjectExpression'(node) {
78
+ "Property > ObjectExpression"(node) {
79
+ const watchProperty = node.parent;
80
+ const optionsObject = watchProperty.parent;
81
+
82
+ if (
83
+ getPropertyName(watchProperty) !== "watch" ||
84
+ !isVueOptionsObject(optionsObject)
85
+ ) {
86
+ return;
87
+ }
88
+
56
89
  node.properties.forEach((watcher) => {
57
90
  if (watcher.type !== "Property") {
58
91
  return;
@@ -0,0 +1,19 @@
1
+
2
+
3
+ <!-- **********************************************************************
4
+ TEMPLATE
5
+ ********************************************************************** -->
6
+
7
+ <template>
8
+ <main>Partial headers</main>
9
+ </template>
10
+
11
+ <script setup>
12
+ const ready = false;
13
+ </script>
14
+
15
+ <style scoped>
16
+ main {
17
+ display: block;
18
+ }
19
+ </style>
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <main>Missing header</main>
3
+ </template>
@@ -0,0 +1,27 @@
1
+ <!-- **********************************************************************
2
+ TEMPLATE
3
+ ********************************************************************** -->
4
+
5
+ <template>
6
+ <main>Ready</main>
7
+ </template>
8
+
9
+
10
+ <!-- **********************************************************************
11
+ SCRIPT
12
+ ********************************************************************** -->
13
+
14
+ <script setup>
15
+ const ready = true;
16
+ </script>
17
+
18
+
19
+ <!-- **********************************************************************
20
+ STYLE
21
+ ********************************************************************** -->
22
+
23
+ <style scoped>
24
+ main {
25
+ display: block;
26
+ }
27
+ </style>
@@ -0,0 +1,78 @@
1
+ import { RuleTester } from "eslint";
2
+ import { describe, it } from "node:test";
3
+ import vueParser from "vue-eslint-parser";
4
+
5
+ RuleTester.describe = describe;
6
+ RuleTester.it = it;
7
+ RuleTester.itOnly = it.only;
8
+
9
+ export default function createRuleTester({
10
+ languageOptions = {},
11
+
12
+ ...options
13
+ } = {}) {
14
+ return new RuleTester({
15
+ ...options,
16
+
17
+ languageOptions: {
18
+ ecmaVersion: "latest",
19
+ sourceType: "module",
20
+
21
+ ...languageOptions
22
+ }
23
+ });
24
+ }
25
+
26
+ export function createVueRuleTester(options = {}) {
27
+ return createRuleTester({
28
+ ...options,
29
+
30
+ languageOptions: {
31
+ ...options.languageOptions,
32
+
33
+ parser: vueParser
34
+ }
35
+ });
36
+ }
37
+
38
+ export function createPugRuleTester(options = {}) {
39
+ return createVueRuleTester({
40
+ ...options,
41
+
42
+ languageOptions: {
43
+ ...options.languageOptions,
44
+
45
+ parserOptions: {
46
+ ...options.languageOptions?.parserOptions,
47
+
48
+ templateTokenizer: {
49
+ pug: "vue-eslint-parser-template-tokenizer-pug"
50
+ }
51
+ }
52
+ }
53
+ });
54
+ }
55
+
56
+ export function withoutFixes(rule) {
57
+ const { fixable, ...meta } = rule.meta || {};
58
+
59
+ return {
60
+ ...rule,
61
+
62
+ meta,
63
+
64
+ create(context) {
65
+ const reportOnlyContext = Object.create(context);
66
+
67
+ Object.defineProperty(reportOnlyContext, "report", {
68
+ value(descriptor) {
69
+ const { fix, ...report } = descriptor;
70
+
71
+ context.report(report);
72
+ }
73
+ });
74
+
75
+ return rule.create(reportOnlyContext);
76
+ }
77
+ };
78
+ }
@@ -0,0 +1,25 @@
1
+ import rule from "../../rules/align-comments.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("align-comments", rule, {
7
+ valid: [
8
+ "// A top-level value\nconst value = 1;",
9
+ "function example() {\n // Return the value\n return true;\n}",
10
+ "const previous = 1; // Keep this inline\nconst next = 2;",
11
+ "const callback = () => {\n // Invoke the callback\n callback();\n};"
12
+ ],
13
+
14
+ invalid: [
15
+ {
16
+ code: "function example() {\n// Misaligned\n return true;\n}",
17
+ output: "function example() {\n // Misaligned\n return true;\n}",
18
+ errors: [
19
+ {
20
+ message: "Comment should be aligned with the next line."
21
+ }
22
+ ]
23
+ }
24
+ ]
25
+ });
@@ -0,0 +1,24 @@
1
+ import rule from "../../rules/align-consecutive-class-assignements.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("align-consecutive-class-assignements", rule, {
7
+ valid: [
8
+ "class Example {\n constructor() {\n this.a = 1;\n this.long = 2;\n }\n}",
9
+ "class Example {\n constructor() {\n this.a = 1;\n\n this.long = 2;\n }\n}",
10
+ "class Example {\n method() {\n this.a = 1;\n this.long = 2;\n }\n}"
11
+ ],
12
+
13
+ invalid: [
14
+ {
15
+ code: "class Example {\n constructor() {\n this.a = 1;\n this.long = 2;\n }\n}",
16
+ errors: [
17
+ {
18
+ message:
19
+ "Assignment of 'this.a' at line 3 column 12 should be aligned at column 15"
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ });
@@ -0,0 +1,31 @@
1
+ import rule from "../../rules/align-one-var.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("align-one-var", rule, {
7
+ valid: [
8
+ "const first = 1,\n next = 2;",
9
+ "const first = 1, next = 2;",
10
+ "let first,\n next;"
11
+ ],
12
+
13
+ invalid: [
14
+ {
15
+ code: "const first = 1,\n next = 2;",
16
+ errors: [
17
+ {
18
+ message: "Misaligned variable declaration."
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ code: "const first = 1,\n next = 2;",
24
+ errors: [
25
+ {
26
+ message: "Misaligned assignment operator."
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ });
@@ -0,0 +1,27 @@
1
+ import rule from "../../rules/align-requires.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester({
5
+ languageOptions: {
6
+ sourceType: "commonjs"
7
+ }
8
+ });
9
+
10
+ ruleTester.run("align-requires", rule, {
11
+ valid: [
12
+ "const alpha = require(\"alpha\"),\n beta = require(\"beta\");",
13
+ "const alpha = require(\"alpha\");\nconst beta = require(\"beta\");",
14
+ "const alpha = require(\"alpha\"), value = 1,\n beta = require(\"beta\");"
15
+ ],
16
+
17
+ invalid: [
18
+ {
19
+ code: "const alpha = require(\"alpha\"),\n beta = require(\"beta\");",
20
+ errors: [
21
+ {
22
+ message: "Misaligned require statement."
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ });
@@ -0,0 +1,23 @@
1
+ import rule from "../../rules/arrow-block-newline.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("arrow-block-newline", rule, {
7
+ valid: [
8
+ "const callback = () => {};",
9
+ "const callback = () => {\n return true;\n};",
10
+ "const callback = () => true;"
11
+ ],
12
+
13
+ invalid: [
14
+ {
15
+ code: "const callback = () => { return true;\n};",
16
+ errors: [
17
+ {
18
+ messageId: "expectedNewline"
19
+ }
20
+ ]
21
+ }
22
+ ]
23
+ });
@@ -0,0 +1,27 @@
1
+ import rule from "../../rules/consecutive-line-comments.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ const lines = (...values) => values.join("\n");
7
+
8
+ ruleTester.run("consecutive-line-comments", rule, {
9
+ valid: [
10
+ lines("// First line \\", "// second line", "const value = 1;"),
11
+ lines("// First comment", "// Second comment", "const value = 1;"),
12
+ lines("// eslint-disable-next-line no-console", "console.log(\"value\");"),
13
+ lines("// Intro \\", "// Important: separate block", "const value = 1;")
14
+ ],
15
+
16
+ invalid: [
17
+ {
18
+ code: lines("// First line \\", "// Second line", "const value = 1;"),
19
+ output: lines("// First line \\", "// Second line", "const value = 1;"),
20
+ errors: [
21
+ {
22
+ messageId: "format"
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ });
@@ -0,0 +1,52 @@
1
+ import rule from "../../rules/const.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("const", rule, {
7
+ valid: [
8
+ "const MAXIMUM = 10;",
9
+ "const client = createClient();",
10
+ "const callback = () => true;",
11
+ "function example() {\n const __CACHE = 1;\n}",
12
+ {
13
+ code: "function example() {\n const cache = 1;\n}",
14
+ options: [
15
+ {
16
+ exceptions: ["cache"]
17
+ }
18
+ ]
19
+ },
20
+ "export const publicValue = 1;"
21
+ ],
22
+
23
+ invalid: [
24
+ {
25
+ code: "const value = 1;",
26
+ errors: [
27
+ {
28
+ message:
29
+ "Consts should be uppercase and defined at the top level or be replaced with let _variable (Crisp convention)."
30
+ }
31
+ ]
32
+ },
33
+ {
34
+ code: "function example() {\n const _cache = 1;\n}",
35
+ output: "function example() {\n let _cache = 1;\n}",
36
+ errors: [
37
+ {
38
+ message: "Local variables prefixed with \"_\" should use \"let\"."
39
+ }
40
+ ]
41
+ },
42
+ {
43
+ code: "function example() {\n const value = 1;\n}",
44
+ errors: [
45
+ {
46
+ message:
47
+ "Consts should be uppercase and defined at the top level or be replaced with let _variable (Crisp convention)."
48
+ }
49
+ ]
50
+ }
51
+ ]
52
+ });
@@ -0,0 +1,52 @@
1
+ import rule from "../../rules/constructor-variables.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("constructor-variables", rule, {
7
+ valid: [
8
+ "class Example {\n constructor() {\n this._value = 1;\n }\n}",
9
+ {
10
+ code: "class Example {\n constructor() {\n this.value = 1;\n }\n}",
11
+ options: [
12
+ {
13
+ variableExceptions: ["value"]
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ code: "class Example {\n constructor() {\n this.value = 1;\n }\n}",
19
+ filename: "/project/special-file.js",
20
+ options: [
21
+ {
22
+ filenameExceptions: ["special-file.js"]
23
+ }
24
+ ]
25
+ },
26
+ "class Example {\n method() {\n this.value = 1;\n }\n}",
27
+ "class Example {\n constructor() {\n this[\"_value\"] = 1;\n }\n}",
28
+ "class Example {\n constructor() {\n this[propertyName] = 1;\n }\n}"
29
+ ],
30
+
31
+ invalid: [
32
+ {
33
+ code: "class Example {\n constructor() {\n this.value = 1;\n }\n}",
34
+ filename: "/project/example.js",
35
+ errors: [
36
+ {
37
+ message:
38
+ "Class properties in the constructor should start with '_', except for specified exceptions"
39
+ }
40
+ ]
41
+ },
42
+ {
43
+ code: "class Example {\n constructor() {\n this[\"value\"] = 1;\n }\n}",
44
+ errors: [
45
+ {
46
+ message:
47
+ "Class properties in the constructor should start with '_', except for specified exceptions"
48
+ }
49
+ ]
50
+ }
51
+ ]
52
+ });
@@ -0,0 +1,24 @@
1
+ import rule from "../../rules/enforce-optional.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("enforce-optional", rule, {
7
+ valid: [
8
+ "const result = foo?.bar;",
9
+ "const result = foo && foo.bar !== null;",
10
+ "const keys = Object.keys(foo || {});",
11
+ "const filtered = (foo || []).filter(Boolean);"
12
+ ],
13
+
14
+ invalid: [
15
+ {
16
+ code: "const result = foo && foo.bar;",
17
+ errors: [
18
+ {
19
+ message: /Prefer using optional chaining rather than/
20
+ }
21
+ ]
22
+ }
23
+ ]
24
+ });
@@ -0,0 +1,69 @@
1
+ import rule from "../../rules/header-check.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+
6
+ ruleTester.run("header-check", rule, {
7
+ valid: [
8
+ {
9
+ code:
10
+ "/*\n * This file is part of Example\n *\n" +
11
+ " * Copyright (c) 2026 Crisp IM SAS\n" +
12
+ " * All rights belong to Crisp IM SAS\n */\nconst VALUE = 1;",
13
+ filename: "/project/example.js"
14
+ },
15
+ {
16
+ code: "/* Custom header */\nconst VALUE = 1;",
17
+ filename: "/project/example.ts",
18
+ options: [
19
+ {
20
+ patterns: [" Custom header "]
21
+ }
22
+ ]
23
+ },
24
+ {
25
+ code: "const VALUE = 1;",
26
+ filename: "/project/example.txt"
27
+ }
28
+ ],
29
+
30
+ invalid: [
31
+ {
32
+ code: "const VALUE = 1;",
33
+ filename: "/project/example.js",
34
+ errors: [
35
+ {
36
+ message: "File must start with the proper header."
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ code: "/* Wrong header */\nconst VALUE = 1;",
42
+ filename: "/project/example.ts",
43
+ options: [
44
+ {
45
+ patterns: [" Expected header "]
46
+ }
47
+ ],
48
+ errors: [
49
+ {
50
+ message: "File must start with the proper header."
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ code: "const VALUE = 1;",
56
+ filename: "/project/example.js",
57
+ options: [
58
+ {
59
+ patterns: ["["]
60
+ }
61
+ ],
62
+ errors: [
63
+ {
64
+ message: "File must start with the proper header."
65
+ }
66
+ ]
67
+ }
68
+ ]
69
+ });
@@ -0,0 +1,89 @@
1
+ import rule from "../../rules/header-comments-check.js";
2
+ import createRuleTester from "../rule-tester.js";
3
+
4
+ const ruleTester = createRuleTester();
5
+ const header = (name) => [
6
+ "/**************************************************************************",
7
+ ` * ${name}`,
8
+ " ***************************************************************************/"
9
+ ].join("\n");
10
+
11
+ ruleTester.run("header-comments-check", rule, {
12
+ valid: [
13
+ {
14
+ filename: "/project/src/example.js",
15
+ code: `${header("IMPORTS")}\nimport value from "package";`
16
+ },
17
+ {
18
+ filename: "/project/src/example.ts",
19
+ code: `${header("CONSTANTS")}\nconst MAX_RETRIES = 3;\n\n${header("INSTANCES")}\nconst pattern = /value/;`
20
+ },
21
+ {
22
+ filename: "/project/src/example.js",
23
+ code:
24
+ `${header("TYPES")}\n/** @typedef {string} Identifier */\n\n` +
25
+ `${header("EXPORTS")}\nexport default {};`
26
+ },
27
+ {
28
+ filename: "/project/src/example.js",
29
+ code: "export default {};"
30
+ },
31
+ {
32
+ filename: "/project/src/example.js",
33
+ code: `${header("MIXIN TO MANAGE HANDOFF")}\nexport default {};`
34
+ },
35
+ {
36
+ filename: "/project/src/example.js",
37
+ code:
38
+ `${header("IMPORTS")}\nimport first from "first";\n` +
39
+ "import second from \"second\";"
40
+ },
41
+ {
42
+ filename: "/project/src/example.vue",
43
+ code: "import value from \"package\";\nconst MAX_RETRIES = 3;"
44
+ },
45
+ {
46
+ filename: "/project/src/example.js",
47
+ code: "function wrapper() {\n const LOCAL_CONSTANT = 1;\n}"
48
+ }
49
+ ],
50
+
51
+ invalid: [
52
+ {
53
+ filename: "/project/src/example.js",
54
+ code: "import value from \"package\";",
55
+ errors: [
56
+ {
57
+ message: "Import group must be preceded by a 'IMPORTS' comment block"
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ filename: "/project/src/example.ts",
63
+ code: "const MAX_RETRIES = 3;",
64
+ errors: [
65
+ {
66
+ message: "Variable group must be preceded by a 'CONSTANTS' comment block"
67
+ }
68
+ ]
69
+ },
70
+ {
71
+ filename: "/project/src/example.js",
72
+ code: "const patterns = [/first/, /second/];",
73
+ errors: [
74
+ {
75
+ message: "Regex group must be preceded by a 'INSTANCES' comment block"
76
+ }
77
+ ]
78
+ },
79
+ {
80
+ filename: "/project/src/example.js",
81
+ code: "/** @typedef {string} Identifier */\nconst value = 1;",
82
+ errors: [
83
+ {
84
+ message: "Type comments group must be preceded by a 'TYPES' comment block"
85
+ }
86
+ ]
87
+ }
88
+ ]
89
+ });