eslint-plugin-complete 1.0.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.
Files changed (171) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +114 -0
  3. package/dist/comments.d.ts +22 -0
  4. package/dist/comments.d.ts.map +1 -0
  5. package/dist/comments.js +66 -0
  6. package/dist/completeCommon.d.ts +25 -0
  7. package/dist/completeCommon.d.ts.map +1 -0
  8. package/dist/completeCommon.js +53 -0
  9. package/dist/completeSentence.d.ts +9 -0
  10. package/dist/completeSentence.d.ts.map +1 -0
  11. package/dist/completeSentence.js +267 -0
  12. package/dist/configs/recommended.d.ts +3 -0
  13. package/dist/configs/recommended.d.ts.map +1 -0
  14. package/dist/configs/recommended.js +63 -0
  15. package/dist/configs.d.ts +4 -0
  16. package/dist/configs.d.ts.map +1 -0
  17. package/dist/configs.js +4 -0
  18. package/dist/constants.d.ts +8 -0
  19. package/dist/constants.d.ts.map +1 -0
  20. package/dist/constants.js +73 -0
  21. package/dist/format.d.ts +18 -0
  22. package/dist/format.d.ts.map +1 -0
  23. package/dist/format.js +246 -0
  24. package/dist/index.d.ts +60 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +49 -0
  27. package/dist/interfaces/MyPluginDocs.d.ts +6 -0
  28. package/dist/interfaces/MyPluginDocs.d.ts.map +1 -0
  29. package/dist/interfaces/MyPluginDocs.js +1 -0
  30. package/dist/jsdoc.d.ts +4 -0
  31. package/dist/jsdoc.d.ts.map +1 -0
  32. package/dist/jsdoc.js +24 -0
  33. package/dist/leadingLineComments.d.ts +32 -0
  34. package/dist/leadingLineComments.d.ts.map +1 -0
  35. package/dist/leadingLineComments.js +77 -0
  36. package/dist/list.d.ts +49 -0
  37. package/dist/list.d.ts.map +1 -0
  38. package/dist/list.js +140 -0
  39. package/dist/rules/complete-sentences-jsdoc.d.ts +4 -0
  40. package/dist/rules/complete-sentences-jsdoc.d.ts.map +1 -0
  41. package/dist/rules/complete-sentences-jsdoc.js +48 -0
  42. package/dist/rules/complete-sentences-line-comments.d.ts +4 -0
  43. package/dist/rules/complete-sentences-line-comments.d.ts.map +1 -0
  44. package/dist/rules/complete-sentences-line-comments.js +88 -0
  45. package/dist/rules/consistent-enum-values.d.ts +2 -0
  46. package/dist/rules/consistent-enum-values.d.ts.map +1 -0
  47. package/dist/rules/consistent-enum-values.js +46 -0
  48. package/dist/rules/consistent-named-tuples.d.ts +2 -0
  49. package/dist/rules/consistent-named-tuples.d.ts.map +1 -0
  50. package/dist/rules/consistent-named-tuples.js +34 -0
  51. package/dist/rules/eqeqeq-fix.d.ts +2 -0
  52. package/dist/rules/eqeqeq-fix.d.ts.map +1 -0
  53. package/dist/rules/eqeqeq-fix.js +173 -0
  54. package/dist/rules/format-jsdoc-comments.d.ts +8 -0
  55. package/dist/rules/format-jsdoc-comments.d.ts.map +1 -0
  56. package/dist/rules/format-jsdoc-comments.js +117 -0
  57. package/dist/rules/format-line-comments.d.ts +8 -0
  58. package/dist/rules/format-line-comments.d.ts.map +1 -0
  59. package/dist/rules/format-line-comments.js +118 -0
  60. package/dist/rules/jsdoc-code-block-language.d.ts +2 -0
  61. package/dist/rules/jsdoc-code-block-language.d.ts.map +1 -0
  62. package/dist/rules/jsdoc-code-block-language.js +52 -0
  63. package/dist/rules/newline-between-switch-case.d.ts +4 -0
  64. package/dist/rules/newline-between-switch-case.d.ts.map +1 -0
  65. package/dist/rules/newline-between-switch-case.js +63 -0
  66. package/dist/rules/no-confusing-set-methods.d.ts +5 -0
  67. package/dist/rules/no-confusing-set-methods.d.ts.map +1 -0
  68. package/dist/rules/no-confusing-set-methods.js +51 -0
  69. package/dist/rules/no-empty-jsdoc.d.ts +2 -0
  70. package/dist/rules/no-empty-jsdoc.d.ts.map +1 -0
  71. package/dist/rules/no-empty-jsdoc.js +45 -0
  72. package/dist/rules/no-empty-line-comments.d.ts +2 -0
  73. package/dist/rules/no-empty-line-comments.d.ts.map +1 -0
  74. package/dist/rules/no-empty-line-comments.js +40 -0
  75. package/dist/rules/no-explicit-array-loops.d.ts +5 -0
  76. package/dist/rules/no-explicit-array-loops.d.ts.map +1 -0
  77. package/dist/rules/no-explicit-array-loops.js +114 -0
  78. package/dist/rules/no-explicit-map-set-loops.d.ts +5 -0
  79. package/dist/rules/no-explicit-map-set-loops.d.ts.map +1 -0
  80. package/dist/rules/no-explicit-map-set-loops.js +74 -0
  81. package/dist/rules/no-for-in.d.ts +2 -0
  82. package/dist/rules/no-for-in.d.ts.map +1 -0
  83. package/dist/rules/no-for-in.js +27 -0
  84. package/dist/rules/no-let-any.d.ts +3 -0
  85. package/dist/rules/no-let-any.d.ts.map +1 -0
  86. package/dist/rules/no-let-any.js +45 -0
  87. package/dist/rules/no-mutable-return.d.ts +5 -0
  88. package/dist/rules/no-mutable-return.d.ts.map +1 -0
  89. package/dist/rules/no-mutable-return.js +63 -0
  90. package/dist/rules/no-number-enums.d.ts +2 -0
  91. package/dist/rules/no-number-enums.d.ts.map +1 -0
  92. package/dist/rules/no-number-enums.js +27 -0
  93. package/dist/rules/no-object-any.d.ts +3 -0
  94. package/dist/rules/no-object-any.d.ts.map +1 -0
  95. package/dist/rules/no-object-any.js +51 -0
  96. package/dist/rules/no-object-methods-with-map-set.d.ts +5 -0
  97. package/dist/rules/no-object-methods-with-map-set.d.ts.map +1 -0
  98. package/dist/rules/no-object-methods-with-map-set.js +84 -0
  99. package/dist/rules/no-string-length-0.d.ts +3 -0
  100. package/dist/rules/no-string-length-0.d.ts.map +1 -0
  101. package/dist/rules/no-string-length-0.js +52 -0
  102. package/dist/rules/no-template-curly-in-string-fix.d.ts +6 -0
  103. package/dist/rules/no-template-curly-in-string-fix.d.ts.map +1 -0
  104. package/dist/rules/no-template-curly-in-string-fix.js +39 -0
  105. package/dist/rules/no-undefined-return-type.d.ts +3 -0
  106. package/dist/rules/no-undefined-return-type.d.ts.map +1 -0
  107. package/dist/rules/no-undefined-return-type.js +40 -0
  108. package/dist/rules/no-unnecessary-assignment.d.ts +5 -0
  109. package/dist/rules/no-unnecessary-assignment.d.ts.map +1 -0
  110. package/dist/rules/no-unnecessary-assignment.js +255 -0
  111. package/dist/rules/no-unsafe-plusplus.d.ts +2 -0
  112. package/dist/rules/no-unsafe-plusplus.d.ts.map +1 -0
  113. package/dist/rules/no-unsafe-plusplus.js +34 -0
  114. package/dist/rules/no-useless-return.d.ts +2 -0
  115. package/dist/rules/no-useless-return.d.ts.map +1 -0
  116. package/dist/rules/no-useless-return.js +347 -0
  117. package/dist/rules/no-void-return-type.d.ts +2 -0
  118. package/dist/rules/no-void-return-type.d.ts.map +1 -0
  119. package/dist/rules/no-void-return-type.js +49 -0
  120. package/dist/rules/prefer-const.d.ts +2 -0
  121. package/dist/rules/prefer-const.d.ts.map +1 -0
  122. package/dist/rules/prefer-const.js +426 -0
  123. package/dist/rules/prefer-plusplus.d.ts +5 -0
  124. package/dist/rules/prefer-plusplus.d.ts.map +1 -0
  125. package/dist/rules/prefer-plusplus.js +49 -0
  126. package/dist/rules/prefer-postfix-plusplus.d.ts +2 -0
  127. package/dist/rules/prefer-postfix-plusplus.d.ts.map +1 -0
  128. package/dist/rules/prefer-postfix-plusplus.js +32 -0
  129. package/dist/rules/prefer-readonly-parameter-types.d.ts +13 -0
  130. package/dist/rules/prefer-readonly-parameter-types.d.ts.map +1 -0
  131. package/dist/rules/prefer-readonly-parameter-types.js +140 -0
  132. package/dist/rules/require-break.d.ts +5 -0
  133. package/dist/rules/require-break.d.ts.map +1 -0
  134. package/dist/rules/require-break.js +76 -0
  135. package/dist/rules/require-capital-const-assertions.d.ts +4 -0
  136. package/dist/rules/require-capital-const-assertions.d.ts.map +1 -0
  137. package/dist/rules/require-capital-const-assertions.js +112 -0
  138. package/dist/rules/require-capital-read-only.d.ts +5 -0
  139. package/dist/rules/require-capital-read-only.d.ts.map +1 -0
  140. package/dist/rules/require-capital-read-only.js +111 -0
  141. package/dist/rules/require-unannotated-const-assertions.d.ts +2 -0
  142. package/dist/rules/require-unannotated-const-assertions.d.ts.map +1 -0
  143. package/dist/rules/require-unannotated-const-assertions.js +27 -0
  144. package/dist/rules/require-variadic-function-argument.d.ts +5 -0
  145. package/dist/rules/require-variadic-function-argument.d.ts.map +1 -0
  146. package/dist/rules/require-variadic-function-argument.js +86 -0
  147. package/dist/rules/strict-array-methods.d.ts +3 -0
  148. package/dist/rules/strict-array-methods.d.ts.map +1 -0
  149. package/dist/rules/strict-array-methods.js +83 -0
  150. package/dist/rules/strict-enums.d.ts +5 -0
  151. package/dist/rules/strict-enums.d.ts.map +1 -0
  152. package/dist/rules/strict-enums.js +445 -0
  153. package/dist/rules/strict-undefined-functions.d.ts +5 -0
  154. package/dist/rules/strict-undefined-functions.d.ts.map +1 -0
  155. package/dist/rules/strict-undefined-functions.js +49 -0
  156. package/dist/rules/strict-void-functions.d.ts +2 -0
  157. package/dist/rules/strict-void-functions.d.ts.map +1 -0
  158. package/dist/rules/strict-void-functions.js +43 -0
  159. package/dist/rules.d.ts +49 -0
  160. package/dist/rules.d.ts.map +1 -0
  161. package/dist/rules.js +85 -0
  162. package/dist/template.d.ts +2 -0
  163. package/dist/template.d.ts.map +1 -0
  164. package/dist/template.js +29 -0
  165. package/dist/typeUtils.d.ts +28 -0
  166. package/dist/typeUtils.d.ts.map +1 -0
  167. package/dist/typeUtils.js +76 -0
  168. package/dist/utils.d.ts +13 -0
  169. package/dist/utils.d.ts.map +1 -0
  170. package/dist/utils.js +54 -0
  171. package/package.json +55 -0
