eslint-plugin-kirklin 0.5.6 → 0.9.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2019-PRESENT Kirk Lin<https://github.com/kirklin>
3
+ Copyright (c) 2021-PRESENT Anthony Fu <https://github.com/kirklin>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # eslint-plugin-kirklin
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+
6
+ Anthony extended ESLint rules. For [kirklin/eslint-config](https://github.com/kirklin/eslint-config).
7
+
8
+ [Rules List](./src/rules)
9
+
10
+ ## Sponsors
11
+
12
+ <p align="center">
13
+ <a href="https://cdn.jsdelivr.net/gh/kirklin/static/sponsors.svg">
14
+ <img src='https://cdn.jsdelivr.net/gh/kirklin/static/sponsors.svg'/>
15
+ </a>
16
+ </p>
17
+
18
+ ## License
19
+
20
+ [MIT](./LICENSE) License © 2023-PRESENT [Anthony Fu](https://github.com/kirklin)
21
+
22
+ <!-- Badges -->
23
+
24
+ [npm-version-src]: https://img.shields.io/npm/v/eslint-plugin-kirklin?style=flat&colorA=080f12&colorB=1fa669
25
+ [npm-version-href]: https://npmjs.com/package/eslint-plugin-kirklin
26
+ [npm-downloads-src]: https://img.shields.io/npm/dm/eslint-plugin-kirklin?style=flat&colorA=080f12&colorB=1fa669
27
+ [npm-downloads-href]: https://npmjs.com/package/eslint-plugin-kirklin
package/dist/index.cjs CHANGED
@@ -1,21 +1,66 @@
1
1
  'use strict';
2
2
 
3
- const utils = require('@typescript-eslint/utils');
3
+ const version = "0.9.0";
4
4
 
5
- const createEslintRule = utils.ESLintUtils.RuleCreator(
6
- (ruleName) => ruleName
5
+ const hasDocs = [
6
+ "consistent-list-newline",
7
+ "if-newline",
8
+ "import-dedupe",
9
+ "top-level-function"
10
+ ];
11
+ const blobUrl = "https://github.com/kirklin/eslint-plugin-kirklin/blob/main/src/rules/";
12
+ function RuleCreator(urlCreator) {
13
+ return function createNamedRule({
14
+ name,
15
+ meta,
16
+ ...rule
17
+ }) {
18
+ return createRule({
19
+ meta: {
20
+ ...meta,
21
+ docs: {
22
+ ...meta.docs,
23
+ url: urlCreator(name)
24
+ }
25
+ },
26
+ ...rule
27
+ });
28
+ };
29
+ }
30
+ function createRule({
31
+ create,
32
+ defaultOptions,
33
+ meta
34
+ }) {
35
+ return {
36
+ create: (context) => {
37
+ const optionsWithDefault = context.options.map((options, index) => {
38
+ return {
39
+ ...defaultOptions[index] || {},
40
+ ...options || {}
41
+ };
42
+ });
43
+ return create(context, optionsWithDefault);
44
+ },
45
+ defaultOptions,
46
+ meta
47
+ };
48
+ }
49
+ const createEslintRule = RuleCreator(
50
+ (ruleName) => hasDocs.includes(ruleName) ? `${blobUrl}${ruleName}.md` : `${blobUrl}${ruleName}.test.ts`
7
51
  );
8
52
 
9
- const RULE_NAME$4 = "generic-spacing";
53
+ const RULE_NAME$a = "generic-spacing";
54
+ const PRESERVE_PREFIX_SPACE_BEFORE_GENERIC = /* @__PURE__ */ new Set(["TSCallSignatureDeclaration", "ArrowFunctionExpression", "TSFunctionType", "FunctionExpression"]);
10
55
  const genericSpacing = createEslintRule({
11
- name: RULE_NAME$4,
56
+ name: RULE_NAME$a,
12
57
  meta: {
13
- type: "suggestion",
58
+ type: "layout",
14
59
  docs: {
15
60
  description: "Spaces around generic type parameters",
16
- recommended: "error"
61
+ recommended: "stylistic"
17
62
  },
18
- fixable: "code",
63
+ fixable: "whitespace",
19
64
  schema: [],
20
65
  messages: {
21
66
  genericSpacingMismatch: "Generic spaces mismatch"
@@ -26,7 +71,7 @@ const genericSpacing = createEslintRule({
26
71
  const sourceCode = context.getSourceCode();
27
72
  return {
28
73
  TSTypeParameterDeclaration: (node) => {
29
- if (!["TSCallSignatureDeclaration", "ArrowFunctionExpression", "TSFunctionType"].includes(node.parent.type)) {
74
+ if (!PRESERVE_PREFIX_SPACE_BEFORE_GENERIC.has(node.parent.type)) {
30
75
  const pre = sourceCode.text.slice(0, node.range[0]);
31
76
  const preSpace = pre.match(/(\s+)$/)?.[0];
32
77
  if (preSpace && preSpace.length) {
@@ -46,7 +91,7 @@ const genericSpacing = createEslintRule({
46
91
  const from = prev.range[1];
47
92
  const to = current.range[0];
48
93
  const span = sourceCode.text.slice(from, to);
49
- if (span !== ", " && !span.match(/,\n/)) {
94
+ if (span !== ", " && !span.match(/,\s*\r?\n/)) {
50
95
  context.report({
51
96
  *fix(fixer) {
52
97
  yield fixer.replaceTextRange([from, to], ", ");
@@ -87,16 +132,16 @@ const genericSpacing = createEslintRule({
87
132
  }
88
133
  });
89
134
 
90
- const RULE_NAME$3 = "if-newline";
135
+ const RULE_NAME$9 = "if-newline";
91
136
  const ifNewline = createEslintRule({
92
- name: RULE_NAME$3,
137
+ name: RULE_NAME$9,
93
138
  meta: {
94
- type: "problem",
139
+ type: "layout",
95
140
  docs: {
96
141
  description: "Newline after if",
97
- recommended: "error"
142
+ recommended: "stylistic"
98
143
  },
99
- fixable: "code",
144
+ fixable: "whitespace",
100
145
  schema: [],
101
146
  messages: {
102
147
  missingIfNewline: "Expect newline after if"
@@ -130,14 +175,14 @@ const ifNewline = createEslintRule({
130
175
  }
131
176
  });
132
177
 
133
- const RULE_NAME$2 = "import-dedupe";
178
+ const RULE_NAME$8 = "import-dedupe";
134
179
  const importDedupe = createEslintRule({
135
- name: RULE_NAME$2,
180
+ name: RULE_NAME$8,
136
181
  meta: {
137
182
  type: "problem",
138
183
  docs: {
139
184
  description: "Fix duplication in imports",
140
- recommended: "error"
185
+ recommended: "strict"
141
186
  },
142
187
  fixable: "code",
143
188
  schema: [],
@@ -180,41 +225,13 @@ const importDedupe = createEslintRule({
180
225
  }
181
226
  });
182
227
 
183
- const RULE_NAME$1 = "no-const-enum";
184
- const noConstEnum = createEslintRule({
185
- name: RULE_NAME$1,
186
- meta: {
187
- type: "problem",
188
- docs: {
189
- description: "Disallow using `const enum` expression",
190
- recommended: "error"
191
- },
192
- schema: [],
193
- messages: {
194
- noConstEnum: "Do not use `const enum` expression"
195
- }
196
- },
197
- defaultOptions: [],
198
- create: (context) => ({
199
- TSEnumDeclaration(node) {
200
- if (node.const) {
201
- context.report({
202
- node,
203
- messageId: "noConstEnum"
204
- });
205
- }
206
- }
207
- })
208
- });
209
-
210
- const RULE_NAME = "prefer-inline-type-import";
228
+ const RULE_NAME$7 = "prefer-inline-type-import";
211
229
  const preferInlineTypeImport = createEslintRule({
212
- name: RULE_NAME,
230
+ name: RULE_NAME$7,
213
231
  meta: {
214
232
  type: "suggestion",
215
233
  docs: {
216
- description: "Inline type import",
217
- recommended: "error"
234
+ description: "Inline type import"
218
235
  },
219
236
  fixable: "code",
220
237
  schema: [],
@@ -249,7 +266,13 @@ const preferInlineTypeImport = createEslintRule({
249
266
  });
250
267
  function* removeTypeSpecifier(fixer, sourceCode, node) {
251
268
  const importKeyword = sourceCode.getFirstToken(node);
269
+ if (!importKeyword) {
270
+ return;
271
+ }
252
272
  const typeIdentifier = sourceCode.getTokenAfter(importKeyword);
273
+ if (!typeIdentifier) {
274
+ return;
275
+ }
253
276
  yield fixer.remove(typeIdentifier);
254
277
  if (importKeyword.loc.end.column + 1 === typeIdentifier.loc.start.column) {
255
278
  yield fixer.removeRange([
@@ -259,14 +282,471 @@ function* removeTypeSpecifier(fixer, sourceCode, node) {
259
282
  }
260
283
  }
261
284
 
262
- const index = {
285
+ const RULE_NAME$6 = "top-level-function";
286
+ const topLevelFunction = createEslintRule({
287
+ name: RULE_NAME$6,
288
+ meta: {
289
+ type: "problem",
290
+ docs: {
291
+ description: "Enforce top-level functions to be declared with function keyword",
292
+ recommended: "stylistic"
293
+ },
294
+ fixable: "code",
295
+ schema: [],
296
+ messages: {
297
+ topLevelFunctionDeclaration: "Top-level functions should be declared with function keyword"
298
+ }
299
+ },
300
+ defaultOptions: [],
301
+ create: (context) => {
302
+ return {
303
+ VariableDeclaration(node) {
304
+ if (node.parent.type !== "Program" && node.parent.type !== "ExportNamedDeclaration") {
305
+ return;
306
+ }
307
+ if (node.declarations.length !== 1) {
308
+ return;
309
+ }
310
+ if (node.kind !== "const") {
311
+ return;
312
+ }
313
+ if (node.declare) {
314
+ return;
315
+ }
316
+ const declaration = node.declarations[0];
317
+ if (declaration.init?.type !== "ArrowFunctionExpression") {
318
+ return;
319
+ }
320
+ if (declaration.id?.type !== "Identifier") {
321
+ return;
322
+ }
323
+ if (declaration.id.typeAnnotation) {
324
+ return;
325
+ }
326
+ if (declaration.init.body.type !== "BlockStatement" && declaration.id?.loc.start.line === declaration.init?.body.loc.end.line) {
327
+ return;
328
+ }
329
+ const arrowFn = declaration.init;
330
+ const body = declaration.init.body;
331
+ const id = declaration.id;
332
+ context.report({
333
+ node,
334
+ loc: {
335
+ start: id.loc.start,
336
+ end: body.loc.start
337
+ },
338
+ messageId: "topLevelFunctionDeclaration",
339
+ fix(fixer) {
340
+ const code = context.getSourceCode().text;
341
+ const textName = code.slice(id.range[0], id.range[1]);
342
+ const textArgs = arrowFn.params.length ? code.slice(arrowFn.params[0].range[0], arrowFn.params[arrowFn.params.length - 1].range[1]) : "";
343
+ const textBody = body.type === "BlockStatement" ? code.slice(body.range[0], body.range[1]) : `{
344
+ return ${code.slice(body.range[0], body.range[1])}
345
+ }`;
346
+ const textGeneric = arrowFn.typeParameters ? code.slice(arrowFn.typeParameters.range[0], arrowFn.typeParameters.range[1]) : "";
347
+ const textTypeReturn = arrowFn.returnType ? code.slice(arrowFn.returnType.range[0], arrowFn.returnType.range[1]) : "";
348
+ const textAsync = arrowFn.async ? "async " : "";
349
+ const final = `${textAsync}function ${textName} ${textGeneric}(${textArgs})${textTypeReturn} ${textBody}`;
350
+ return fixer.replaceTextRange([node.range[0], node.range[1]], final);
351
+ }
352
+ });
353
+ }
354
+ };
355
+ }
356
+ });
357
+
358
+ const RULE_NAME$5 = "no-import-node-modules-by-path";
359
+ const noImportNodeModulesByPath = createEslintRule({
360
+ name: RULE_NAME$5,
361
+ meta: {
362
+ type: "problem",
363
+ docs: {
364
+ description: "Prevent importing modules in `node_modules` folder by relative or absolute path",
365
+ recommended: "recommended"
366
+ },
367
+ schema: [],
368
+ messages: {
369
+ noImportNodeModulesByPath: "Do not import modules in `node_modules` folder by path"
370
+ }
371
+ },
372
+ defaultOptions: [],
373
+ create: (context) => {
374
+ return {
375
+ "ImportDeclaration": (node) => {
376
+ if (node.source.value.includes("/node_modules/")) {
377
+ context.report({
378
+ node,
379
+ messageId: "noImportNodeModulesByPath"
380
+ });
381
+ }
382
+ },
383
+ 'CallExpression[callee.name="require"]': (node) => {
384
+ const value = node.arguments[0]?.value;
385
+ if (typeof value === "string" && value.includes("/node_modules/")) {
386
+ context.report({
387
+ node,
388
+ messageId: "noImportNodeModulesByPath"
389
+ });
390
+ }
391
+ }
392
+ };
393
+ }
394
+ });
395
+
396
+ const RULE_NAME$4 = "no-ts-export-equal";
397
+ const noTsExportEqual = createEslintRule({
398
+ name: RULE_NAME$4,
399
+ meta: {
400
+ type: "problem",
401
+ docs: {
402
+ description: "Do not use `exports =`",
403
+ recommended: "recommended"
404
+ },
405
+ schema: [],
406
+ messages: {
407
+ noTsExportEqual: "Use ESM `export default` instead"
408
+ }
409
+ },
410
+ defaultOptions: [],
411
+ create: (context) => {
412
+ const extension = context.getFilename().split(".").pop();
413
+ if (!extension) {
414
+ return {};
415
+ }
416
+ if (!["ts", "tsx", "mts", "cts"].includes(extension)) {
417
+ return {};
418
+ }
419
+ return {
420
+ TSExportAssignment(node) {
421
+ context.report({
422
+ node,
423
+ messageId: "noTsExportEqual"
424
+ });
425
+ }
426
+ };
427
+ }
428
+ });
429
+
430
+ const RULE_NAME$3 = "no-cjs-exports";
431
+ const noCjsExports = createEslintRule({
432
+ name: RULE_NAME$3,
433
+ meta: {
434
+ type: "problem",
435
+ docs: {
436
+ description: "Do not use CJS exports"
437
+ },
438
+ schema: [],
439
+ messages: {
440
+ noCjsExports: "Use ESM export instead"
441
+ }
442
+ },
443
+ defaultOptions: [],
444
+ create: (context) => {
445
+ const extension = context.getFilename().split(".").pop();
446
+ if (!extension) {
447
+ return {};
448
+ }
449
+ if (!["ts", "tsx", "mts", "cts"].includes(extension)) {
450
+ return {};
451
+ }
452
+ return {
453
+ 'MemberExpression[object.name="exports"]': function(node) {
454
+ context.report({
455
+ node,
456
+ messageId: "noCjsExports"
457
+ });
458
+ },
459
+ 'MemberExpression[object.name="module"][property.name="exports"]': function(node) {
460
+ context.report({
461
+ node,
462
+ messageId: "noCjsExports"
463
+ });
464
+ }
465
+ };
466
+ }
467
+ });
468
+
469
+ const RULE_NAME$2 = "no-const-enum";
470
+ const noConstEnum = createEslintRule({
471
+ name: RULE_NAME$2,
472
+ meta: {
473
+ type: "problem",
474
+ docs: {
475
+ description: "Deprecated. Use `'no-restricted-syntax': ['error', 'TSEnumDeclaration[const=true]']` instead."
476
+ },
477
+ schema: [],
478
+ messages: {
479
+ noConstEnum: "Do not use `const enum` expression"
480
+ },
481
+ deprecated: true
482
+ },
483
+ defaultOptions: [],
484
+ create: (context) => {
485
+ return {
486
+ TSEnumDeclaration: (node) => {
487
+ if (node.const) {
488
+ context.report({
489
+ node,
490
+ messageId: "noConstEnum"
491
+ });
492
+ }
493
+ }
494
+ };
495
+ }
496
+ });
497
+
498
+ const RULE_NAME$1 = "named-tuple-spacing";
499
+ const RE = /^([\w_$]+)(\s*)(\?\s*)?:(\s*)(.*)$/;
500
+ const namedTupleSpacing = createEslintRule({
501
+ name: RULE_NAME$1,
502
+ meta: {
503
+ type: "layout",
504
+ docs: {
505
+ description: "Expect space before type declaration in named tuple",
506
+ recommended: "stylistic"
507
+ },
508
+ fixable: "whitespace",
509
+ schema: [],
510
+ messages: {
511
+ expectedSpaceAfter: "Expected a space after the ':'.",
512
+ unexpectedSpaceBetween: "Unexpected space between '?' and the ':'.",
513
+ unexpectedSpaceBefore: "Unexpected space before the ':'."
514
+ }
515
+ },
516
+ defaultOptions: [],
517
+ create: (context) => {
518
+ const sourceCode = context.getSourceCode();
519
+ return {
520
+ TSNamedTupleMember: (node) => {
521
+ const code = sourceCode.text.slice(node.range[0], node.range[1]);
522
+ const match = code.match(RE);
523
+ if (!match) {
524
+ return;
525
+ }
526
+ const labelName = node.label.name;
527
+ const spaceBeforeColon = match[2];
528
+ const optionalMark = match[3];
529
+ const spacesAfterColon = match[4];
530
+ const elementType = match[5];
531
+ function getReplaceValue() {
532
+ let ret = labelName;
533
+ if (node.optional) {
534
+ ret += "?";
535
+ }
536
+ ret += ": ";
537
+ ret += elementType;
538
+ return ret;
539
+ }
540
+ if (optionalMark?.length > 1) {
541
+ context.report({
542
+ node,
543
+ messageId: "unexpectedSpaceBetween",
544
+ *fix(fixer) {
545
+ yield fixer.replaceTextRange(node.range, code.replace(RE, getReplaceValue()));
546
+ }
547
+ });
548
+ }
549
+ if (spaceBeforeColon?.length) {
550
+ context.report({
551
+ node,
552
+ messageId: "unexpectedSpaceBefore",
553
+ *fix(fixer) {
554
+ yield fixer.replaceTextRange(node.range, code.replace(RE, getReplaceValue()));
555
+ }
556
+ });
557
+ }
558
+ if (spacesAfterColon != null && spacesAfterColon.length !== 1) {
559
+ context.report({
560
+ node,
561
+ messageId: "expectedSpaceAfter",
562
+ *fix(fixer) {
563
+ yield fixer.replaceTextRange(node.range, code.replace(RE, getReplaceValue()));
564
+ }
565
+ });
566
+ }
567
+ }
568
+ };
569
+ }
570
+ });
571
+
572
+ const RULE_NAME = "consistent-list-newline";
573
+ const consistentListNewline = createEslintRule({
574
+ name: RULE_NAME,
575
+ meta: {
576
+ type: "layout",
577
+ docs: {
578
+ description: "Having line breaks styles to object, array and named imports",
579
+ recommended: "stylistic"
580
+ },
581
+ fixable: "whitespace",
582
+ schema: [],
583
+ messages: {
584
+ shouldWrap: "Should have line breaks between items",
585
+ shouldNotWrap: "Should not have line breaks between items"
586
+ }
587
+ },
588
+ defaultOptions: [{}],
589
+ create: (context, [options = {}] = [{}]) => {
590
+ function removeLines(fixer, start, end) {
591
+ const range = [start, end];
592
+ const code = context.getSourceCode().text.slice(...range);
593
+ return fixer.replaceTextRange(range, code.replace(/(\r\n|\n)/g, ""));
594
+ }
595
+ function check(node, children, prevNode, nextNode) {
596
+ const items = children.filter(Boolean);
597
+ if (items.length === 0) {
598
+ return;
599
+ }
600
+ const startLine = prevNode ? prevNode.loc.end.line : node.loc.start.line;
601
+ let mode = null;
602
+ let lastLine = startLine;
603
+ items.forEach((item, idx) => {
604
+ if (mode == null) {
605
+ mode = item.loc.start.line === lastLine ? "inline" : "newline";
606
+ lastLine = item.loc.end.line;
607
+ return;
608
+ }
609
+ const currentStart = item.loc.start.line;
610
+ if (mode === "newline" && currentStart === lastLine) {
611
+ context.report({
612
+ node: item,
613
+ messageId: "shouldWrap",
614
+ *fix(fixer) {
615
+ yield fixer.insertTextBefore(item, "\n");
616
+ }
617
+ });
618
+ } else if (mode === "inline" && currentStart !== lastLine) {
619
+ const lastItem2 = items[idx - 1];
620
+ context.report({
621
+ node: item,
622
+ messageId: "shouldNotWrap",
623
+ *fix(fixer) {
624
+ yield removeLines(fixer, lastItem2.range[1], item.range[0]);
625
+ }
626
+ });
627
+ }
628
+ lastLine = item.loc.end.line;
629
+ });
630
+ const endLoc = nextNode?.loc.start ?? node.loc.end;
631
+ const endRange = nextNode?.range[0] ? nextNode?.range[0] - 1 : node.range[1];
632
+ const lastItem = items[items.length - 1];
633
+ if (mode === "newline" && endLoc.line === lastLine) {
634
+ context.report({
635
+ node: lastItem,
636
+ messageId: "shouldWrap",
637
+ *fix(fixer) {
638
+ yield fixer.insertTextAfter(lastItem, "\n");
639
+ }
640
+ });
641
+ } else if (mode === "inline" && endLoc.line !== lastLine) {
642
+ if (items.length === 1 && items[0].loc.start.line !== items[1]?.loc.start.line) {
643
+ return;
644
+ }
645
+ context.report({
646
+ node: lastItem,
647
+ messageId: "shouldNotWrap",
648
+ *fix(fixer) {
649
+ yield removeLines(fixer, lastItem.range[1], endRange);
650
+ }
651
+ });
652
+ }
653
+ }
654
+ const listenser = {
655
+ ObjectExpression: (node) => {
656
+ check(node, node.properties);
657
+ },
658
+ ArrayExpression: (node) => {
659
+ check(node, node.elements);
660
+ },
661
+ ImportDeclaration: (node) => {
662
+ check(node, node.specifiers);
663
+ },
664
+ ExportNamedDeclaration: (node) => {
665
+ check(node, node.specifiers);
666
+ },
667
+ FunctionDeclaration: (node) => {
668
+ check(
669
+ node,
670
+ node.params,
671
+ node.typeParameters || void 0,
672
+ node.returnType || node.body
673
+ );
674
+ },
675
+ FunctionExpression: (node) => {
676
+ check(
677
+ node,
678
+ node.params,
679
+ node.typeParameters || void 0,
680
+ node.returnType || node.body
681
+ );
682
+ },
683
+ ArrowFunctionExpression: (node) => {
684
+ check(
685
+ node,
686
+ node.params,
687
+ node.typeParameters || void 0,
688
+ node.returnType || node.body
689
+ );
690
+ },
691
+ CallExpression: (node) => {
692
+ const startNode = node.typeArguments?.params.length ? node.typeArguments.params[node.typeArguments.params.length - 1] : node.callee.type === "MemberExpression" ? node.callee.property : node.callee;
693
+ check(node, node.arguments, startNode);
694
+ },
695
+ TSInterfaceDeclaration: (node) => {
696
+ check(node, node.body.body);
697
+ },
698
+ TSTypeLiteral: (node) => {
699
+ check(node, node.members);
700
+ },
701
+ TSTupleType: (node) => {
702
+ check(node, node.elementTypes);
703
+ },
704
+ NewExpression: (node) => {
705
+ check(node, node.arguments, node.callee);
706
+ },
707
+ TSTypeParameterDeclaration(node) {
708
+ check(node, node.params);
709
+ },
710
+ TSTypeParameterInstantiation(node) {
711
+ check(node, node.params);
712
+ },
713
+ ObjectPattern(node) {
714
+ check(node, node.properties, void 0, node.typeAnnotation);
715
+ },
716
+ ArrayPattern(node) {
717
+ check(node, node.elements);
718
+ }
719
+ };
720
+ Object.keys(options).forEach((key) => {
721
+ if (options[key] === false) {
722
+ delete listenser[key];
723
+ }
724
+ });
725
+ return listenser;
726
+ }
727
+ });
728
+
729
+ const plugin = {
730
+ meta: {
731
+ name: "kirklin",
732
+ version
733
+ },
263
734
  rules: {
735
+ "consistent-list-newline": consistentListNewline,
736
+ "generic-spacing": genericSpacing,
264
737
  "if-newline": ifNewline,
265
738
  "import-dedupe": importDedupe,
739
+ "named-tuple-spacing": namedTupleSpacing,
740
+ "no-cjs-exports": noCjsExports,
741
+ "no-import-node-modules-by-path": noImportNodeModulesByPath,
742
+ "no-ts-export-equal": noTsExportEqual,
266
743
  "prefer-inline-type-import": preferInlineTypeImport,
267
- "generic-spacing": genericSpacing,
744
+ "top-level-function": topLevelFunction,
745
+ /**
746
+ * @deprecated Use `'no-restricted-syntax': ['error', 'TSEnumDeclaration[const=true]']` instead.
747
+ */
268
748
  "no-const-enum": noConstEnum
269
749
  }
270
750
  };
271
751
 
272
- module.exports = index;
752
+ module.exports = plugin;