eslint-plugin-react-jsx 5.17.0 → 5.17.2

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 (2) hide show
  1. package/dist/index.js +485 -13
  2. package/package.json +9 -9
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { Check, Extract } from "@eslint-react/ast";
4
4
  import * as core from "@eslint-react/core";
5
5
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
6
6
  import "@eslint-react/eslint";
7
- import { collapseMultilineText, findAttribute, getAttributeName, getChildren, getElementFullType, hasAnyAttribute, hasChildren, isEmptyStringExpression, isFragmentElement, isHostElement, isWhitespaceText } from "@eslint-react/jsx";
7
+ import { collapseMultilineText, findAttribute, getChildren, getElementFullType, hasAnyAttribute, hasChildren, isAttribute, isEmptyStringExpression, isFragmentElement, isHostElement, isWhitespaceText } from "@eslint-react/jsx";
8
8
  import ts from "typescript";
9
9
 
10
10
  //#region \0rolldown/runtime.js
@@ -26,7 +26,7 @@ var __exportAll = (all, no_symbols) => {
26
26
  //#endregion
27
27
  //#region package.json
28
28
  var name$2 = "eslint-plugin-react-jsx";
29
- var version = "5.17.0";
29
+ var version = "5.17.2";
30
30
 
31
31
  //#endregion
32
32
  //#region src/utils/create-rule.ts
@@ -261,6 +261,483 @@ function create$5(context) {
261
261
  return { JSXText: visit };
262
262
  }
263
263
 
264
+ //#endregion
265
+ //#region ../../.pkgs/eff/dist/index.js
266
+ function not(predicate) {
267
+ return (data) => !predicate(data);
268
+ }
269
+ /**
270
+ * Applies a `pipe` method's variadic arguments to an initial value from left
271
+ * to right.
272
+ *
273
+ * **When to use**
274
+ *
275
+ * Use to implement a custom `.pipe(...)` method from JavaScript's `arguments`
276
+ * object.
277
+ *
278
+ * **Details**
279
+ *
280
+ * This helper is intended for implementing `Pipeable.pipe` methods that
281
+ * receive JavaScript's `arguments` object. With no functions it returns the
282
+ * original value; otherwise it feeds each result into the next function.
283
+ *
284
+ * **Example** (Implementing a pipe method)
285
+ *
286
+ * ```ts
287
+ * import { Pipeable } from "effect"
288
+ *
289
+ * class NumberBox {
290
+ * constructor(readonly value: number) {}
291
+ *
292
+ * pipe(..._fns: ReadonlyArray<(value: number) => number>): number {
293
+ * return Pipeable.pipeArguments(this.value, arguments) as number
294
+ * }
295
+ * }
296
+ *
297
+ * const result = new NumberBox(5).pipe(
298
+ * (n) => n + 2,
299
+ * (n) => n * 3
300
+ * )
301
+ * console.log(result) // 21
302
+ * ```
303
+ *
304
+ * @category combinators
305
+ * @since 2.0.0
306
+ */
307
+ const pipeArguments = (self, args) => {
308
+ switch (args.length) {
309
+ case 0: return self;
310
+ case 1: return args[0](self);
311
+ case 2: return args[1](args[0](self));
312
+ case 3: return args[2](args[1](args[0](self)));
313
+ case 4: return args[3](args[2](args[1](args[0](self))));
314
+ case 5: return args[4](args[3](args[2](args[1](args[0](self)))));
315
+ case 6: return args[5](args[4](args[3](args[2](args[1](args[0](self))))));
316
+ case 7: return args[6](args[5](args[4](args[3](args[2](args[1](args[0](self)))))));
317
+ case 8: return args[7](args[6](args[5](args[4](args[3](args[2](args[1](args[0](self))))))));
318
+ case 9: return args[8](args[7](args[6](args[5](args[4](args[3](args[2](args[1](args[0](self)))))))));
319
+ default: {
320
+ let ret = self;
321
+ for (let i = 0, len = args.length; i < len; i++) ret = args[i](ret);
322
+ return ret;
323
+ }
324
+ }
325
+ };
326
+ /**
327
+ * Reusable prototype that implements `Pipeable.pipe`.
328
+ *
329
+ * **When to use**
330
+ *
331
+ * Use when classes or object prototypes can reuse this value when they need the
332
+ * standard pipe implementation backed by `pipeArguments`.
333
+ *
334
+ * @category prototypes
335
+ * @since 3.15.0
336
+ */
337
+ const Prototype = { pipe() {
338
+ return pipeArguments(this, arguments);
339
+ } };
340
+ /**
341
+ * Provides a base constructor whose instances implement the standard `Pipeable.pipe`
342
+ * method.
343
+ *
344
+ * **When to use**
345
+ *
346
+ * Use when you need to define a class that supports Effect-style method
347
+ * chaining through `.pipe(...)`.
348
+ *
349
+ * @category constructors
350
+ * @since 3.15.0
351
+ */
352
+ const Class = (function() {
353
+ function PipeableBase() {}
354
+ PipeableBase.prototype = Prototype;
355
+ return PipeableBase;
356
+ })();
357
+ /**
358
+ * Provides small helpers for defining and reusing TypeScript functions.
359
+ *
360
+ * The main helpers are `pipe` and `flow` for left-to-right composition and
361
+ * `dual` for APIs that support both direct and pipe-friendly call styles. The
362
+ * module also contains small identity, constant, tuple, type-level, and
363
+ * memoization helpers used across the library.
364
+ *
365
+ * @since 2.0.0
366
+ */
367
+ /**
368
+ * Creates a function that can be called in data-first style or data-last
369
+ * (`pipe`-friendly) style.
370
+ *
371
+ * **When to use**
372
+ *
373
+ * Use to expose one implementation through both direct and `pipe`-friendly
374
+ * call styles.
375
+ *
376
+ * **Details**
377
+ *
378
+ * Pass either the arity of the uncurried function or a predicate that decides
379
+ * whether the current call is data-first. Arity is the common case. Use a
380
+ * predicate when optional arguments make arity ambiguous.
381
+ *
382
+ * **Example** (Selecting data-first or data-last style by arity)
383
+ *
384
+ * ```ts
385
+ * import { Function, pipe } from "effect"
386
+ *
387
+ * const sum = Function.dual<
388
+ * (that: number) => (self: number) => number,
389
+ * (self: number, that: number) => number
390
+ * >(2, (self, that) => self + that)
391
+ *
392
+ * console.log(sum(2, 3)) // 5
393
+ * console.log(pipe(2, sum(3))) // 5
394
+ * ```
395
+ *
396
+ * **Example** (Defining overloads with call signatures)
397
+ *
398
+ * ```ts
399
+ * import { Function, pipe } from "effect"
400
+ *
401
+ * const sum: {
402
+ * (that: number): (self: number) => number
403
+ * (self: number, that: number): number
404
+ * } = Function.dual(2, (self: number, that: number): number => self + that)
405
+ *
406
+ * console.log(sum(2, 3)) // 5
407
+ * console.log(pipe(2, sum(3))) // 5
408
+ * ```
409
+ *
410
+ * **Example** (Selecting data-first or data-last style with a predicate)
411
+ *
412
+ * ```ts
413
+ * import { Function, pipe } from "effect"
414
+ *
415
+ * const sum = Function.dual<
416
+ * (that: number) => (self: number) => number,
417
+ * (self: number, that: number) => number
418
+ * >(
419
+ * (args) => args.length === 2,
420
+ * (self, that) => self + that
421
+ * )
422
+ *
423
+ * console.log(sum(2, 3)) // 5
424
+ * console.log(pipe(2, sum(3))) // 5
425
+ * ```
426
+ *
427
+ * @category combinators
428
+ * @since 2.0.0
429
+ */
430
+ const dual = function(arity, body) {
431
+ if (typeof arity === "function") return function() {
432
+ return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
433
+ };
434
+ switch (arity) {
435
+ case 0:
436
+ case 1: throw new RangeError(`Invalid arity ${arity}`);
437
+ case 2: return function(a, b) {
438
+ if (arguments.length >= 2) return body(a, b);
439
+ return function(self) {
440
+ return body(self, a);
441
+ };
442
+ };
443
+ case 3: return function(a, b, c) {
444
+ if (arguments.length >= 3) return body(a, b, c);
445
+ return function(self) {
446
+ return body(self, a, b);
447
+ };
448
+ };
449
+ default: return function() {
450
+ if (arguments.length >= arity) return body.apply(this, arguments);
451
+ const args = arguments;
452
+ return function(self) {
453
+ return body(self, ...args);
454
+ };
455
+ };
456
+ }
457
+ };
458
+ /**
459
+ * Returns its input argument unchanged.
460
+ *
461
+ * **When to use**
462
+ *
463
+ * Use to return a value unchanged where a function is required.
464
+ *
465
+ * **Example** (Returning the same value)
466
+ *
467
+ * ```ts
468
+ * import { identity } from "effect"
469
+ * import * as assert from "node:assert"
470
+ *
471
+ * assert.deepStrictEqual(identity(5), 5)
472
+ * ```
473
+ *
474
+ * @category combinators
475
+ * @since 2.0.0
476
+ */
477
+ const identity = (a) => a;
478
+ /**
479
+ * Returns the input value with a different static type.
480
+ *
481
+ * **When to use**
482
+ *
483
+ * Use when you need an explicit type-level cast and accept that the value is
484
+ * returned unchanged at runtime.
485
+ *
486
+ * **Gotchas**
487
+ *
488
+ * This is a type-level cast only; it performs no runtime validation or
489
+ * conversion.
490
+ *
491
+ * @see {@link satisfies} for checking assignability without changing the resulting type
492
+ *
493
+ * @category utility types
494
+ * @since 4.0.0
495
+ */
496
+ const cast = identity;
497
+ /**
498
+ * Creates a zero-argument function that always returns the provided value.
499
+ *
500
+ * **When to use**
501
+ *
502
+ * Use when you need a thunk or callback that returns the same value on every
503
+ * invocation.
504
+ *
505
+ * **Example** (Creating a constant thunk)
506
+ *
507
+ * ```ts
508
+ * import { Function } from "effect"
509
+ * import * as assert from "node:assert"
510
+ *
511
+ * const constNull = Function.constant(null)
512
+ *
513
+ * assert.deepStrictEqual(constNull(), null)
514
+ * assert.deepStrictEqual(constNull(), null)
515
+ * ```
516
+ *
517
+ * @category constructors
518
+ * @since 2.0.0
519
+ */
520
+ const constant = (value) => () => value;
521
+ /**
522
+ * Returns `true` when called.
523
+ *
524
+ * **When to use**
525
+ *
526
+ * Use when you need a thunk that returns `true` on every invocation.
527
+ *
528
+ * **Example** (Returning true from a thunk)
529
+ *
530
+ * ```ts
531
+ * import { Function } from "effect"
532
+ * import * as assert from "node:assert"
533
+ *
534
+ * assert.deepStrictEqual(Function.constTrue(), true)
535
+ * ```
536
+ *
537
+ * @category constants
538
+ * @since 2.0.0
539
+ */
540
+ const constTrue = constant(true);
541
+ /**
542
+ * Returns `false` when called.
543
+ *
544
+ * **When to use**
545
+ *
546
+ * Use when you need a thunk that returns `false` on every invocation.
547
+ *
548
+ * **Example** (Returning false from a thunk)
549
+ *
550
+ * ```ts
551
+ * import { Function } from "effect"
552
+ * import * as assert from "node:assert"
553
+ *
554
+ * assert.deepStrictEqual(Function.constFalse(), false)
555
+ * ```
556
+ *
557
+ * @category constants
558
+ * @since 2.0.0
559
+ */
560
+ const constFalse = constant(false);
561
+ /**
562
+ * Returns `null` when called.
563
+ *
564
+ * **When to use**
565
+ *
566
+ * Use when you need a thunk that returns `null` on every invocation.
567
+ *
568
+ * **Example** (Returning null from a thunk)
569
+ *
570
+ * ```ts
571
+ * import { Function } from "effect"
572
+ * import * as assert from "node:assert"
573
+ *
574
+ * assert.deepStrictEqual(Function.constNull(), null)
575
+ * ```
576
+ *
577
+ * @category constants
578
+ * @since 2.0.0
579
+ */
580
+ const constNull = constant(null);
581
+ /**
582
+ * Returns `undefined` when called.
583
+ *
584
+ * **When to use**
585
+ *
586
+ * Use when you need a thunk that returns `undefined` on every invocation.
587
+ *
588
+ * **Example** (Returning undefined from a thunk)
589
+ *
590
+ * ```ts
591
+ * import { Function } from "effect"
592
+ * import * as assert from "node:assert"
593
+ *
594
+ * assert.deepStrictEqual(Function.constUndefined(), undefined)
595
+ * ```
596
+ *
597
+ * @category constants
598
+ * @since 2.0.0
599
+ */
600
+ const constUndefined = constant(void 0);
601
+ /**
602
+ * Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
603
+ * The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
604
+ *
605
+ * **When to use**
606
+ *
607
+ * Use to compose exactly two unary functions into a reusable unary function.
608
+ *
609
+ * **Example** (Composing two functions)
610
+ *
611
+ * ```ts
612
+ * import { Function } from "effect"
613
+ * import * as assert from "node:assert"
614
+ *
615
+ * const increment = (n: number) => n + 1
616
+ * const square = (n: number) => n * n
617
+ *
618
+ * assert.strictEqual(Function.compose(increment, square)(2), 9)
619
+ * ```
620
+ *
621
+ * @see {@link flow} for composing a left-to-right sequence of functions
622
+ * @see {@link pipe} for applying a value through a left-to-right sequence immediately
623
+ *
624
+ * @category combinators
625
+ * @since 2.0.0
626
+ */
627
+ const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
628
+ /**
629
+ * Marks an impossible branch by accepting a `never` value and returning any
630
+ * type.
631
+ *
632
+ * **When to use**
633
+ *
634
+ * Use when you need a return value in a branch that exhaustive checks prove
635
+ * cannot be reached.
636
+ *
637
+ * **Gotchas**
638
+ *
639
+ * Calling `absurd` throws, because a value of type `never` should be
640
+ * impossible at runtime.
641
+ *
642
+ * **Example** (Handling impossible values)
643
+ *
644
+ * ```ts
645
+ * import { absurd } from "effect"
646
+ *
647
+ * const handleNever = (value: never) => {
648
+ * return absurd(value) // This will throw an error if called
649
+ * }
650
+ * ```
651
+ *
652
+ * @category utility types
653
+ * @since 2.0.0
654
+ */
655
+ const absurd = (_) => {
656
+ throw new Error("Called `absurd` function which should be uncallable");
657
+ };
658
+ /**
659
+ * Creates a compile-time placeholder for a value of any type.
660
+ *
661
+ * **When to use**
662
+ *
663
+ * Use as a temporary typed placeholder while developing incomplete code.
664
+ *
665
+ * **Gotchas**
666
+ *
667
+ * `hole` is intended for temporary development use. If the placeholder is
668
+ * evaluated at runtime, it throws.
669
+ *
670
+ * **Example** (Creating a development placeholder)
671
+ *
672
+ * ```ts
673
+ * import { hole } from "effect"
674
+ *
675
+ * // Intentionally not called: `hole` throws if the placeholder is evaluated.
676
+ * const buildUser = (id: number): { readonly id: number; readonly name: string } => ({
677
+ * id,
678
+ * name: hole<string>()
679
+ * })
680
+ *
681
+ * console.log(typeof buildUser) // "function"
682
+ * ```
683
+ *
684
+ * @category utility types
685
+ * @since 2.0.0
686
+ */
687
+ const hole = cast(absurd);
688
+ /**
689
+ * Drops the longest prefix of elements from an array that satisfy the given predicate.
690
+ *
691
+ * Supports both data-first and data-last (`pipe`-friendly) call styles.
692
+ *
693
+ * @param pred - The predicate to test each element with.
694
+ * @returns A new array without the matching prefix.
695
+ * @example
696
+ * ```ts
697
+ * import * as assert from "node:assert"
698
+ * import { dropWhile, pipe } from "@local/eff"
699
+ *
700
+ * // data-first
701
+ * assert.deepStrictEqual(dropWhile([1, 2, 3, 2, 1], (n: number) => n < 3), [3, 2, 1])
702
+ *
703
+ * // data-last
704
+ * assert.deepStrictEqual(pipe([1, 2, 3, 2, 1], dropWhile((n: number) => n < 3)), [3, 2, 1])
705
+ * ```
706
+ * @category array
707
+ */
708
+ const dropWhile = dual(2, (xs, pred) => {
709
+ const len = xs.length;
710
+ let idx = 0;
711
+ while (idx < len && pred(xs[idx])) idx++;
712
+ return xs.slice(idx);
713
+ });
714
+ /**
715
+ * Takes the longest prefix of elements from an array that satisfy the given predicate.
716
+ *
717
+ * Supports both data-first and data-last (`pipe`-friendly) call styles.
718
+ *
719
+ * @param pred - The predicate to test each element with.
720
+ * @returns A new array containing only the matching prefix.
721
+ * @example
722
+ * ```ts
723
+ * import * as assert from "node:assert"
724
+ * import { pipe, takeWhile } from "@local/eff"
725
+ *
726
+ * // data-first
727
+ * assert.deepStrictEqual(takeWhile([1, 2, 3, 2, 1], (n: number) => n < 3), [1, 2])
728
+ *
729
+ * // data-last
730
+ * assert.deepStrictEqual(pipe([1, 2, 3, 2, 1], takeWhile((n: number) => n < 3)), [1, 2])
731
+ * ```
732
+ * @category array
733
+ */
734
+ const takeWhile = dual(2, (xs, pred) => {
735
+ const len = xs.length;
736
+ let idx = 0;
737
+ while (idx < len && pred(xs[idx])) idx++;
738
+ return xs.slice(0, idx);
739
+ });
740
+
264
741
  //#endregion
265
742
  //#region src/rules/no-key-after-spread/no-key-after-spread.ts
266
743
  const RULE_NAME$4 = "no-key-after-spread";
@@ -276,20 +753,15 @@ var no_key_after_spread_default = createRule({
276
753
  defaultOptions: []
277
754
  });
278
755
  function create$4(context) {
756
+ if (!context.sourceCode.text.includes("key=")) return {};
279
757
  const { jsx } = core.getJsxConfig(context);
280
758
  if (jsx !== ts.JsxEmit.ReactJSX && jsx !== ts.JsxEmit.ReactJSXDev) return {};
759
+ const isJsxSpreadAttribute = Check.is(AST_NODE_TYPES.JSXSpreadAttribute);
281
760
  return { JSXOpeningElement(node) {
282
- let hasSpreadBefore = false;
283
- for (const prop of node.attributes) {
284
- if (prop.type === AST_NODE_TYPES.JSXSpreadAttribute) {
285
- hasSpreadBefore = true;
286
- continue;
287
- }
288
- if (hasSpreadBefore && getAttributeName(prop) === "key") context.report({
289
- messageId: "default",
290
- node: prop
291
- });
292
- }
761
+ for (const n of dropWhile(node.attributes, not(isJsxSpreadAttribute)).filter(isAttribute("key"))) context.report({
762
+ messageId: "default",
763
+ node: n
764
+ });
293
765
  } };
294
766
  }
295
767
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-jsx",
3
- "version": "5.17.0",
3
+ "version": "5.17.2",
4
4
  "description": "ESLint React's ESLint plugin for React Flavored JSX rules.",
5
5
  "keywords": [
6
6
  "react",
@@ -39,21 +39,21 @@
39
39
  "dependencies": {
40
40
  "@typescript-eslint/types": "^8.64.0",
41
41
  "@typescript-eslint/utils": "^8.64.0",
42
- "@eslint-react/ast": "5.17.0",
43
- "@eslint-react/core": "5.17.0",
44
- "@eslint-react/eslint": "5.17.0",
45
- "@eslint-react/jsx": "5.17.0",
46
- "@eslint-react/shared": "5.17.0"
42
+ "@eslint-react/ast": "5.17.2",
43
+ "@eslint-react/core": "5.17.2",
44
+ "@eslint-react/jsx": "5.17.2",
45
+ "@eslint-react/shared": "5.17.2",
46
+ "@eslint-react/eslint": "5.17.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/react": "^19.2.17",
50
50
  "@types/react-dom": "^19.2.3",
51
51
  "dedent": "^1.7.2",
52
52
  "eslint": "^10.7.0",
53
- "tsdown": "^0.22.7",
53
+ "tsdown": "^0.22.9",
54
54
  "typescript": "6.0.3",
55
- "@local/configs": "0.0.0",
56
- "@local/eff": "0.0.0"
55
+ "@local/eff": "0.0.0",
56
+ "@local/configs": "0.0.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "eslint": "*",