@@ -0,0 +1,63 @@
1
+ /// THIS FILE IS AUTOMATICALLY GENERATED BY THE "generate.ts" SCRIPT.
2
+ /// DO NOT EDIT THIS FILE! YOU CAN REGENERATE IT WITH:
3
+ /// npm run generate
4
+ export const recommended = [
5
+ {
6
+ plugins: {},
7
+ rules: {
8
+ eqeqeq: "off",
9
+ "no-useless-return": "off",
10
+ "no-template-curly-in-string": "off",
11
+ "prefer-const": "off",
12
+ "complete/complete-sentences-jsdoc": "error",
13
+ "complete/complete-sentences-line-comments": "error",
14
+ "complete/consistent-enum-values": "error",
15
+ "complete/consistent-named-tuples": "error",
16
+ "complete/eqeqeq-fix": "error",
17
+ "complete/format-jsdoc-comments": "error",
18
+ "complete/format-line-comments": "error",
19
+ "complete/jsdoc-code-block-language": "error",
20
+ "complete/newline-between-switch-case": "error",
21
+ "complete/no-confusing-set-methods": "error",
22
+ "complete/no-empty-jsdoc": "error",
23
+ "complete/no-empty-line-comments": "error",
24
+ "complete/no-explicit-array-loops": "error",
25
+ "complete/no-explicit-map-set-loops": "error",
26
+ "complete/no-for-in": "error",
27
+ "complete/no-let-any": "error",
28
+ "complete/no-mutable-return": "error",
29
+ "complete/no-number-enums": "error",
30
+ "complete/no-object-any": "error",
31
+ "complete/no-object-methods-with-map-set": "error",
32
+ "complete/no-string-length-0": "error",
33
+ "complete/no-template-curly-in-string-fix": "error",
34
+ "complete/no-undefined-return-type": "error",
35
+ "complete/no-unnecessary-assignment": "error",
36
+ "complete/no-unsafe-plusplus": "error",
37
+ "complete/no-useless-return": "error",
38
+ "complete/no-void-return-type": "error",
39
+ "complete/prefer-const": "error",
40
+ "complete/prefer-plusplus": "error",
41
+ "complete/prefer-postfix-plusplus": "error",
42
+ "complete/prefer-readonly-parameter-types": "error",
43
+ "complete/require-break": "error",
44
+ "complete/require-capital-const-assertions": "error",
45
+ "complete/require-capital-read-only": "error",
46
+ "complete/require-unannotated-const-assertions": "error",
47
+ "complete/require-variadic-function-argument": "error",
48
+ "complete/strict-array-methods": "error",
49
+ "complete/strict-enums": "error",
50
+ "complete/strict-undefined-functions": "error",
51
+ "complete/strict-void-functions": "error",
52
+ },
53
+ },
54
+ {
55
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs", "**/*.jsx"],
56
+ rules: {
57
+ "complete/no-let-any": "off",
58
+ "complete/no-object-any": "off",
59
+ "complete/require-capital-const-assertions": "off",
60
+ "complete/require-capital-read-only": "off",
61
+ },
62
+ },
63
+ ];
@@ -0,0 +1,4 @@
1
+ export declare const configs: {
2
+ recommended: import("@typescript-eslint/utils/ts-eslint").FlatConfig.ConfigArray;
3
+ };
4
+ //# sourceMappingURL=configs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configs.d.ts","sourceRoot":"","sources":["../src/configs.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO;;CAEnB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { recommended } from "./configs/recommended.js";
2
+ export const configs = {
3
+ recommended,
4
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * From: https://www.w3schools.com/js/js_reserved.asp
3
+ *
4
+ * - Some words that would not typically start a line are manually removed.
5
+ * - `console` is added.
6
+ */
7
+ export declare const JAVASCRIPT_RESERVED_WORDS_SET: ReadonlySet<string>;
8
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAE,WAAW,CAAC,MAAM,CAkE5D,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * From: https://www.w3schools.com/js/js_reserved.asp
3
+ *
4
+ * - Some words that would not typically start a line are manually removed.
5
+ * - `console` is added.
6
+ */
7
+ export const JAVASCRIPT_RESERVED_WORDS_SET = new Set([
8
+ "abstract",
9
+ // "arguments",
10
+ "await",
11
+ // "boolean",
12
+ "break",
13
+ // "byte",
14
+ "case",
15
+ "catch",
16
+ // "char",
17
+ "class",
18
+ "console", // Manually added.
19
+ "const",
20
+ "continue",
21
+ "debugger",
22
+ // "default",
23
+ // "delete",
24
+ "do",
25
+ // "double",
26
+ "else",
27
+ "enum",
28
+ // "eval",
29
+ "export",
30
+ // "extends",
31
+ // "false",
32
+ // "final",
33
+ "finally",
34
+ // - "float",
35
+ "for",
36
+ "function",
37
+ "goto",
38
+ "if",
39
+ // "implements",
40
+ "import",
41
+ // "in",
42
+ // "instanceof",
43
+ // "int",
44
+ "interface",
45
+ "let",
46
+ // "long",
47
+ // "native",
48
+ "new",
49
+ // "null",
50
+ // "package",
51
+ "private",
52
+ "protected",
53
+ "public",
54
+ "return",
55
+ // "short",
56
+ "static",
57
+ "super",
58
+ "switch",
59
+ // "synchronized",
60
+ // "this",
61
+ "throw",
62
+ // "throws",
63
+ // "transient",
64
+ // "true",
65
+ "try",
66
+ // "typeof",
67
+ // "var",
68
+ // "void",
69
+ // "volatile",
70
+ "while",
71
+ // "with",
72
+ "yield",
73
+ ]);
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Feed this function a string that contains one or more lines of text. It will combine all of the
3
+ * lines and return a string with lines that do not exceed the maximum line length.
4
+ *
5
+ * For obvious reasons, this function works best on text that is composed of complete sentences.
6
+ * Otherwise, it would incorrectly combine together two disparate sentences.
7
+ *
8
+ * This function tries to be as smart as possible in that it will not merge specific kinds of lines,
9
+ * like bullet points, "eslint-disable" comments, and so on.
10
+ *
11
+ * @param text One or more lines of text, separated by newlines.
12
+ * @param maxLength The ruler cutoff for the formatted text.
13
+ * @param shouldParseJSDocTags Whether to make formatting decisions based on the presence of JSDoc
14
+ * tags. True by default. Pass false if working with leading line
15
+ * comments or other non-JSDoc text.
16
+ */
17
+ export declare function formatText(text: string, maxLength: number, shouldParseJSDocTags?: boolean): string;
18
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,oBAAoB,UAAO,GAC1B,MAAM,CAyRR"}
package/dist/format.js ADDED
@@ -0,0 +1,246 @@
1
+ import { isEnumBlockLabel, isSeparatorLine, isSpecialComment, } from "./comments.js";
2
+ import { ListKind, getAdjustedList, reachedNewList } from "./list.js";
3
+ import { hasURL } from "./utils.js";
4
+ /**
5
+ * Feed this function a string that contains one or more lines of text. It will combine all of the
6
+ * lines and return a string with lines that do not exceed the maximum line length.
7
+ *
8
+ * For obvious reasons, this function works best on text that is composed of complete sentences.
9
+ * Otherwise, it would incorrectly combine together two disparate sentences.
10
+ *
11
+ * This function tries to be as smart as possible in that it will not merge specific kinds of lines,
12
+ * like bullet points, "eslint-disable" comments, and so on.
13
+ *
14
+ * @param text One or more lines of text, separated by newlines.
15
+ * @param maxLength The ruler cutoff for the formatted text.
16
+ * @param shouldParseJSDocTags Whether to make formatting decisions based on the presence of JSDoc
17
+ * tags. True by default. Pass false if working with leading line
18
+ * comments or other non-JSDoc text.
19
+ */
20
+ export function formatText(text, maxLength, shouldParseJSDocTags = true) {
21
+ // First, replace any whitespace that is not a newline or a space with a space (like e.g. tabs).
22
+ text = text.replaceAll(/[^\S\n ]+/g, " ");
23
+ let formattedText = "";
24
+ let formattedLine = "";
25
+ let insideList;
26
+ let insideCodeBlock = false;
27
+ let insideExampleTagBlock = false;
28
+ let encounteredJSDocTags = false;
29
+ const lines = text.split("\n");
30
+ for (const [i, line] of lines.entries()) {
31
+ // Gather information about this line.
32
+ const lineIsBlank = line.trim() === "";
33
+ const hasCodeBlock = line.includes("```");
34
+ const previousLineInsideCodeBlock = insideCodeBlock;
35
+ if (hasCodeBlock) {
36
+ insideCodeBlock = !insideCodeBlock;
37
+ }
38
+ const previousLineInsideExampleTagBlock = insideExampleTagBlock;
39
+ if (shouldParseJSDocTags) {
40
+ const hasExampleTag = line.includes("@example");
41
+ if (hasExampleTag) {
42
+ insideExampleTagBlock = true;
43
+ }
44
+ else if (insideExampleTagBlock && line.trimStart().startsWith("@")) {
45
+ insideExampleTagBlock = false;
46
+ }
47
+ }
48
+ const lineHasURL = hasURL(line);
49
+ const hasExample = startsWithExample(line);
50
+ const separatorLine = isSeparatorLine(line);
51
+ const specialComment = isSpecialComment(line);
52
+ const enumBlockLabel = isEnumBlockLabel(line);
53
+ const beginsWithPipe = line.trimStart().startsWith("|");
54
+ // Gather information about the previous line.
55
+ const previousLine = lines[i - 1];
56
+ const previousLineWasBlank = previousLine === undefined || previousLine.trim() === "";
57
+ const previousLineHasCodeBlock = previousLine !== undefined && previousLine.includes("```");
58
+ const previousLineHadURL = previousLine !== undefined && hasURL(previousLine);
59
+ const previousLineEndedInColon = previousLine !== undefined && previousLine.trimEnd().endsWith(":");
60
+ const previousLineWasSeparatorLine = previousLine !== undefined && isSeparatorLine(previousLine);
61
+ const previousLineWasEnumBlockLabel = previousLine !== undefined && isEnumBlockLabel(previousLine);
62
+ // Handle blank lines.
63
+ if (lineIsBlank) {
64
+ // Append the partial line that we were building, if any.
65
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
66
+ // Append the blank line, but ignore multiple blank lines in a row (unless we are inside of a
67
+ // code block).
68
+ const lastCharacter = formattedText.at(-1);
69
+ if ((lastCharacter !== undefined && lastCharacter !== "\n") ||
70
+ insideCodeBlock) {
71
+ formattedText += "\n";
72
+ }
73
+ insideList = undefined;
74
+ continue;
75
+ }
76
+ // Handle code blocks. This case is simple because we need to exactly preserve the text.
77
+ if (hasCodeBlock ||
78
+ previousLineHasCodeBlock ||
79
+ insideCodeBlock ||
80
+ insideExampleTagBlock) {
81
+ // Append the partial line that we were building, if any.
82
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
83
+ // Enforce newlines before the beginning of code blocks. (But not inside of an example code
84
+ // block, because there should not be newlines between tags.)
85
+ if (hasCodeBlock &&
86
+ !previousLineInsideCodeBlock &&
87
+ !previousLineWasBlank &&
88
+ !insideExampleTagBlock) {
89
+ formattedText += "\n";
90
+ }
91
+ // Copy the line exactly.
92
+ formattedLine += line;
93
+ // Enforce newlines after the end of code blocks. (But not inside of an example code block,
94
+ // because there should not be newlines between tags.)
95
+ const nextLine = lines[i + 1];
96
+ const nextLineIsBlank = nextLine === undefined || nextLine.trim() === "";
97
+ if (hasCodeBlock &&
98
+ previousLineInsideCodeBlock &&
99
+ !nextLineIsBlank &&
100
+ !insideExampleTagBlock) {
101
+ // Append the partial line that we were building, if any.
102
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
103
+ formattedText += "\n";
104
+ }
105
+ insideList = undefined;
106
+ continue;
107
+ }
108
+ // Handle lines that begin with a pipe, which indicate a Markdown table. This case is simple
109
+ // because we need to exactly preserve the text.
110
+ if (beginsWithPipe) {
111
+ // Append the partial line that we were building, if any.
112
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
113
+ // Copy the line exactly.
114
+ formattedLine += line;
115
+ continue;
116
+ }
117
+ // Handle special comments.
118
+ if (specialComment) {
119
+ // Append the partial line that we were building, if any.
120
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
121
+ // Copy the line exactly.
122
+ formattedLine += line;
123
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
124
+ continue;
125
+ }
126
+ // Handle lists. (JSDoc tags also count as lists.)
127
+ const list = getAdjustedList(line, previousLineWasBlank, previousLineEndedInColon, insideList);
128
+ if (reachedNewList(insideList, list)) {
129
+ // Keep track that we have begun a list (or a new sub-list).
130
+ insideList = list;
131
+ }
132
+ // Lists and some other specific text elements indicate that we should always insert a new line,
133
+ // even if the text has no wrapped to the end of the ruler yet.
134
+ if (list !== undefined ||
135
+ lineHasURL ||
136
+ previousLineHadURL ||
137
+ hasExample ||
138
+ separatorLine ||
139
+ previousLineWasSeparatorLine ||
140
+ enumBlockLabel ||
141
+ previousLineWasEnumBlockLabel) {
142
+ // Append the partial line that we were building, if any.
143
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
144
+ }
145
+ // Keep track of when we first encounter JSDoc tags. (JSDoc comments can be thought of as having
146
+ // an "description" or "introductory" section at the top, and then a list of JSDoc tags at the
147
+ // bottom.)
148
+ if (shouldParseJSDocTags &&
149
+ !encounteredJSDocTags &&
150
+ list !== undefined &&
151
+ list.kind === ListKind.JSDocTag) {
152
+ encounteredJSDocTags = true;
153
+ // Enforce a newline between a JSDoc description (i.e. introductory text) and the first JSDoc
154
+ // tag.
155
+ if (!stringContainsOnlyWhitespace(formattedText) &&
156
+ !previousLineWasBlank &&
157
+ !previousLineInsideExampleTagBlock) {
158
+ // Append the partial line that we were building, if any.
159
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
160
+ formattedText += "\n";
161
+ }
162
+ }
163
+ const words = getWordsFromLine(line);
164
+ for (const word of words) {
165
+ // Words can be blank strings in certain cases. For example: "dog cat"
166
+ if (word === "") {
167
+ continue;
168
+ }
169
+ // Handle splitting to a new line.
170
+ const splitToNewLine = shouldSplitToNewLine(formattedLine, word, maxLength);
171
+ if (splitToNewLine) {
172
+ // Append the partial line that we were building, if any.
173
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
174
+ // Overflowed lists should be indented so that the list items can be more easily
175
+ // distinguished.
176
+ if (insideList !== undefined) {
177
+ // It is possible for JSDoc comments to have really long variable names, which would make
178
+ // the indent be really big. Thus, we arbitrarily hard-cap the effective marker size at a
179
+ // third of the width of the remaining space.
180
+ const amountOfSpacesToWorkWith = maxLength - insideList.numLeadingSpaces;
181
+ const thirdOfRemainingSpace = Math.floor(amountOfSpacesToWorkWith / 3);
182
+ const effectiveMarkerSize = Math.min(insideList.markerSize, thirdOfRemainingSpace);
183
+ // We subtract one since we will add an extra space below when adding the first word.
184
+ const numSpacesToAdd = insideList.numLeadingSpaces + effectiveMarkerSize - 1;
185
+ formattedLine += " ".repeat(numSpacesToAdd);
186
+ }
187
+ }
188
+ // Add the word. (`numLeadingSpaces` will be set if this is a line with a sub-bullet point.)
189
+ const atBeginningOfLine = formattedLine === "";
190
+ const numLeadingSpaces = list === undefined ? 0 : list.numLeadingSpaces;
191
+ const leadingSpaces = " ".repeat(numLeadingSpaces);
192
+ const textToAdd = atBeginningOfLine
193
+ ? `${leadingSpaces}${word}`
194
+ : ` ${word}`;
195
+ formattedLine += textToAdd;
196
+ }
197
+ }
198
+ // Append the partial line that we were building, if any.
199
+ // eslint-disable-next-line no-useless-assignment
200
+ [formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
201
+ return formattedText;
202
+ }
203
+ /**
204
+ * We split to a new line if:
205
+ * 1. adding the word would make it overflow past the maximum length
206
+ * 2. and there is at least one word on the current line
207
+ *
208
+ * For example, there could be a very long URL that exceeds the maximum length, but since there are
209
+ * no spaces in the URL, it can't be split up and has to exceed the maximum length.
210
+ */
211
+ function shouldSplitToNewLine(formattedLine, word, effectiveLength) {
212
+ const atBeginningOfLine = formattedLine === "";
213
+ const textToAdd = atBeginningOfLine ? word : ` ${word}`;
214
+ const lineLengthIfAdded = formattedLine.length + textToAdd.length;
215
+ return lineLengthIfAdded > effectiveLength && !atBeginningOfLine;
216
+ }
217
+ function appendLineToText(formattedLine, formattedText) {
218
+ if (formattedLine !== "") {
219
+ if (formattedText !== "") {
220
+ formattedText += "\n";
221
+ }
222
+ formattedText += formattedLine;
223
+ formattedLine = "";
224
+ }
225
+ return [formattedLine, formattedText];
226
+ }
227
+ function startsWithExample(text) {
228
+ const trimmedText = text.trimStart();
229
+ return (trimmedText.startsWith("e.g. ") ||
230
+ trimmedText.startsWith("(e.g. ") ||
231
+ trimmedText.startsWith("i.e. ") ||
232
+ trimmedText.startsWith("(i.e. "));
233
+ }
234
+ function stringContainsOnlyWhitespace(string) {
235
+ return string.trim() === "";
236
+ }
237
+ /**
238
+ * For most cases, we can get the words on a line by splitting on a space.
239
+ *
240
+ * However, we don't want to split up a fragment like "{@link foo}" between lines, because it breaks
241
+ * the parsing inside VSCode. Thus, anything matching this pattern should be considered its own
242
+ * word, even if it has spaces inside of it.
243
+ */
244
+ function getWordsFromLine(line) {
245
+ return line.match(/(?:{@link .+?}|\S)+/g) ?? [];
246
+ }
@@ -0,0 +1,60 @@
1
+ import type { TSESLint } from "@typescript-eslint/utils";
2
+ declare const plugin: {
3
+ meta: {
4
+ name: unknown;
5
+ version: unknown;
6
+ };
7
+ configs: {
8
+ recommended: TSESLint.FlatConfig.ConfigArray;
9
+ };
10
+ rules: {
11
+ "complete-sentences-jsdoc": TSESLint.RuleModule<import("./completeSentence.js").CompleteSentenceMessageIds, [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
12
+ "complete-sentences-line-comments": TSESLint.RuleModule<import("./completeSentence.js").CompleteSentenceMessageIds, [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
13
+ "consistent-enum-values": TSESLint.RuleModule<"inconsistentValue", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
14
+ "consistent-named-tuples": TSESLint.RuleModule<"notNamed", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
15
+ "eqeqeq-fix": TSESLint.RuleModule<"unexpected", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
16
+ "format-jsdoc-comments": TSESLint.RuleModule<"incorrectlyFormatted", import("./rules/format-jsdoc-comments.js").Options, import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
17
+ "format-line-comments": TSESLint.RuleModule<"incorrectlyFormatted", import("./rules/format-line-comments.js").Options, import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
18
+ "jsdoc-code-block-language": TSESLint.RuleModule<"noLanguage", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
19
+ "newline-between-switch-case": TSESLint.RuleModule<"noNewline", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
20
+ "no-confusing-set-methods": TSESLint.RuleModule<"noKeys" | "noEntries", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
21
+ "no-empty-jsdoc": TSESLint.RuleModule<"isEmpty", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
22
+ "no-empty-line-comments": TSESLint.RuleModule<"isEmpty", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
23
+ "no-explicit-array-loops": TSESLint.RuleModule<"noExplicitArray", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
24
+ "no-explicit-map-set-loops": TSESLint.RuleModule<"noExplicitMap" | "noExplicitSet", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
25
+ "no-for-in": TSESLint.RuleModule<"noForIn", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
26
+ "no-let-any": TSESLint.RuleModule<"noType", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
27
+ "no-mutable-return": TSESLint.RuleModule<"mutableArray" | "mutableMap" | "mutableSet", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
28
+ "no-number-enums": TSESLint.RuleModule<"noNumberEnums", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
29
+ "no-object-any": TSESLint.RuleModule<"noType", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
30
+ "no-object-methods-with-map-set": TSESLint.RuleModule<"noObjectEntriesMap" | "noObjectKeysMap" | "noObjectValuesMap" | "noObjectEntriesSet" | "noObjectKeysSet" | "noObjectValuesSet", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
31
+ "no-string-length-0": TSESLint.RuleModule<"noStringLength0", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
32
+ "no-template-curly-in-string-fix": TSESLint.RuleModule<"unexpectedTemplateExpression", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
33
+ "no-undefined-return-type": TSESLint.RuleModule<"undefinedReturnType", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
34
+ "no-unnecessary-assignment": TSESLint.RuleModule<import("./rules/no-unnecessary-assignment.js").MessageIds, [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
35
+ "no-unsafe-plusplus": TSESLint.RuleModule<"plusPlus" | "minusMinus", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
36
+ "no-useless-return": TSESLint.RuleModule<"unnecessaryReturn", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
37
+ "no-void-return-type": TSESLint.RuleModule<"voidReturnType", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
38
+ "prefer-const": TSESLint.RuleModule<"useConst", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
39
+ "prefer-plusplus": TSESLint.RuleModule<import("./rules/prefer-plusplus.js").MessageIds, [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
40
+ "prefer-postfix-plusplus": TSESLint.RuleModule<"plusPlus" | "minusMinus", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
41
+ "prefer-readonly-parameter-types": TSESLint.RuleModule<"shouldBeReadonly", [{
42
+ allow?: import("@typescript-eslint/type-utils").TypeOrValueSpecifier[];
43
+ checkParameterProperties?: boolean;
44
+ ignoreInferredTypes?: boolean;
45
+ treatMethodsAsReadonly?: boolean;
46
+ onlyRecordsArraysMapsSet?: boolean;
47
+ }], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
48
+ "require-break": TSESLint.RuleModule<"noBreak", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
49
+ "require-capital-const-assertions": TSESLint.RuleModule<"noConstAssertion", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
50
+ "require-capital-read-only": TSESLint.RuleModule<import("./rules/require-capital-read-only.js").MessageIds, [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
51
+ "require-unannotated-const-assertions": TSESLint.RuleModule<"annotatedConstAssertion", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
52
+ "require-variadic-function-argument": TSESLint.RuleModule<"noArgument", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
53
+ "strict-array-methods": TSESLint.RuleModule<"conditionError", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
54
+ "strict-enums": TSESLint.RuleModule<import("./rules/strict-enums.js").MessageIds, [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
55
+ "strict-undefined-functions": TSESLint.RuleModule<"mismatchedReturnType", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
56
+ "strict-void-functions": TSESLint.RuleModule<"mismatchedReturnType", [], import("./interfaces/MyPluginDocs.js").MyPluginDocs, TSESLint.RuleListener>;
57
+ };
58
+ };
59
+ export default plugin;
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AASzD,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOX,CAAC;AAIF,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { configs } from "./configs.js";
4
+ import { rules } from "./rules.js";
5
+ const { name, version } = getPackageJSON();
6
+ const plugin = {
7
+ meta: {
8
+ name,
9
+ version,
10
+ },
11
+ configs,
12
+ rules,
13
+ };
14
+ addPluginToConfigs(configs, name);
15
+ export default plugin;
16
+ /**
17
+ * We parse the package JSON manually since importing JSON files directly in Node is experimental.
18
+ */
19
+ function getPackageJSON() {
20
+ const packageRoot = path.join(import.meta.dirname, "..");
21
+ const packageJSONPath = path.join(packageRoot, "package.json");
22
+ try {
23
+ const packageJSONString = fs.readFileSync(packageJSONPath, "utf8");
24
+ return JSON.parse(packageJSONString);
25
+ }
26
+ catch (error) {
27
+ throw new Error(`Failed to read the "${packageJSONPath}" file: ${error}`);
28
+ }
29
+ }
30
+ /** @see https://eslint.org/docs/latest/extend/plugins#configs-in-plugins */
31
+ function addPluginToConfigs(configsToMutate, packageName) {
32
+ if (typeof packageName !== "string") {
33
+ throw new TypeError('Failed to parse the plugin name from the "package.json" file.');
34
+ }
35
+ const packageNameWords = packageName.split("-");
36
+ const pluginName = packageNameWords.at(-1);
37
+ if (pluginName === undefined || pluginName === "") {
38
+ throw new Error("Failed to parse the plugin name from the package name.");
39
+ }
40
+ for (const configArray of Object.values(configsToMutate)) {
41
+ for (const config of configArray) {
42
+ if (config.plugins !== undefined) {
43
+ Object.assign(config.plugins, {
44
+ [pluginName]: plugin,
45
+ });
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,6 @@
1
+ /** @see https://typescript-eslint.io/developers/custom-rules#extra-rule-docs-types */
2
+ export interface MyPluginDocs {
3
+ recommended: boolean;
4
+ requiresTypeChecking: boolean;
5
+ }
6
+ //# sourceMappingURL=MyPluginDocs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MyPluginDocs.d.ts","sourceRoot":"","sources":["../../src/interfaces/MyPluginDocs.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,oBAAoB,EAAE,OAAO,CAAC;CAC/B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import { TSESTree } from "@typescript-eslint/utils";
2
+ export declare function getJSDocComments(comments: readonly TSESTree.Comment[]): readonly TSESTree.Comment[];
3
+ export declare function getTextFromJSDocComment(comment: string): string;
4
+ //# sourceMappingURL=jsdoc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsdoc.d.ts","sourceRoot":"","sources":["../src/jsdoc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,QAAQ,CAAC,OAAO,EAAE,GACpC,SAAS,QAAQ,CAAC,OAAO,EAAE,CAM7B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuB/D"}
package/dist/jsdoc.js ADDED
@@ -0,0 +1,24 @@
1
+ import { TSESTree } from "@typescript-eslint/utils";
2
+ export function getJSDocComments(comments) {
3
+ return comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Block && // i.e. a "/*" comment
4
+ comment.value.startsWith("*"));
5
+ }
6
+ export function getTextFromJSDocComment(comment) {
7
+ comment = comment.trim();
8
+ const lines = comment.split("\n");
9
+ const linesWithRemovedAsterisks = lines.map((line) => {
10
+ // First, if the line contains only spaces and/or asterisks, it can be deleted.
11
+ if (/^[\s*]*$/.test(line)) {
12
+ return "";
13
+ }
14
+ // We have to be careful not to trim all of the whitespace from the line here because whitespace
15
+ // must be preserved while inside of code blocks.
16
+ line = line.replace(/^\s*\* /, "");
17
+ // Remove any duplicate asterisks, like "* * Foo".
18
+ while (line.startsWith("* ")) {
19
+ line = line.replace(/^\* /, "");
20
+ }
21
+ return line;
22
+ });
23
+ return linesWithRemovedAsterisks.join("\n").trim();
24
+ }
@@ -0,0 +1,32 @@
1
+ import type { TSESLint } from "@typescript-eslint/utils";
2
+ import { TSESTree } from "@typescript-eslint/utils";
3
+ export declare function getLeadingLineComments(sourceCode: TSESLint.SourceCode, comments: readonly TSESTree.Comment[]): readonly TSESTree.Comment[];
4
+ /**
5
+ * An object containing one or more contiguous leading line comments. For example:
6
+ *
7
+ * ```ts
8
+ * // The first line of the block.
9
+ * // The second line of the block.
10
+ * ```
11
+ */
12
+ interface LeadingLineCommentBlock {
13
+ mergedText: string;
14
+ originalComments: TSESTree.Comment[];
15
+ }
16
+ /**
17
+ * Returns an array of grouped comments. For example, the following code would return an array of
18
+ * three comment blocks:
19
+ *
20
+ * ```ts
21
+ * // This is the first block.
22
+ *
23
+ * // This is the second block.
24
+ * // We are still in the second block, because there has not been a newline separator yet.
25
+ *
26
+ * // This is the third block.
27
+ * ```
28
+ */
29
+ export declare function getCommentBlocks(comments: readonly TSESTree.Comment[]): readonly LeadingLineCommentBlock[];
30
+ export declare function allCommentsInBlockAreCommentedOutArrayElements(commentBlock: LeadingLineCommentBlock): boolean;
31
+ export {};
32
+ //# sourceMappingURL=leadingLineComments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leadingLineComments.d.ts","sourceRoot":"","sources":["../src/leadingLineComments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAC/B,QAAQ,EAAE,SAAS,QAAQ,CAAC,OAAO,EAAE,GACpC,SAAS,QAAQ,CAAC,OAAO,EAAE,CAQ7B;AAED;;;;;;;GAOG;AACH,UAAU,uBAAuB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,QAAQ,CAAC,OAAO,EAAE,GACpC,SAAS,uBAAuB,EAAE,CAgEpC;AAED,wBAAgB,8CAA8C,CAC5D,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAIT"}