@eslint-react/jsx 0.5.8 → 0.5.9

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/dist/index.cjs CHANGED
@@ -1,17 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var memo = require('micro-memoize');
4
3
  require('@typescript-eslint/scope-manager');
5
4
  var types = require('@typescript-eslint/types');
6
5
  var utils = require('@typescript-eslint/utils');
7
-
8
- /**
9
- * Check if a JSXElement or JSXFragment has children
10
- * @param node The AST node to check
11
- * @returns `true` if the node has children
12
- */ function hasChildren(node) {
13
- return node.children.length > 0;
14
- }
6
+ var memo = require('micro-memoize');
15
7
 
16
8
  /**
17
9
  * @since 2.0.0
@@ -4760,43 +4752,6 @@ var effectData_esm = /*#__PURE__*/ Object.freeze({
4760
4752
  unsafeStruct: unsafeStruct
4761
4753
  });
4762
4754
 
4763
- /**
4764
- * Tests if a value is a `string`.
4765
- *
4766
- * @param input - The value to test.
4767
- *
4768
- * @example
4769
- * import { isString } from "effect/Predicate"
4770
- *
4771
- * assert.deepStrictEqual(isString("a"), true)
4772
- *
4773
- * assert.deepStrictEqual(isString(1), false)
4774
- *
4775
- * @category guards
4776
- * @since 2.0.0
4777
- */
4778
- const isString$1 = input => typeof input === "string";
4779
-
4780
- const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
4781
- // Does not check for reserved keywords or unicode characters
4782
- const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
4783
- function getFragmentFromContext(context) {
4784
- // eslint-disable-next-line prefer-destructuring
4785
- const settings = context.settings;
4786
- const fragment = settings.react?.fragment;
4787
- if (isString$1(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
4788
- return fragment;
4789
- }
4790
- return "Fragment";
4791
- }
4792
- const getPragmaFromContext = memo((context)=>{
4793
- // eslint-disable-next-line prefer-destructuring
4794
- const settings = context.settings;
4795
- const sourceCode = context.getSourceCode();
4796
- const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
4797
- return effectFunction_esm.pipe(effectOption_esm.orElse(effectOption_esm.fromNullable(settings.react?.pragma), ()=>effectFunction_esm.pipe(effectOption_esm.fromNullable(pragmaNode), effectOption_esm.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), effectOption_esm.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), effectOption_esm.flatMap(effectOption_esm.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), effectOption_esm.getOrElse(effectFunction_esm.constant("React")));
4798
- });
4799
-
4800
4755
  function isNil(x){
4801
4756
  return x === undefined || x === null
4802
4757
  }
@@ -4815,7 +4770,7 @@ function isNil(x){
4815
4770
  *
4816
4771
  * @category guards
4817
4772
  * @since 2.0.0
4818
- */ const isString = (input)=>typeof input === "string";
4773
+ */ const isString$1 = (input)=>typeof input === "string";
4819
4774
  const t$1 = Symbol.for("@ts-pattern/matcher"), e$1 = Symbol.for("@ts-pattern/isVariadic"), n$1 = "@ts-pattern/anonymous-select-key", r$1 = (t)=>Boolean(t && "object" == typeof t), i$1 = (e)=>e && !!e[t$1], s$1 = (n, o, c)=>{
4820
4775
  if (i$1(n)) {
4821
4776
  const e = n[t$1](), { matched: r, selections: i } = e.match(o);
@@ -6480,7 +6435,7 @@ Function.call.bind(Object.hasOwnProperty);
6480
6435
  return returnStatements;
6481
6436
  }
6482
6437
  function isStringLiteral(node) {
6483
- return node?.type === NodeType.Literal && isString(node.value);
6438
+ return node?.type === NodeType.Literal && isString$1(node.value);
6484
6439
  }
6485
6440
  /**
6486
6441
  * Check if a node is multiline
@@ -6552,6 +6507,62 @@ function isStringLiteral(node) {
6552
6507
  };
6553
6508
  }
6554
6509
 
6510
+ /**
6511
+ * Check if a `JSXElement` or `JSXFragment` has children
6512
+ * @param node The AST node to check
6513
+ * @param predicate A predicate to filter the children
6514
+ * @returns `true` if the node has children
6515
+ */ function hasChildren(node, predicate) {
6516
+ if (typeof predicate === "function") {
6517
+ return node.children.some(predicate);
6518
+ }
6519
+ return node.children.length > 0;
6520
+ }
6521
+ /**
6522
+ * Check if a node is a child of a `JSXElement`
6523
+ * @param node The AST node to check
6524
+ * @returns `true` if the node is a child of a `JSXElement`
6525
+ */ function isChildOfJSXElement(node) {
6526
+ return node.parent?.type === NodeType.JSXElement && node.parent.children.some((child)=>child === node);
6527
+ }
6528
+
6529
+ /**
6530
+ * Tests if a value is a `string`.
6531
+ *
6532
+ * @param input - The value to test.
6533
+ *
6534
+ * @example
6535
+ * import { isString } from "effect/Predicate"
6536
+ *
6537
+ * assert.deepStrictEqual(isString("a"), true)
6538
+ *
6539
+ * assert.deepStrictEqual(isString(1), false)
6540
+ *
6541
+ * @category guards
6542
+ * @since 2.0.0
6543
+ */
6544
+ const isString = input => typeof input === "string";
6545
+
6546
+ const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
6547
+ // Does not check for reserved keywords or unicode characters
6548
+ const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
6549
+ function getFragmentFromContext(context) {
6550
+ // eslint-disable-next-line prefer-destructuring
6551
+ const settings = context.settings;
6552
+ const fragment = settings.react?.fragment;
6553
+ if (isString(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
6554
+ return fragment;
6555
+ }
6556
+ return "Fragment";
6557
+ }
6558
+ const getPragmaFromContext = memo((context)=>{
6559
+ // eslint-disable-next-line prefer-destructuring
6560
+ const settings = context.settings;
6561
+ const sourceCode = context.getSourceCode();
6562
+ const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
6563
+ return effectFunction_esm.pipe(effectOption_esm.orElse(effectOption_esm.fromNullable(settings.react?.pragma), ()=>effectFunction_esm.pipe(effectOption_esm.fromNullable(pragmaNode), effectOption_esm.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), effectOption_esm.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), effectOption_esm.flatMap(effectOption_esm.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), effectOption_esm.getOrElse(effectFunction_esm.constant("React")));
6564
+ });
6565
+
6555
6566
  const t=Symbol.for("@ts-pattern/matcher"),e=Symbol.for("@ts-pattern/isVariadic"),n="@ts-pattern/anonymous-select-key",r=t=>Boolean(t&&"object"==typeof t),i=e=>e&&!!e[t],s=(n,o,c)=>{if(i(n)){const e=n[t](),{matched:r,selections:i}=e.match(o);return r&&i&&Object.keys(i).forEach(t=>c(t,i[t])),r}if(r(n)){if(!r(o))return !1;if(Array.isArray(n)){if(!Array.isArray(o))return !1;let t=[],r=[],a=[];for(const s of n.keys()){const o=n[s];i(o)&&o[e]?a.push(o):a.length?r.push(o):t.push(o);}if(a.length){if(a.length>1)throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");if(o.length<t.length+r.length)return !1;const e=o.slice(0,t.length),n=0===r.length?[]:o.slice(-r.length),i=o.slice(t.length,0===r.length?Infinity:-r.length);return t.every((t,n)=>s(t,e[n],c))&&r.every((t,e)=>s(t,n[e],c))&&(0===a.length||s(a[0],i,c))}return n.length===o.length&&n.every((t,e)=>s(t,o[e],c))}return Object.keys(n).every(e=>{const r=n[e];return (e in o||i(a=r)&&"optional"===a[t]().matcherType)&&s(r,o[e],c);var a;})}return Object.is(o,n)},o=e=>{var n,s,a;return r(e)?i(e)?null!=(n=null==(s=(a=e[t]()).getSelectionKeys)?void 0:s.call(a))?n:[]:Array.isArray(e)?c(e,o):c(Object.values(e),o):[]},c=(t,e)=>t.reduce((t,n)=>t.concat(e(n)),[]);function a(...t){if(1===t.length){const[e]=t;return t=>s(e,t,()=>{})}if(2===t.length){const[e,n]=t;return s(e,n,()=>{})}throw new Error(`isMatching wasn't given the right number of arguments: expected 1 or 2, received ${t.length}.`)}function u(t){return Object.assign(t,{optional:()=>l(t),and:e=>m(t,e),or:e=>y(t,e),select:e=>void 0===e?p(t):p(e,t)})}function h(t){return Object.assign((t=>Object.assign(t,{*[Symbol.iterator](){yield Object.assign(t,{[e]:!0});}}))(t),{optional:()=>h(l(t)),select:e=>h(void 0===e?p(t):p(e,t))})}function l(e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return void 0===t?(o(e).forEach(t=>r(t,void 0)),{matched:!0,selections:n}):{matched:s(e,t,r),selections:n}},getSelectionKeys:()=>o(e),matcherType:"optional"})})}const f=(t,e)=>{for(const n of t)if(!e(n))return !1;return !0},g=(t,e)=>{for(const[n,r]of t.entries())if(!e(r,n))return !1;return !0};function m(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return {matched:e.every(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"and"})})}function y(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return c(e,o).forEach(t=>r(t,void 0)),{matched:e.some(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"or"})})}function d(e){return {[t]:()=>({match:t=>({matched:Boolean(e(t))})})}}function p(...e){const r="string"==typeof e[0]?e[0]:void 0,i=2===e.length?e[1]:"string"==typeof e[0]?void 0:e[0];return u({[t]:()=>({match:t=>{let e={[null!=r?r:n]:t};return {matched:void 0===i||s(i,t,(t,n)=>{e[t]=n;}),selections:e}},getSelectionKeys:()=>[null!=r?r:n].concat(void 0===i?[]:o(i))})})}function v(t){return "number"==typeof t}function b(t){return "string"==typeof t}function w(t){return "bigint"==typeof t}const S=u(d(function(t){return !0})),O=S,j=t=>Object.assign(u(t),{startsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.startsWith(n)))));var n;},endsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.endsWith(n)))));var n;},minLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length>=t))(e))),maxLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length<=t))(e))),includes:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.includes(n)))));var n;},regex:e=>{return j(m(t,(n=e,d(t=>b(t)&&Boolean(t.match(n))))));var n;}}),E=j(d(b)),K=t=>Object.assign(u(t),{between:(e,n)=>K(m(t,((t,e)=>d(n=>v(n)&&t<=n&&e>=n))(e,n))),lt:e=>K(m(t,(t=>d(e=>v(e)&&e<t))(e))),gt:e=>K(m(t,(t=>d(e=>v(e)&&e>t))(e))),lte:e=>K(m(t,(t=>d(e=>v(e)&&e<=t))(e))),gte:e=>K(m(t,(t=>d(e=>v(e)&&e>=t))(e))),int:()=>K(m(t,d(t=>v(t)&&Number.isInteger(t)))),finite:()=>K(m(t,d(t=>v(t)&&Number.isFinite(t)))),positive:()=>K(m(t,d(t=>v(t)&&t>0))),negative:()=>K(m(t,d(t=>v(t)&&t<0)))}),A=K(d(v)),x=t=>Object.assign(u(t),{between:(e,n)=>x(m(t,((t,e)=>d(n=>w(n)&&t<=n&&e>=n))(e,n))),lt:e=>x(m(t,(t=>d(e=>w(e)&&e<t))(e))),gt:e=>x(m(t,(t=>d(e=>w(e)&&e>t))(e))),lte:e=>x(m(t,(t=>d(e=>w(e)&&e<=t))(e))),gte:e=>x(m(t,(t=>d(e=>w(e)&&e>=t))(e))),positive:()=>x(m(t,d(t=>w(t)&&t>0))),negative:()=>x(m(t,d(t=>w(t)&&t<0)))}),P=x(d(w)),T=u(d(function(t){return "boolean"==typeof t})),k=u(d(function(t){return "symbol"==typeof t})),B=u(d(function(t){return null==t}));var _={__proto__:null,matcher:t,optional:l,array:function(...e){return h({[t]:()=>({match:t=>{if(!Array.isArray(t))return {matched:!1};if(0===e.length)return {matched:!0};const n=e[0];let r={};if(0===t.length)return o(n).forEach(t=>{r[t]=[];}),{matched:!0,selections:r};const i=(t,e)=>{r[t]=(r[t]||[]).concat([e]);};return {matched:t.every(t=>s(n,t,i)),selections:r}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},set:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Set))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};if(0===e.length)return {matched:!0};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);},i=e[0];return {matched:f(t,t=>s(i,t,r)),selections:n}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},map:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Map))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);};if(0===e.length)return {matched:!0};var i;if(1===e.length)throw new Error(`\`P.map\` wasn't given enough arguments. Expected (key, value), received ${null==(i=e[0])?void 0:i.toString()}`);const[o,c]=e;return {matched:g(t,(t,e)=>{const n=s(o,e,r),i=s(c,t,r);return n&&i}),selections:n}},getSelectionKeys:()=>0===e.length?[]:[...o(e[0]),...o(e[1])]})})},intersection:m,union:y,not:function(e){return u({[t]:()=>({match:t=>({matched:!s(e,t,()=>{})}),getSelectionKeys:()=>[],matcherType:"not"})})},when:d,select:p,any:S,_:O,string:E,number:A,bigint:P,boolean:T,symbol:k,nullish:B,instanceOf:function(t){return u(d(function(t){return e=>e instanceof t}(t)))},shape:function(t){return u(d(a(t)))}};const W={matched:!1,value:void 0};function N(t){return new $(t,W)}class ${constructor(t,e){this.input=void 0,this.state=void 0,this.input=t,this.state=e;}with(...t){if(this.state.matched)return this;const e=t[t.length-1],r=[t[0]];let i;3===t.length&&"function"==typeof t[1]?(r.push(t[0]),i=t[1]):t.length>2&&r.push(...t.slice(1,t.length-1));let o=!1,c={};const a=(t,e)=>{o=!0,c[t]=e;},u=!r.some(t=>s(t,this.input,a))||i&&!Boolean(i(this.input))?W:{matched:!0,value:e(o?n in c?c[n]:c:this.input,this.input)};return new $(this.input,u)}when(t,e){if(this.state.matched)return this;const n=Boolean(t(this.input));return new $(this.input,n?{matched:!0,value:e(this.input,this.input)}:W)}otherwise(t){return this.state.matched?this.state.value:t(this.input)}exhaustive(){return this.run()}run(){if(this.state.matched)return this.state.value;let t;try{t=JSON.stringify(this.input);}catch(e){t=this.input;}throw new Error(`Pattern matching error: no pattern matches value ${t}`)}returnType(){return this}}
6556
6567
 
6557
6568
  function isPropertyOfPragma(name, context, pragma = getPragmaFromContext(context)) {
@@ -6667,6 +6678,21 @@ function isChildrenOfCreateElement(node, context) {
6667
6678
  return maybeCallExpression.arguments.slice(2).some((child)=>child === node);
6668
6679
  }
6669
6680
 
6681
+ /**
6682
+ * Check if a node is a `JSXElement` of `User-Defined Component` type
6683
+ * @param node The AST node to check
6684
+ * @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
6685
+ */ function isJSXElementOfUserDefinedComponent(node) {
6686
+ return node.type === NodeType.JSXElement && node.openingElement.name.type === NodeType.JSXIdentifier && /^[A-Z]/u.test(node.openingElement.name.name);
6687
+ }
6688
+ /**
6689
+ * Check if a node is a `JSXFragment` of `Built-in Component` type
6690
+ * @param node The AST node to check
6691
+ * @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
6692
+ */ function isJSXElementOfBuiltinComponent(node) {
6693
+ return node.type === NodeType.JSXElement && node.openingElement.name.type === NodeType.JSXIdentifier && node.openingElement.name.name.toLowerCase() === node.openingElement.name.name && /^[a-z]/u.test(node.openingElement.name.name);
6694
+ }
6695
+
6670
6696
  /**
6671
6697
  * Determines whether inside createElement's props.
6672
6698
  * @param node The AST node to check
@@ -6822,6 +6848,89 @@ const hdlWheel = [
6822
6848
  ...hdlWheel
6823
6849
  ];
6824
6850
 
6851
+ /**
6852
+ * Check if a node is a Literal or JSXText
6853
+ * @param node The AST node to check
6854
+ * @returns boolean `true` if the node is a Literal or JSXText
6855
+ */ const isLiteral = isOneOf([
6856
+ NodeType.Literal,
6857
+ NodeType.JSXText
6858
+ ]);
6859
+ /**
6860
+ * Check if a Literal or JSXText node is whitespace
6861
+ * @param node The AST node to check
6862
+ * @returns boolean `true` if the node is whitespace
6863
+ */ function isWhiteSpace(node) {
6864
+ return isString(node.value) && node.value.trim() === "";
6865
+ }
6866
+ /**
6867
+ * Check if a Literal or JSXText node is a line break
6868
+ * @param node The AST node to check
6869
+ * @returns boolean
6870
+ */ function isLineBreak(node) {
6871
+ return isLiteral(node) && isWhiteSpace(node) && isMultiLine(node);
6872
+ }
6873
+ /**
6874
+ * Check if a Literal or JSXText node is padding spaces
6875
+ * @param node The AST node to check
6876
+ * @returns boolean
6877
+ */ function isPaddingSpaces(node) {
6878
+ return isLiteral(node) && isWhiteSpace(node) && node.raw.includes("\n");
6879
+ }
6880
+
6881
+ const isFragment = (node, pragma, fragment)=>{
6882
+ if (!isOneOf([
6883
+ NodeType.JSXElement,
6884
+ NodeType.JSXFragment
6885
+ ])(node)) {
6886
+ return false;
6887
+ }
6888
+ return isFragmentSyntax(node) || isFragmentElement(node, pragma, fragment);
6889
+ };
6890
+ /**
6891
+ * Check if a node is `<></>`
6892
+ */ const isFragmentSyntax = is(NodeType.JSXFragment);
6893
+ /**
6894
+ * Check if a node is `<Fragment></Fragment>` or `<Pragma.Fragment></Pragma.Fragment>`
6895
+ * @param node
6896
+ * @param pragma
6897
+ * @param fragment
6898
+ */ function isFragmentElement(node, pragma, fragment) {
6899
+ const { name } = node.openingElement;
6900
+ // <Fragment>
6901
+ if (name.type === NodeType.JSXIdentifier && name.name === fragment) {
6902
+ return true;
6903
+ }
6904
+ // <Pragma.Fragment>
6905
+ return name.type === NodeType.JSXMemberExpression && name.object.type === NodeType.JSXIdentifier && name.object.name === pragma && name.property.name === fragment;
6906
+ }
6907
+ /**
6908
+ * Check if a JSXElement or JSXFragment has only one literal child and is not a child
6909
+ * @param node The AST node to check
6910
+ * @returns `true` if the node has only one literal child and is not a child
6911
+ * @example Somehow fragment like this is useful: <Foo content={<>ee eeee eeee ...</>} />
6912
+ */ function isFragmentWithOnlyTextAndIsNotChild(node) {
6913
+ return node.children.length === 1 && isLiteral(node.children[0]) && !(node.parent.type === NodeType.JSXElement || node.parent.type === NodeType.JSXFragment);
6914
+ }
6915
+ function containsCallExpression(node) {
6916
+ return node.type === NodeType.JSXExpressionContainer && node.expression.type === NodeType.CallExpression;
6917
+ }
6918
+ /**
6919
+ * Check if a JSXElement or JSXFragment has less than two non-padding children and the first child is not a call expression
6920
+ * @param node The AST node to check
6921
+ * @returns boolean
6922
+ */ function isFragmentHasLessThanTwoChildren(node) {
6923
+ const nonPaddingChildren = node.children.filter((child)=>!isPaddingSpaces(child));
6924
+ if (nonPaddingChildren.length === 1) {
6925
+ return !containsCallExpression(nonPaddingChildren[0]);
6926
+ }
6927
+ return nonPaddingChildren.length === 0;
6928
+ }
6929
+ function isFragmentWithSingleExpression(node) {
6930
+ const children = node.children.filter((child)=>!isPaddingSpaces(child));
6931
+ return children.length === 1 && children[0]?.type === NodeType.JSXExpressionContainer;
6932
+ }
6933
+
6825
6934
  const defaultJSXValueCheckOptions = {
6826
6935
  ignoreNull: false,
6827
6936
  strict: false
@@ -6871,7 +6980,7 @@ const defaultJSXValueCheckOptions = {
6871
6980
  if (isJSXTagNameExpression(node)) {
6872
6981
  return true;
6873
6982
  }
6874
- if (!isString$1(node.name) && node.name.type !== NodeType.Identifier) {
6983
+ if (!isString(node.name) && node.name.type !== NodeType.Identifier) {
6875
6984
  return isJSXTagNameExpression(node.name);
6876
6985
  }
6877
6986
  const name = N(node.name).with(_.string, effectFunction_esm.identity).with({
@@ -7053,29 +7162,6 @@ const defaultJSXValueCheckOptions = {
7053
7162
  return effectOption_esm.some(getStaticValue(argument, scope));
7054
7163
  }
7055
7164
 
7056
- /**
7057
- * Check if a node is a Literal or JSXText
7058
- * @param node The AST node to check
7059
- * @returns boolean `true` if the node is a Literal or JSXText
7060
- */ const isLiteral = isOneOf([
7061
- NodeType.Literal,
7062
- NodeType.JSXText
7063
- ]);
7064
- /**
7065
- * Check if a Literal or JSXText node is whitespace
7066
- * @param node The AST node to check
7067
- * @returns boolean `true` if the node is whitespace
7068
- */ function isWhiteSpace(node) {
7069
- return isString$1(node.value) && node.value.trim() === "";
7070
- }
7071
- /**
7072
- * Check if a Literal or JSXText node is a line break
7073
- * @param node The AST node to check
7074
- * @returns boolean
7075
- */ function isLineBreak(node) {
7076
- return isLiteral(node) && isWhiteSpace(node) && isMultiLine(node);
7077
- }
7078
-
7079
7165
  exports.defaultJSXValueCheckOptions = defaultJSXValueCheckOptions;
7080
7166
  exports.elementType = elementType;
7081
7167
  exports.findPropInAttributes = findPropInAttributes;
@@ -7104,16 +7190,26 @@ exports.hdlTouch = hdlTouch;
7104
7190
  exports.hdlTransition = hdlTransition;
7105
7191
  exports.hdlWheel = hdlWheel;
7106
7192
  exports.isCallFromPragma = isCallFromPragma;
7193
+ exports.isChildOfJSXElement = isChildOfJSXElement;
7107
7194
  exports.isChildrenOfCreateElement = isChildrenOfCreateElement;
7108
7195
  exports.isCloneElementCall = isCloneElementCall;
7109
7196
  exports.isCreateElementCall = isCreateElementCall;
7197
+ exports.isFragment = isFragment;
7198
+ exports.isFragmentElement = isFragmentElement;
7199
+ exports.isFragmentHasLessThanTwoChildren = isFragmentHasLessThanTwoChildren;
7200
+ exports.isFragmentSyntax = isFragmentSyntax;
7201
+ exports.isFragmentWithOnlyTextAndIsNotChild = isFragmentWithOnlyTextAndIsNotChild;
7202
+ exports.isFragmentWithSingleExpression = isFragmentWithSingleExpression;
7110
7203
  exports.isFunctionReturningJSXValue = isFunctionReturningJSXValue;
7111
7204
  exports.isInitializedFromPragma = isInitializedFromPragma;
7112
7205
  exports.isInsideCreateElementProps = isInsideCreateElementProps;
7113
7206
  exports.isInsidePropValue = isInsidePropValue;
7207
+ exports.isJSXElementOfBuiltinComponent = isJSXElementOfBuiltinComponent;
7208
+ exports.isJSXElementOfUserDefinedComponent = isJSXElementOfUserDefinedComponent;
7114
7209
  exports.isJSXValue = isJSXValue;
7115
7210
  exports.isLineBreak = isLineBreak;
7116
7211
  exports.isLiteral = isLiteral;
7212
+ exports.isPaddingSpaces = isPaddingSpaces;
7117
7213
  exports.isPropertyOfPragma = isPropertyOfPragma;
7118
7214
  exports.isWhiteSpace = isWhiteSpace;
7119
7215
  exports.traverseUpProp = traverseUpProp;
package/dist/index.d.mts CHANGED
@@ -5,14 +5,36 @@ import { TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
5
5
  import { O } from '@eslint-react/tools';
6
6
 
7
7
  /**
8
- * Check if a JSXElement or JSXFragment has children
8
+ * Check if a `JSXElement` or `JSXFragment` has children
9
9
  * @param node The AST node to check
10
+ * @param predicate A predicate to filter the children
10
11
  * @returns `true` if the node has children
11
12
  */
12
- declare function hasChildren(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
13
+ declare function hasChildren(node: TSESTree.JSXElement | TSESTree.JSXFragment, predicate?: (node: TSESTree.JSXChild) => boolean): boolean;
14
+ /**
15
+ * Check if a node is a child of a `JSXElement`
16
+ * @param node The AST node to check
17
+ * @returns `true` if the node is a child of a `JSXElement`
18
+ */
19
+ declare function isChildOfJSXElement(node: TSESTree.Node): node is TSESTree.JSXElement & {
20
+ parent: TSESTree.JSXElement;
21
+ };
13
22
 
14
23
  declare function isChildrenOfCreateElement(node: TSESTree.Node, context: RuleContext): boolean;
15
24
 
25
+ /**
26
+ * Check if a node is a `JSXElement` of `User-Defined Component` type
27
+ * @param node The AST node to check
28
+ * @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
29
+ */
30
+ declare function isJSXElementOfUserDefinedComponent(node: TSESTree.Node): node is TSESTree.JSXElement;
31
+ /**
32
+ * Check if a node is a `JSXFragment` of `Built-in Component` type
33
+ * @param node The AST node to check
34
+ * @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
35
+ */
36
+ declare function isJSXElementOfBuiltinComponent(node: TSESTree.Node): node is TSESTree.JSXFragment;
37
+
16
38
  declare function getFragmentFromContext<T extends RuleContext>(context: T): string;
17
39
  declare const getPragmaFromContext: <T extends RuleContext>(context: T) => string;
18
40
 
@@ -72,6 +94,33 @@ declare const hdlTransition: readonly ["onTransitionEnd"];
72
94
  declare const hdlScroll: readonly ["onScroll"];
73
95
  declare const hdlWheel: readonly ["onWheel"];
74
96
 
97
+ declare const isFragment: (node: TSESTree.Node, pragma: string, fragment: string) => node is TSESTree.JSXElement | TSESTree.JSXFragment;
98
+ /**
99
+ * Check if a node is `<></>`
100
+ */
101
+ declare const isFragmentSyntax: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXFragment;
102
+ /**
103
+ * Check if a node is `<Fragment></Fragment>` or `<Pragma.Fragment></Pragma.Fragment>`
104
+ * @param node
105
+ * @param pragma
106
+ * @param fragment
107
+ */
108
+ declare function isFragmentElement(node: TSESTree.JSXElement, pragma: string, fragment: string): boolean;
109
+ /**
110
+ * Check if a JSXElement or JSXFragment has only one literal child and is not a child
111
+ * @param node The AST node to check
112
+ * @returns `true` if the node has only one literal child and is not a child
113
+ * @example Somehow fragment like this is useful: <Foo content={<>ee eeee eeee ...</>} />
114
+ */
115
+ declare function isFragmentWithOnlyTextAndIsNotChild(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
116
+ /**
117
+ * Check if a JSXElement or JSXFragment has less than two non-padding children and the first child is not a call expression
118
+ * @param node The AST node to check
119
+ * @returns boolean
120
+ */
121
+ declare function isFragmentHasLessThanTwoChildren(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
122
+ declare function isFragmentWithSingleExpression(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
123
+
75
124
  type JSXValueCheckOptions = {
76
125
  /**
77
126
  * Whether to check all branches of the conditional expression
@@ -196,5 +245,11 @@ declare function isWhiteSpace(node: TSESTree.JSXText | TSESTree.Literal): boolea
196
245
  * @returns boolean
197
246
  */
198
247
  declare function isLineBreak(node: TSESTree.Node): boolean;
248
+ /**
249
+ * Check if a Literal or JSXText node is padding spaces
250
+ * @param node The AST node to check
251
+ * @returns boolean
252
+ */
253
+ declare function isPaddingSpaces(node: TSESTree.Node): boolean;
199
254
 
200
- export { type CallFromPragmaPredicate, type JSXValueCheckOptions, defaultJSXValueCheckOptions, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getPropName, getPropNameWithNamespace, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXValue, isLineBreak, isLiteral, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
255
+ export { type CallFromPragmaPredicate, type JSXValueCheckOptions, defaultJSXValueCheckOptions, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getPropName, getPropNameWithNamespace, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildOfJSXElement, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFragment, isFragmentElement, isFragmentHasLessThanTwoChildren, isFragmentSyntax, isFragmentWithOnlyTextAndIsNotChild, isFragmentWithSingleExpression, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXElementOfBuiltinComponent, isJSXElementOfUserDefinedComponent, isJSXValue, isLineBreak, isLiteral, isPaddingSpaces, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
package/dist/index.d.ts CHANGED
@@ -5,14 +5,36 @@ import { TSESTree as TSESTree$1 } from '@typescript-eslint/utils';
5
5
  import { O } from '@eslint-react/tools';
6
6
 
7
7
  /**
8
- * Check if a JSXElement or JSXFragment has children
8
+ * Check if a `JSXElement` or `JSXFragment` has children
9
9
  * @param node The AST node to check
10
+ * @param predicate A predicate to filter the children
10
11
  * @returns `true` if the node has children
11
12
  */
12
- declare function hasChildren(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
13
+ declare function hasChildren(node: TSESTree.JSXElement | TSESTree.JSXFragment, predicate?: (node: TSESTree.JSXChild) => boolean): boolean;
14
+ /**
15
+ * Check if a node is a child of a `JSXElement`
16
+ * @param node The AST node to check
17
+ * @returns `true` if the node is a child of a `JSXElement`
18
+ */
19
+ declare function isChildOfJSXElement(node: TSESTree.Node): node is TSESTree.JSXElement & {
20
+ parent: TSESTree.JSXElement;
21
+ };
13
22
 
14
23
  declare function isChildrenOfCreateElement(node: TSESTree.Node, context: RuleContext): boolean;
15
24
 
25
+ /**
26
+ * Check if a node is a `JSXElement` of `User-Defined Component` type
27
+ * @param node The AST node to check
28
+ * @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
29
+ */
30
+ declare function isJSXElementOfUserDefinedComponent(node: TSESTree.Node): node is TSESTree.JSXElement;
31
+ /**
32
+ * Check if a node is a `JSXFragment` of `Built-in Component` type
33
+ * @param node The AST node to check
34
+ * @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
35
+ */
36
+ declare function isJSXElementOfBuiltinComponent(node: TSESTree.Node): node is TSESTree.JSXFragment;
37
+
16
38
  declare function getFragmentFromContext<T extends RuleContext>(context: T): string;
17
39
  declare const getPragmaFromContext: <T extends RuleContext>(context: T) => string;
18
40
 
@@ -72,6 +94,33 @@ declare const hdlTransition: readonly ["onTransitionEnd"];
72
94
  declare const hdlScroll: readonly ["onScroll"];
73
95
  declare const hdlWheel: readonly ["onWheel"];
74
96
 
97
+ declare const isFragment: (node: TSESTree.Node, pragma: string, fragment: string) => node is TSESTree.JSXElement | TSESTree.JSXFragment;
98
+ /**
99
+ * Check if a node is `<></>`
100
+ */
101
+ declare const isFragmentSyntax: (node: TSESTree.Node | null | undefined) => node is TSESTree.JSXFragment;
102
+ /**
103
+ * Check if a node is `<Fragment></Fragment>` or `<Pragma.Fragment></Pragma.Fragment>`
104
+ * @param node
105
+ * @param pragma
106
+ * @param fragment
107
+ */
108
+ declare function isFragmentElement(node: TSESTree.JSXElement, pragma: string, fragment: string): boolean;
109
+ /**
110
+ * Check if a JSXElement or JSXFragment has only one literal child and is not a child
111
+ * @param node The AST node to check
112
+ * @returns `true` if the node has only one literal child and is not a child
113
+ * @example Somehow fragment like this is useful: <Foo content={<>ee eeee eeee ...</>} />
114
+ */
115
+ declare function isFragmentWithOnlyTextAndIsNotChild(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
116
+ /**
117
+ * Check if a JSXElement or JSXFragment has less than two non-padding children and the first child is not a call expression
118
+ * @param node The AST node to check
119
+ * @returns boolean
120
+ */
121
+ declare function isFragmentHasLessThanTwoChildren(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
122
+ declare function isFragmentWithSingleExpression(node: TSESTree.JSXElement | TSESTree.JSXFragment): boolean;
123
+
75
124
  type JSXValueCheckOptions = {
76
125
  /**
77
126
  * Whether to check all branches of the conditional expression
@@ -196,5 +245,11 @@ declare function isWhiteSpace(node: TSESTree.JSXText | TSESTree.Literal): boolea
196
245
  * @returns boolean
197
246
  */
198
247
  declare function isLineBreak(node: TSESTree.Node): boolean;
248
+ /**
249
+ * Check if a Literal or JSXText node is padding spaces
250
+ * @param node The AST node to check
251
+ * @returns boolean
252
+ */
253
+ declare function isPaddingSpaces(node: TSESTree.Node): boolean;
199
254
 
200
- export { type CallFromPragmaPredicate, type JSXValueCheckOptions, defaultJSXValueCheckOptions, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getPropName, getPropNameWithNamespace, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXValue, isLineBreak, isLiteral, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
255
+ export { type CallFromPragmaPredicate, type JSXValueCheckOptions, defaultJSXValueCheckOptions, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getPropName, getPropNameWithNamespace, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildOfJSXElement, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFragment, isFragmentElement, isFragmentHasLessThanTwoChildren, isFragmentSyntax, isFragmentWithOnlyTextAndIsNotChild, isFragmentWithSingleExpression, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXElementOfBuiltinComponent, isJSXElementOfUserDefinedComponent, isJSXValue, isLineBreak, isLiteral, isPaddingSpaces, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
package/dist/index.js CHANGED
@@ -1,17 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var memo = require('micro-memoize');
4
3
  require('@typescript-eslint/scope-manager');
5
4
  var types = require('@typescript-eslint/types');
6
5
  var utils = require('@typescript-eslint/utils');
7
-
8
- /**
9
- * Check if a JSXElement or JSXFragment has children
10
- * @param node The AST node to check
11
- * @returns `true` if the node has children
12
- */ function hasChildren(node) {
13
- return node.children.length > 0;
14
- }
6
+ var memo = require('micro-memoize');
15
7
 
16
8
  /**
17
9
  * @since 2.0.0
@@ -4760,43 +4752,6 @@ var effectData_esm = /*#__PURE__*/ Object.freeze({
4760
4752
  unsafeStruct: unsafeStruct
4761
4753
  });
4762
4754
 
4763
- /**
4764
- * Tests if a value is a `string`.
4765
- *
4766
- * @param input - The value to test.
4767
- *
4768
- * @example
4769
- * import { isString } from "effect/Predicate"
4770
- *
4771
- * assert.deepStrictEqual(isString("a"), true)
4772
- *
4773
- * assert.deepStrictEqual(isString(1), false)
4774
- *
4775
- * @category guards
4776
- * @since 2.0.0
4777
- */
4778
- const isString$1 = input => typeof input === "string";
4779
-
4780
- const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
4781
- // Does not check for reserved keywords or unicode characters
4782
- const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
4783
- function getFragmentFromContext(context) {
4784
- // eslint-disable-next-line prefer-destructuring
4785
- const settings = context.settings;
4786
- const fragment = settings.react?.fragment;
4787
- if (isString$1(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
4788
- return fragment;
4789
- }
4790
- return "Fragment";
4791
- }
4792
- const getPragmaFromContext = memo((context)=>{
4793
- // eslint-disable-next-line prefer-destructuring
4794
- const settings = context.settings;
4795
- const sourceCode = context.getSourceCode();
4796
- const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
4797
- return effectFunction_esm.pipe(effectOption_esm.orElse(effectOption_esm.fromNullable(settings.react?.pragma), ()=>effectFunction_esm.pipe(effectOption_esm.fromNullable(pragmaNode), effectOption_esm.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), effectOption_esm.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), effectOption_esm.flatMap(effectOption_esm.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), effectOption_esm.getOrElse(effectFunction_esm.constant("React")));
4798
- });
4799
-
4800
4755
  function isNil(x){
4801
4756
  return x === undefined || x === null
4802
4757
  }
@@ -4815,7 +4770,7 @@ function isNil(x){
4815
4770
  *
4816
4771
  * @category guards
4817
4772
  * @since 2.0.0
4818
- */ const isString = (input)=>typeof input === "string";
4773
+ */ const isString$1 = (input)=>typeof input === "string";
4819
4774
  const t$1 = Symbol.for("@ts-pattern/matcher"), e$1 = Symbol.for("@ts-pattern/isVariadic"), n$1 = "@ts-pattern/anonymous-select-key", r$1 = (t)=>Boolean(t && "object" == typeof t), i$1 = (e)=>e && !!e[t$1], s$1 = (n, o, c)=>{
4820
4775
  if (i$1(n)) {
4821
4776
  const e = n[t$1](), { matched: r, selections: i } = e.match(o);
@@ -6480,7 +6435,7 @@ Function.call.bind(Object.hasOwnProperty);
6480
6435
  return returnStatements;
6481
6436
  }
6482
6437
  function isStringLiteral(node) {
6483
- return node?.type === NodeType.Literal && isString(node.value);
6438
+ return node?.type === NodeType.Literal && isString$1(node.value);
6484
6439
  }
6485
6440
  /**
6486
6441
  * Check if a node is multiline
@@ -6552,6 +6507,62 @@ function isStringLiteral(node) {
6552
6507
  };
6553
6508
  }
6554
6509
 
6510
+ /**
6511
+ * Check if a `JSXElement` or `JSXFragment` has children
6512
+ * @param node The AST node to check
6513
+ * @param predicate A predicate to filter the children
6514
+ * @returns `true` if the node has children
6515
+ */ function hasChildren(node, predicate) {
6516
+ if (typeof predicate === "function") {
6517
+ return node.children.some(predicate);
6518
+ }
6519
+ return node.children.length > 0;
6520
+ }
6521
+ /**
6522
+ * Check if a node is a child of a `JSXElement`
6523
+ * @param node The AST node to check
6524
+ * @returns `true` if the node is a child of a `JSXElement`
6525
+ */ function isChildOfJSXElement(node) {
6526
+ return node.parent?.type === NodeType.JSXElement && node.parent.children.some((child)=>child === node);
6527
+ }
6528
+
6529
+ /**
6530
+ * Tests if a value is a `string`.
6531
+ *
6532
+ * @param input - The value to test.
6533
+ *
6534
+ * @example
6535
+ * import { isString } from "effect/Predicate"
6536
+ *
6537
+ * assert.deepStrictEqual(isString("a"), true)
6538
+ *
6539
+ * assert.deepStrictEqual(isString(1), false)
6540
+ *
6541
+ * @category guards
6542
+ * @since 2.0.0
6543
+ */
6544
+ const isString = input => typeof input === "string";
6545
+
6546
+ const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
6547
+ // Does not check for reserved keywords or unicode characters
6548
+ const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
6549
+ function getFragmentFromContext(context) {
6550
+ // eslint-disable-next-line prefer-destructuring
6551
+ const settings = context.settings;
6552
+ const fragment = settings.react?.fragment;
6553
+ if (isString(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
6554
+ return fragment;
6555
+ }
6556
+ return "Fragment";
6557
+ }
6558
+ const getPragmaFromContext = memo((context)=>{
6559
+ // eslint-disable-next-line prefer-destructuring
6560
+ const settings = context.settings;
6561
+ const sourceCode = context.getSourceCode();
6562
+ const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
6563
+ return effectFunction_esm.pipe(effectOption_esm.orElse(effectOption_esm.fromNullable(settings.react?.pragma), ()=>effectFunction_esm.pipe(effectOption_esm.fromNullable(pragmaNode), effectOption_esm.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), effectOption_esm.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), effectOption_esm.flatMap(effectOption_esm.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), effectOption_esm.getOrElse(effectFunction_esm.constant("React")));
6564
+ });
6565
+
6555
6566
  const t=Symbol.for("@ts-pattern/matcher"),e=Symbol.for("@ts-pattern/isVariadic"),n="@ts-pattern/anonymous-select-key",r=t=>Boolean(t&&"object"==typeof t),i=e=>e&&!!e[t],s=(n,o,c)=>{if(i(n)){const e=n[t](),{matched:r,selections:i}=e.match(o);return r&&i&&Object.keys(i).forEach(t=>c(t,i[t])),r}if(r(n)){if(!r(o))return !1;if(Array.isArray(n)){if(!Array.isArray(o))return !1;let t=[],r=[],a=[];for(const s of n.keys()){const o=n[s];i(o)&&o[e]?a.push(o):a.length?r.push(o):t.push(o);}if(a.length){if(a.length>1)throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");if(o.length<t.length+r.length)return !1;const e=o.slice(0,t.length),n=0===r.length?[]:o.slice(-r.length),i=o.slice(t.length,0===r.length?Infinity:-r.length);return t.every((t,n)=>s(t,e[n],c))&&r.every((t,e)=>s(t,n[e],c))&&(0===a.length||s(a[0],i,c))}return n.length===o.length&&n.every((t,e)=>s(t,o[e],c))}return Object.keys(n).every(e=>{const r=n[e];return (e in o||i(a=r)&&"optional"===a[t]().matcherType)&&s(r,o[e],c);var a;})}return Object.is(o,n)},o=e=>{var n,s,a;return r(e)?i(e)?null!=(n=null==(s=(a=e[t]()).getSelectionKeys)?void 0:s.call(a))?n:[]:Array.isArray(e)?c(e,o):c(Object.values(e),o):[]},c=(t,e)=>t.reduce((t,n)=>t.concat(e(n)),[]);function a(...t){if(1===t.length){const[e]=t;return t=>s(e,t,()=>{})}if(2===t.length){const[e,n]=t;return s(e,n,()=>{})}throw new Error(`isMatching wasn't given the right number of arguments: expected 1 or 2, received ${t.length}.`)}function u(t){return Object.assign(t,{optional:()=>l(t),and:e=>m(t,e),or:e=>y(t,e),select:e=>void 0===e?p(t):p(e,t)})}function h(t){return Object.assign((t=>Object.assign(t,{*[Symbol.iterator](){yield Object.assign(t,{[e]:!0});}}))(t),{optional:()=>h(l(t)),select:e=>h(void 0===e?p(t):p(e,t))})}function l(e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return void 0===t?(o(e).forEach(t=>r(t,void 0)),{matched:!0,selections:n}):{matched:s(e,t,r),selections:n}},getSelectionKeys:()=>o(e),matcherType:"optional"})})}const f=(t,e)=>{for(const n of t)if(!e(n))return !1;return !0},g=(t,e)=>{for(const[n,r]of t.entries())if(!e(r,n))return !1;return !0};function m(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return {matched:e.every(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"and"})})}function y(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return c(e,o).forEach(t=>r(t,void 0)),{matched:e.some(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"or"})})}function d(e){return {[t]:()=>({match:t=>({matched:Boolean(e(t))})})}}function p(...e){const r="string"==typeof e[0]?e[0]:void 0,i=2===e.length?e[1]:"string"==typeof e[0]?void 0:e[0];return u({[t]:()=>({match:t=>{let e={[null!=r?r:n]:t};return {matched:void 0===i||s(i,t,(t,n)=>{e[t]=n;}),selections:e}},getSelectionKeys:()=>[null!=r?r:n].concat(void 0===i?[]:o(i))})})}function v(t){return "number"==typeof t}function b(t){return "string"==typeof t}function w(t){return "bigint"==typeof t}const S=u(d(function(t){return !0})),O=S,j=t=>Object.assign(u(t),{startsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.startsWith(n)))));var n;},endsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.endsWith(n)))));var n;},minLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length>=t))(e))),maxLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length<=t))(e))),includes:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.includes(n)))));var n;},regex:e=>{return j(m(t,(n=e,d(t=>b(t)&&Boolean(t.match(n))))));var n;}}),E=j(d(b)),K=t=>Object.assign(u(t),{between:(e,n)=>K(m(t,((t,e)=>d(n=>v(n)&&t<=n&&e>=n))(e,n))),lt:e=>K(m(t,(t=>d(e=>v(e)&&e<t))(e))),gt:e=>K(m(t,(t=>d(e=>v(e)&&e>t))(e))),lte:e=>K(m(t,(t=>d(e=>v(e)&&e<=t))(e))),gte:e=>K(m(t,(t=>d(e=>v(e)&&e>=t))(e))),int:()=>K(m(t,d(t=>v(t)&&Number.isInteger(t)))),finite:()=>K(m(t,d(t=>v(t)&&Number.isFinite(t)))),positive:()=>K(m(t,d(t=>v(t)&&t>0))),negative:()=>K(m(t,d(t=>v(t)&&t<0)))}),A=K(d(v)),x=t=>Object.assign(u(t),{between:(e,n)=>x(m(t,((t,e)=>d(n=>w(n)&&t<=n&&e>=n))(e,n))),lt:e=>x(m(t,(t=>d(e=>w(e)&&e<t))(e))),gt:e=>x(m(t,(t=>d(e=>w(e)&&e>t))(e))),lte:e=>x(m(t,(t=>d(e=>w(e)&&e<=t))(e))),gte:e=>x(m(t,(t=>d(e=>w(e)&&e>=t))(e))),positive:()=>x(m(t,d(t=>w(t)&&t>0))),negative:()=>x(m(t,d(t=>w(t)&&t<0)))}),P=x(d(w)),T=u(d(function(t){return "boolean"==typeof t})),k=u(d(function(t){return "symbol"==typeof t})),B=u(d(function(t){return null==t}));var _={__proto__:null,matcher:t,optional:l,array:function(...e){return h({[t]:()=>({match:t=>{if(!Array.isArray(t))return {matched:!1};if(0===e.length)return {matched:!0};const n=e[0];let r={};if(0===t.length)return o(n).forEach(t=>{r[t]=[];}),{matched:!0,selections:r};const i=(t,e)=>{r[t]=(r[t]||[]).concat([e]);};return {matched:t.every(t=>s(n,t,i)),selections:r}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},set:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Set))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};if(0===e.length)return {matched:!0};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);},i=e[0];return {matched:f(t,t=>s(i,t,r)),selections:n}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},map:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Map))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);};if(0===e.length)return {matched:!0};var i;if(1===e.length)throw new Error(`\`P.map\` wasn't given enough arguments. Expected (key, value), received ${null==(i=e[0])?void 0:i.toString()}`);const[o,c]=e;return {matched:g(t,(t,e)=>{const n=s(o,e,r),i=s(c,t,r);return n&&i}),selections:n}},getSelectionKeys:()=>0===e.length?[]:[...o(e[0]),...o(e[1])]})})},intersection:m,union:y,not:function(e){return u({[t]:()=>({match:t=>({matched:!s(e,t,()=>{})}),getSelectionKeys:()=>[],matcherType:"not"})})},when:d,select:p,any:S,_:O,string:E,number:A,bigint:P,boolean:T,symbol:k,nullish:B,instanceOf:function(t){return u(d(function(t){return e=>e instanceof t}(t)))},shape:function(t){return u(d(a(t)))}};const W={matched:!1,value:void 0};function N(t){return new $(t,W)}class ${constructor(t,e){this.input=void 0,this.state=void 0,this.input=t,this.state=e;}with(...t){if(this.state.matched)return this;const e=t[t.length-1],r=[t[0]];let i;3===t.length&&"function"==typeof t[1]?(r.push(t[0]),i=t[1]):t.length>2&&r.push(...t.slice(1,t.length-1));let o=!1,c={};const a=(t,e)=>{o=!0,c[t]=e;},u=!r.some(t=>s(t,this.input,a))||i&&!Boolean(i(this.input))?W:{matched:!0,value:e(o?n in c?c[n]:c:this.input,this.input)};return new $(this.input,u)}when(t,e){if(this.state.matched)return this;const n=Boolean(t(this.input));return new $(this.input,n?{matched:!0,value:e(this.input,this.input)}:W)}otherwise(t){return this.state.matched?this.state.value:t(this.input)}exhaustive(){return this.run()}run(){if(this.state.matched)return this.state.value;let t;try{t=JSON.stringify(this.input);}catch(e){t=this.input;}throw new Error(`Pattern matching error: no pattern matches value ${t}`)}returnType(){return this}}
6556
6567
 
6557
6568
  function isPropertyOfPragma(name, context, pragma = getPragmaFromContext(context)) {
@@ -6667,6 +6678,21 @@ function isChildrenOfCreateElement(node, context) {
6667
6678
  return maybeCallExpression.arguments.slice(2).some((child)=>child === node);
6668
6679
  }
6669
6680
 
6681
+ /**
6682
+ * Check if a node is a `JSXElement` of `User-Defined Component` type
6683
+ * @param node The AST node to check
6684
+ * @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
6685
+ */ function isJSXElementOfUserDefinedComponent(node) {
6686
+ return node.type === NodeType.JSXElement && node.openingElement.name.type === NodeType.JSXIdentifier && /^[A-Z]/u.test(node.openingElement.name.name);
6687
+ }
6688
+ /**
6689
+ * Check if a node is a `JSXFragment` of `Built-in Component` type
6690
+ * @param node The AST node to check
6691
+ * @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
6692
+ */ function isJSXElementOfBuiltinComponent(node) {
6693
+ return node.type === NodeType.JSXElement && node.openingElement.name.type === NodeType.JSXIdentifier && node.openingElement.name.name.toLowerCase() === node.openingElement.name.name && /^[a-z]/u.test(node.openingElement.name.name);
6694
+ }
6695
+
6670
6696
  /**
6671
6697
  * Determines whether inside createElement's props.
6672
6698
  * @param node The AST node to check
@@ -6822,6 +6848,89 @@ const hdlWheel = [
6822
6848
  ...hdlWheel
6823
6849
  ];
6824
6850
 
6851
+ /**
6852
+ * Check if a node is a Literal or JSXText
6853
+ * @param node The AST node to check
6854
+ * @returns boolean `true` if the node is a Literal or JSXText
6855
+ */ const isLiteral = isOneOf([
6856
+ NodeType.Literal,
6857
+ NodeType.JSXText
6858
+ ]);
6859
+ /**
6860
+ * Check if a Literal or JSXText node is whitespace
6861
+ * @param node The AST node to check
6862
+ * @returns boolean `true` if the node is whitespace
6863
+ */ function isWhiteSpace(node) {
6864
+ return isString(node.value) && node.value.trim() === "";
6865
+ }
6866
+ /**
6867
+ * Check if a Literal or JSXText node is a line break
6868
+ * @param node The AST node to check
6869
+ * @returns boolean
6870
+ */ function isLineBreak(node) {
6871
+ return isLiteral(node) && isWhiteSpace(node) && isMultiLine(node);
6872
+ }
6873
+ /**
6874
+ * Check if a Literal or JSXText node is padding spaces
6875
+ * @param node The AST node to check
6876
+ * @returns boolean
6877
+ */ function isPaddingSpaces(node) {
6878
+ return isLiteral(node) && isWhiteSpace(node) && node.raw.includes("\n");
6879
+ }
6880
+
6881
+ const isFragment = (node, pragma, fragment)=>{
6882
+ if (!isOneOf([
6883
+ NodeType.JSXElement,
6884
+ NodeType.JSXFragment
6885
+ ])(node)) {
6886
+ return false;
6887
+ }
6888
+ return isFragmentSyntax(node) || isFragmentElement(node, pragma, fragment);
6889
+ };
6890
+ /**
6891
+ * Check if a node is `<></>`
6892
+ */ const isFragmentSyntax = is(NodeType.JSXFragment);
6893
+ /**
6894
+ * Check if a node is `<Fragment></Fragment>` or `<Pragma.Fragment></Pragma.Fragment>`
6895
+ * @param node
6896
+ * @param pragma
6897
+ * @param fragment
6898
+ */ function isFragmentElement(node, pragma, fragment) {
6899
+ const { name } = node.openingElement;
6900
+ // <Fragment>
6901
+ if (name.type === NodeType.JSXIdentifier && name.name === fragment) {
6902
+ return true;
6903
+ }
6904
+ // <Pragma.Fragment>
6905
+ return name.type === NodeType.JSXMemberExpression && name.object.type === NodeType.JSXIdentifier && name.object.name === pragma && name.property.name === fragment;
6906
+ }
6907
+ /**
6908
+ * Check if a JSXElement or JSXFragment has only one literal child and is not a child
6909
+ * @param node The AST node to check
6910
+ * @returns `true` if the node has only one literal child and is not a child
6911
+ * @example Somehow fragment like this is useful: <Foo content={<>ee eeee eeee ...</>} />
6912
+ */ function isFragmentWithOnlyTextAndIsNotChild(node) {
6913
+ return node.children.length === 1 && isLiteral(node.children[0]) && !(node.parent.type === NodeType.JSXElement || node.parent.type === NodeType.JSXFragment);
6914
+ }
6915
+ function containsCallExpression(node) {
6916
+ return node.type === NodeType.JSXExpressionContainer && node.expression.type === NodeType.CallExpression;
6917
+ }
6918
+ /**
6919
+ * Check if a JSXElement or JSXFragment has less than two non-padding children and the first child is not a call expression
6920
+ * @param node The AST node to check
6921
+ * @returns boolean
6922
+ */ function isFragmentHasLessThanTwoChildren(node) {
6923
+ const nonPaddingChildren = node.children.filter((child)=>!isPaddingSpaces(child));
6924
+ if (nonPaddingChildren.length === 1) {
6925
+ return !containsCallExpression(nonPaddingChildren[0]);
6926
+ }
6927
+ return nonPaddingChildren.length === 0;
6928
+ }
6929
+ function isFragmentWithSingleExpression(node) {
6930
+ const children = node.children.filter((child)=>!isPaddingSpaces(child));
6931
+ return children.length === 1 && children[0]?.type === NodeType.JSXExpressionContainer;
6932
+ }
6933
+
6825
6934
  const defaultJSXValueCheckOptions = {
6826
6935
  ignoreNull: false,
6827
6936
  strict: false
@@ -6871,7 +6980,7 @@ const defaultJSXValueCheckOptions = {
6871
6980
  if (isJSXTagNameExpression(node)) {
6872
6981
  return true;
6873
6982
  }
6874
- if (!isString$1(node.name) && node.name.type !== NodeType.Identifier) {
6983
+ if (!isString(node.name) && node.name.type !== NodeType.Identifier) {
6875
6984
  return isJSXTagNameExpression(node.name);
6876
6985
  }
6877
6986
  const name = N(node.name).with(_.string, effectFunction_esm.identity).with({
@@ -7053,29 +7162,6 @@ const defaultJSXValueCheckOptions = {
7053
7162
  return effectOption_esm.some(getStaticValue(argument, scope));
7054
7163
  }
7055
7164
 
7056
- /**
7057
- * Check if a node is a Literal or JSXText
7058
- * @param node The AST node to check
7059
- * @returns boolean `true` if the node is a Literal or JSXText
7060
- */ const isLiteral = isOneOf([
7061
- NodeType.Literal,
7062
- NodeType.JSXText
7063
- ]);
7064
- /**
7065
- * Check if a Literal or JSXText node is whitespace
7066
- * @param node The AST node to check
7067
- * @returns boolean `true` if the node is whitespace
7068
- */ function isWhiteSpace(node) {
7069
- return isString$1(node.value) && node.value.trim() === "";
7070
- }
7071
- /**
7072
- * Check if a Literal or JSXText node is a line break
7073
- * @param node The AST node to check
7074
- * @returns boolean
7075
- */ function isLineBreak(node) {
7076
- return isLiteral(node) && isWhiteSpace(node) && isMultiLine(node);
7077
- }
7078
-
7079
7165
  exports.defaultJSXValueCheckOptions = defaultJSXValueCheckOptions;
7080
7166
  exports.elementType = elementType;
7081
7167
  exports.findPropInAttributes = findPropInAttributes;
@@ -7104,16 +7190,26 @@ exports.hdlTouch = hdlTouch;
7104
7190
  exports.hdlTransition = hdlTransition;
7105
7191
  exports.hdlWheel = hdlWheel;
7106
7192
  exports.isCallFromPragma = isCallFromPragma;
7193
+ exports.isChildOfJSXElement = isChildOfJSXElement;
7107
7194
  exports.isChildrenOfCreateElement = isChildrenOfCreateElement;
7108
7195
  exports.isCloneElementCall = isCloneElementCall;
7109
7196
  exports.isCreateElementCall = isCreateElementCall;
7197
+ exports.isFragment = isFragment;
7198
+ exports.isFragmentElement = isFragmentElement;
7199
+ exports.isFragmentHasLessThanTwoChildren = isFragmentHasLessThanTwoChildren;
7200
+ exports.isFragmentSyntax = isFragmentSyntax;
7201
+ exports.isFragmentWithOnlyTextAndIsNotChild = isFragmentWithOnlyTextAndIsNotChild;
7202
+ exports.isFragmentWithSingleExpression = isFragmentWithSingleExpression;
7110
7203
  exports.isFunctionReturningJSXValue = isFunctionReturningJSXValue;
7111
7204
  exports.isInitializedFromPragma = isInitializedFromPragma;
7112
7205
  exports.isInsideCreateElementProps = isInsideCreateElementProps;
7113
7206
  exports.isInsidePropValue = isInsidePropValue;
7207
+ exports.isJSXElementOfBuiltinComponent = isJSXElementOfBuiltinComponent;
7208
+ exports.isJSXElementOfUserDefinedComponent = isJSXElementOfUserDefinedComponent;
7114
7209
  exports.isJSXValue = isJSXValue;
7115
7210
  exports.isLineBreak = isLineBreak;
7116
7211
  exports.isLiteral = isLiteral;
7212
+ exports.isPaddingSpaces = isPaddingSpaces;
7117
7213
  exports.isPropertyOfPragma = isPropertyOfPragma;
7118
7214
  exports.isWhiteSpace = isWhiteSpace;
7119
7215
  exports.traverseUpProp = traverseUpProp;
package/dist/index.mjs CHANGED
@@ -1,15 +1,7 @@
1
- import memo from 'micro-memoize';
2
1
  import '@typescript-eslint/scope-manager';
3
2
  import { AST_NODE_TYPES } from '@typescript-eslint/types';
4
3
  import { ASTUtils } from '@typescript-eslint/utils';
5
-
6
- /**
7
- * Check if a JSXElement or JSXFragment has children
8
- * @param node The AST node to check
9
- * @returns `true` if the node has children
10
- */ function hasChildren(node) {
11
- return node.children.length > 0;
12
- }
4
+ import memo from 'micro-memoize';
13
5
 
14
6
  /**
15
7
  * @since 2.0.0
@@ -4758,43 +4750,6 @@ var effectData_esm = /*#__PURE__*/ Object.freeze({
4758
4750
  unsafeStruct: unsafeStruct
4759
4751
  });
4760
4752
 
4761
- /**
4762
- * Tests if a value is a `string`.
4763
- *
4764
- * @param input - The value to test.
4765
- *
4766
- * @example
4767
- * import { isString } from "effect/Predicate"
4768
- *
4769
- * assert.deepStrictEqual(isString("a"), true)
4770
- *
4771
- * assert.deepStrictEqual(isString(1), false)
4772
- *
4773
- * @category guards
4774
- * @since 2.0.0
4775
- */
4776
- const isString$1 = input => typeof input === "string";
4777
-
4778
- const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
4779
- // Does not check for reserved keywords or unicode characters
4780
- const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
4781
- function getFragmentFromContext(context) {
4782
- // eslint-disable-next-line prefer-destructuring
4783
- const settings = context.settings;
4784
- const fragment = settings.react?.fragment;
4785
- if (isString$1(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
4786
- return fragment;
4787
- }
4788
- return "Fragment";
4789
- }
4790
- const getPragmaFromContext = memo((context)=>{
4791
- // eslint-disable-next-line prefer-destructuring
4792
- const settings = context.settings;
4793
- const sourceCode = context.getSourceCode();
4794
- const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
4795
- return effectFunction_esm.pipe(effectOption_esm.orElse(effectOption_esm.fromNullable(settings.react?.pragma), ()=>effectFunction_esm.pipe(effectOption_esm.fromNullable(pragmaNode), effectOption_esm.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), effectOption_esm.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), effectOption_esm.flatMap(effectOption_esm.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), effectOption_esm.getOrElse(effectFunction_esm.constant("React")));
4796
- });
4797
-
4798
4753
  function isNil(x){
4799
4754
  return x === undefined || x === null
4800
4755
  }
@@ -4813,7 +4768,7 @@ function isNil(x){
4813
4768
  *
4814
4769
  * @category guards
4815
4770
  * @since 2.0.0
4816
- */ const isString = (input)=>typeof input === "string";
4771
+ */ const isString$1 = (input)=>typeof input === "string";
4817
4772
  const t$1 = Symbol.for("@ts-pattern/matcher"), e$1 = Symbol.for("@ts-pattern/isVariadic"), n$1 = "@ts-pattern/anonymous-select-key", r$1 = (t)=>Boolean(t && "object" == typeof t), i$1 = (e)=>e && !!e[t$1], s$1 = (n, o, c)=>{
4818
4773
  if (i$1(n)) {
4819
4774
  const e = n[t$1](), { matched: r, selections: i } = e.match(o);
@@ -6478,7 +6433,7 @@ Function.call.bind(Object.hasOwnProperty);
6478
6433
  return returnStatements;
6479
6434
  }
6480
6435
  function isStringLiteral(node) {
6481
- return node?.type === NodeType.Literal && isString(node.value);
6436
+ return node?.type === NodeType.Literal && isString$1(node.value);
6482
6437
  }
6483
6438
  /**
6484
6439
  * Check if a node is multiline
@@ -6550,6 +6505,62 @@ function isStringLiteral(node) {
6550
6505
  };
6551
6506
  }
6552
6507
 
6508
+ /**
6509
+ * Check if a `JSXElement` or `JSXFragment` has children
6510
+ * @param node The AST node to check
6511
+ * @param predicate A predicate to filter the children
6512
+ * @returns `true` if the node has children
6513
+ */ function hasChildren(node, predicate) {
6514
+ if (typeof predicate === "function") {
6515
+ return node.children.some(predicate);
6516
+ }
6517
+ return node.children.length > 0;
6518
+ }
6519
+ /**
6520
+ * Check if a node is a child of a `JSXElement`
6521
+ * @param node The AST node to check
6522
+ * @returns `true` if the node is a child of a `JSXElement`
6523
+ */ function isChildOfJSXElement(node) {
6524
+ return node.parent?.type === NodeType.JSXElement && node.parent.children.some((child)=>child === node);
6525
+ }
6526
+
6527
+ /**
6528
+ * Tests if a value is a `string`.
6529
+ *
6530
+ * @param input - The value to test.
6531
+ *
6532
+ * @example
6533
+ * import { isString } from "effect/Predicate"
6534
+ *
6535
+ * assert.deepStrictEqual(isString("a"), true)
6536
+ *
6537
+ * assert.deepStrictEqual(isString(1), false)
6538
+ *
6539
+ * @category guards
6540
+ * @since 2.0.0
6541
+ */
6542
+ const isString = input => typeof input === "string";
6543
+
6544
+ const RE_JSX_ANNOTATION_REGEX = /@jsx\s+(\S+)/u;
6545
+ // Does not check for reserved keywords or unicode characters
6546
+ const RE_JS_IDENTIFIER_REGEX = /^[$A-Z_a-z][\w$]*$/u;
6547
+ function getFragmentFromContext(context) {
6548
+ // eslint-disable-next-line prefer-destructuring
6549
+ const settings = context.settings;
6550
+ const fragment = settings.react?.fragment;
6551
+ if (isString(fragment) && RE_JS_IDENTIFIER_REGEX.test(fragment)) {
6552
+ return fragment;
6553
+ }
6554
+ return "Fragment";
6555
+ }
6556
+ const getPragmaFromContext = memo((context)=>{
6557
+ // eslint-disable-next-line prefer-destructuring
6558
+ const settings = context.settings;
6559
+ const sourceCode = context.getSourceCode();
6560
+ const pragmaNode = sourceCode.getAllComments().find((node)=>RE_JSX_ANNOTATION_REGEX.test(node.value));
6561
+ return effectFunction_esm.pipe(effectOption_esm.orElse(effectOption_esm.fromNullable(settings.react?.pragma), ()=>effectFunction_esm.pipe(effectOption_esm.fromNullable(pragmaNode), effectOption_esm.map(({ value })=>RE_JSX_ANNOTATION_REGEX.exec(value)), effectOption_esm.flatMapNullable((matches)=>matches?.[1]?.split(".")[0]))), effectOption_esm.flatMap(effectOption_esm.liftPredicate((x)=>RE_JS_IDENTIFIER_REGEX.test(x))), effectOption_esm.getOrElse(effectFunction_esm.constant("React")));
6562
+ });
6563
+
6553
6564
  const t=Symbol.for("@ts-pattern/matcher"),e=Symbol.for("@ts-pattern/isVariadic"),n="@ts-pattern/anonymous-select-key",r=t=>Boolean(t&&"object"==typeof t),i=e=>e&&!!e[t],s=(n,o,c)=>{if(i(n)){const e=n[t](),{matched:r,selections:i}=e.match(o);return r&&i&&Object.keys(i).forEach(t=>c(t,i[t])),r}if(r(n)){if(!r(o))return !1;if(Array.isArray(n)){if(!Array.isArray(o))return !1;let t=[],r=[],a=[];for(const s of n.keys()){const o=n[s];i(o)&&o[e]?a.push(o):a.length?r.push(o):t.push(o);}if(a.length){if(a.length>1)throw new Error("Pattern error: Using `...P.array(...)` several times in a single pattern is not allowed.");if(o.length<t.length+r.length)return !1;const e=o.slice(0,t.length),n=0===r.length?[]:o.slice(-r.length),i=o.slice(t.length,0===r.length?Infinity:-r.length);return t.every((t,n)=>s(t,e[n],c))&&r.every((t,e)=>s(t,n[e],c))&&(0===a.length||s(a[0],i,c))}return n.length===o.length&&n.every((t,e)=>s(t,o[e],c))}return Object.keys(n).every(e=>{const r=n[e];return (e in o||i(a=r)&&"optional"===a[t]().matcherType)&&s(r,o[e],c);var a;})}return Object.is(o,n)},o=e=>{var n,s,a;return r(e)?i(e)?null!=(n=null==(s=(a=e[t]()).getSelectionKeys)?void 0:s.call(a))?n:[]:Array.isArray(e)?c(e,o):c(Object.values(e),o):[]},c=(t,e)=>t.reduce((t,n)=>t.concat(e(n)),[]);function a(...t){if(1===t.length){const[e]=t;return t=>s(e,t,()=>{})}if(2===t.length){const[e,n]=t;return s(e,n,()=>{})}throw new Error(`isMatching wasn't given the right number of arguments: expected 1 or 2, received ${t.length}.`)}function u(t){return Object.assign(t,{optional:()=>l(t),and:e=>m(t,e),or:e=>y(t,e),select:e=>void 0===e?p(t):p(e,t)})}function h(t){return Object.assign((t=>Object.assign(t,{*[Symbol.iterator](){yield Object.assign(t,{[e]:!0});}}))(t),{optional:()=>h(l(t)),select:e=>h(void 0===e?p(t):p(e,t))})}function l(e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return void 0===t?(o(e).forEach(t=>r(t,void 0)),{matched:!0,selections:n}):{matched:s(e,t,r),selections:n}},getSelectionKeys:()=>o(e),matcherType:"optional"})})}const f=(t,e)=>{for(const n of t)if(!e(n))return !1;return !0},g=(t,e)=>{for(const[n,r]of t.entries())if(!e(r,n))return !1;return !0};function m(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return {matched:e.every(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"and"})})}function y(...e){return u({[t]:()=>({match:t=>{let n={};const r=(t,e)=>{n[t]=e;};return c(e,o).forEach(t=>r(t,void 0)),{matched:e.some(e=>s(e,t,r)),selections:n}},getSelectionKeys:()=>c(e,o),matcherType:"or"})})}function d(e){return {[t]:()=>({match:t=>({matched:Boolean(e(t))})})}}function p(...e){const r="string"==typeof e[0]?e[0]:void 0,i=2===e.length?e[1]:"string"==typeof e[0]?void 0:e[0];return u({[t]:()=>({match:t=>{let e={[null!=r?r:n]:t};return {matched:void 0===i||s(i,t,(t,n)=>{e[t]=n;}),selections:e}},getSelectionKeys:()=>[null!=r?r:n].concat(void 0===i?[]:o(i))})})}function v(t){return "number"==typeof t}function b(t){return "string"==typeof t}function w(t){return "bigint"==typeof t}const S=u(d(function(t){return !0})),O=S,j=t=>Object.assign(u(t),{startsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.startsWith(n)))));var n;},endsWith:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.endsWith(n)))));var n;},minLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length>=t))(e))),maxLength:e=>j(m(t,(t=>d(e=>b(e)&&e.length<=t))(e))),includes:e=>{return j(m(t,(n=e,d(t=>b(t)&&t.includes(n)))));var n;},regex:e=>{return j(m(t,(n=e,d(t=>b(t)&&Boolean(t.match(n))))));var n;}}),E=j(d(b)),K=t=>Object.assign(u(t),{between:(e,n)=>K(m(t,((t,e)=>d(n=>v(n)&&t<=n&&e>=n))(e,n))),lt:e=>K(m(t,(t=>d(e=>v(e)&&e<t))(e))),gt:e=>K(m(t,(t=>d(e=>v(e)&&e>t))(e))),lte:e=>K(m(t,(t=>d(e=>v(e)&&e<=t))(e))),gte:e=>K(m(t,(t=>d(e=>v(e)&&e>=t))(e))),int:()=>K(m(t,d(t=>v(t)&&Number.isInteger(t)))),finite:()=>K(m(t,d(t=>v(t)&&Number.isFinite(t)))),positive:()=>K(m(t,d(t=>v(t)&&t>0))),negative:()=>K(m(t,d(t=>v(t)&&t<0)))}),A=K(d(v)),x=t=>Object.assign(u(t),{between:(e,n)=>x(m(t,((t,e)=>d(n=>w(n)&&t<=n&&e>=n))(e,n))),lt:e=>x(m(t,(t=>d(e=>w(e)&&e<t))(e))),gt:e=>x(m(t,(t=>d(e=>w(e)&&e>t))(e))),lte:e=>x(m(t,(t=>d(e=>w(e)&&e<=t))(e))),gte:e=>x(m(t,(t=>d(e=>w(e)&&e>=t))(e))),positive:()=>x(m(t,d(t=>w(t)&&t>0))),negative:()=>x(m(t,d(t=>w(t)&&t<0)))}),P=x(d(w)),T=u(d(function(t){return "boolean"==typeof t})),k=u(d(function(t){return "symbol"==typeof t})),B=u(d(function(t){return null==t}));var _={__proto__:null,matcher:t,optional:l,array:function(...e){return h({[t]:()=>({match:t=>{if(!Array.isArray(t))return {matched:!1};if(0===e.length)return {matched:!0};const n=e[0];let r={};if(0===t.length)return o(n).forEach(t=>{r[t]=[];}),{matched:!0,selections:r};const i=(t,e)=>{r[t]=(r[t]||[]).concat([e]);};return {matched:t.every(t=>s(n,t,i)),selections:r}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},set:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Set))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};if(0===e.length)return {matched:!0};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);},i=e[0];return {matched:f(t,t=>s(i,t,r)),selections:n}},getSelectionKeys:()=>0===e.length?[]:o(e[0])})})},map:function(...e){return u({[t]:()=>({match:t=>{if(!(t instanceof Map))return {matched:!1};let n={};if(0===t.size)return {matched:!0,selections:n};const r=(t,e)=>{n[t]=(n[t]||[]).concat([e]);};if(0===e.length)return {matched:!0};var i;if(1===e.length)throw new Error(`\`P.map\` wasn't given enough arguments. Expected (key, value), received ${null==(i=e[0])?void 0:i.toString()}`);const[o,c]=e;return {matched:g(t,(t,e)=>{const n=s(o,e,r),i=s(c,t,r);return n&&i}),selections:n}},getSelectionKeys:()=>0===e.length?[]:[...o(e[0]),...o(e[1])]})})},intersection:m,union:y,not:function(e){return u({[t]:()=>({match:t=>({matched:!s(e,t,()=>{})}),getSelectionKeys:()=>[],matcherType:"not"})})},when:d,select:p,any:S,_:O,string:E,number:A,bigint:P,boolean:T,symbol:k,nullish:B,instanceOf:function(t){return u(d(function(t){return e=>e instanceof t}(t)))},shape:function(t){return u(d(a(t)))}};const W={matched:!1,value:void 0};function N(t){return new $(t,W)}class ${constructor(t,e){this.input=void 0,this.state=void 0,this.input=t,this.state=e;}with(...t){if(this.state.matched)return this;const e=t[t.length-1],r=[t[0]];let i;3===t.length&&"function"==typeof t[1]?(r.push(t[0]),i=t[1]):t.length>2&&r.push(...t.slice(1,t.length-1));let o=!1,c={};const a=(t,e)=>{o=!0,c[t]=e;},u=!r.some(t=>s(t,this.input,a))||i&&!Boolean(i(this.input))?W:{matched:!0,value:e(o?n in c?c[n]:c:this.input,this.input)};return new $(this.input,u)}when(t,e){if(this.state.matched)return this;const n=Boolean(t(this.input));return new $(this.input,n?{matched:!0,value:e(this.input,this.input)}:W)}otherwise(t){return this.state.matched?this.state.value:t(this.input)}exhaustive(){return this.run()}run(){if(this.state.matched)return this.state.value;let t;try{t=JSON.stringify(this.input);}catch(e){t=this.input;}throw new Error(`Pattern matching error: no pattern matches value ${t}`)}returnType(){return this}}
6554
6565
 
6555
6566
  function isPropertyOfPragma(name, context, pragma = getPragmaFromContext(context)) {
@@ -6665,6 +6676,21 @@ function isChildrenOfCreateElement(node, context) {
6665
6676
  return maybeCallExpression.arguments.slice(2).some((child)=>child === node);
6666
6677
  }
6667
6678
 
6679
+ /**
6680
+ * Check if a node is a `JSXElement` of `User-Defined Component` type
6681
+ * @param node The AST node to check
6682
+ * @returns `true` if the node is a `JSXElement` of `User-Defined Component` type
6683
+ */ function isJSXElementOfUserDefinedComponent(node) {
6684
+ return node.type === NodeType.JSXElement && node.openingElement.name.type === NodeType.JSXIdentifier && /^[A-Z]/u.test(node.openingElement.name.name);
6685
+ }
6686
+ /**
6687
+ * Check if a node is a `JSXFragment` of `Built-in Component` type
6688
+ * @param node The AST node to check
6689
+ * @returns `true` if the node is a `JSXFragment` of `Built-in Component` type
6690
+ */ function isJSXElementOfBuiltinComponent(node) {
6691
+ return node.type === NodeType.JSXElement && node.openingElement.name.type === NodeType.JSXIdentifier && node.openingElement.name.name.toLowerCase() === node.openingElement.name.name && /^[a-z]/u.test(node.openingElement.name.name);
6692
+ }
6693
+
6668
6694
  /**
6669
6695
  * Determines whether inside createElement's props.
6670
6696
  * @param node The AST node to check
@@ -6820,6 +6846,89 @@ const hdlWheel = [
6820
6846
  ...hdlWheel
6821
6847
  ];
6822
6848
 
6849
+ /**
6850
+ * Check if a node is a Literal or JSXText
6851
+ * @param node The AST node to check
6852
+ * @returns boolean `true` if the node is a Literal or JSXText
6853
+ */ const isLiteral = isOneOf([
6854
+ NodeType.Literal,
6855
+ NodeType.JSXText
6856
+ ]);
6857
+ /**
6858
+ * Check if a Literal or JSXText node is whitespace
6859
+ * @param node The AST node to check
6860
+ * @returns boolean `true` if the node is whitespace
6861
+ */ function isWhiteSpace(node) {
6862
+ return isString(node.value) && node.value.trim() === "";
6863
+ }
6864
+ /**
6865
+ * Check if a Literal or JSXText node is a line break
6866
+ * @param node The AST node to check
6867
+ * @returns boolean
6868
+ */ function isLineBreak(node) {
6869
+ return isLiteral(node) && isWhiteSpace(node) && isMultiLine(node);
6870
+ }
6871
+ /**
6872
+ * Check if a Literal or JSXText node is padding spaces
6873
+ * @param node The AST node to check
6874
+ * @returns boolean
6875
+ */ function isPaddingSpaces(node) {
6876
+ return isLiteral(node) && isWhiteSpace(node) && node.raw.includes("\n");
6877
+ }
6878
+
6879
+ const isFragment = (node, pragma, fragment)=>{
6880
+ if (!isOneOf([
6881
+ NodeType.JSXElement,
6882
+ NodeType.JSXFragment
6883
+ ])(node)) {
6884
+ return false;
6885
+ }
6886
+ return isFragmentSyntax(node) || isFragmentElement(node, pragma, fragment);
6887
+ };
6888
+ /**
6889
+ * Check if a node is `<></>`
6890
+ */ const isFragmentSyntax = is(NodeType.JSXFragment);
6891
+ /**
6892
+ * Check if a node is `<Fragment></Fragment>` or `<Pragma.Fragment></Pragma.Fragment>`
6893
+ * @param node
6894
+ * @param pragma
6895
+ * @param fragment
6896
+ */ function isFragmentElement(node, pragma, fragment) {
6897
+ const { name } = node.openingElement;
6898
+ // <Fragment>
6899
+ if (name.type === NodeType.JSXIdentifier && name.name === fragment) {
6900
+ return true;
6901
+ }
6902
+ // <Pragma.Fragment>
6903
+ return name.type === NodeType.JSXMemberExpression && name.object.type === NodeType.JSXIdentifier && name.object.name === pragma && name.property.name === fragment;
6904
+ }
6905
+ /**
6906
+ * Check if a JSXElement or JSXFragment has only one literal child and is not a child
6907
+ * @param node The AST node to check
6908
+ * @returns `true` if the node has only one literal child and is not a child
6909
+ * @example Somehow fragment like this is useful: <Foo content={<>ee eeee eeee ...</>} />
6910
+ */ function isFragmentWithOnlyTextAndIsNotChild(node) {
6911
+ return node.children.length === 1 && isLiteral(node.children[0]) && !(node.parent.type === NodeType.JSXElement || node.parent.type === NodeType.JSXFragment);
6912
+ }
6913
+ function containsCallExpression(node) {
6914
+ return node.type === NodeType.JSXExpressionContainer && node.expression.type === NodeType.CallExpression;
6915
+ }
6916
+ /**
6917
+ * Check if a JSXElement or JSXFragment has less than two non-padding children and the first child is not a call expression
6918
+ * @param node The AST node to check
6919
+ * @returns boolean
6920
+ */ function isFragmentHasLessThanTwoChildren(node) {
6921
+ const nonPaddingChildren = node.children.filter((child)=>!isPaddingSpaces(child));
6922
+ if (nonPaddingChildren.length === 1) {
6923
+ return !containsCallExpression(nonPaddingChildren[0]);
6924
+ }
6925
+ return nonPaddingChildren.length === 0;
6926
+ }
6927
+ function isFragmentWithSingleExpression(node) {
6928
+ const children = node.children.filter((child)=>!isPaddingSpaces(child));
6929
+ return children.length === 1 && children[0]?.type === NodeType.JSXExpressionContainer;
6930
+ }
6931
+
6823
6932
  const defaultJSXValueCheckOptions = {
6824
6933
  ignoreNull: false,
6825
6934
  strict: false
@@ -6869,7 +6978,7 @@ const defaultJSXValueCheckOptions = {
6869
6978
  if (isJSXTagNameExpression(node)) {
6870
6979
  return true;
6871
6980
  }
6872
- if (!isString$1(node.name) && node.name.type !== NodeType.Identifier) {
6981
+ if (!isString(node.name) && node.name.type !== NodeType.Identifier) {
6873
6982
  return isJSXTagNameExpression(node.name);
6874
6983
  }
6875
6984
  const name = N(node.name).with(_.string, effectFunction_esm.identity).with({
@@ -7051,27 +7160,4 @@ const defaultJSXValueCheckOptions = {
7051
7160
  return effectOption_esm.some(getStaticValue(argument, scope));
7052
7161
  }
7053
7162
 
7054
- /**
7055
- * Check if a node is a Literal or JSXText
7056
- * @param node The AST node to check
7057
- * @returns boolean `true` if the node is a Literal or JSXText
7058
- */ const isLiteral = isOneOf([
7059
- NodeType.Literal,
7060
- NodeType.JSXText
7061
- ]);
7062
- /**
7063
- * Check if a Literal or JSXText node is whitespace
7064
- * @param node The AST node to check
7065
- * @returns boolean `true` if the node is whitespace
7066
- */ function isWhiteSpace(node) {
7067
- return isString$1(node.value) && node.value.trim() === "";
7068
- }
7069
- /**
7070
- * Check if a Literal or JSXText node is a line break
7071
- * @param node The AST node to check
7072
- * @returns boolean
7073
- */ function isLineBreak(node) {
7074
- return isLiteral(node) && isWhiteSpace(node) && isMultiLine(node);
7075
- }
7076
-
7077
- export { defaultJSXValueCheckOptions, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getPropName, getPropNameWithNamespace, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXValue, isLineBreak, isLiteral, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
7163
+ export { defaultJSXValueCheckOptions, elementType, findPropInAttributes, findPropInProperties, getFragmentFromContext, getPragmaFromContext, getPropName, getPropNameWithNamespace, getPropValue, hasAnyProp, hasChildren, hasEveryProp, hasProp, hdlAnimation, hdlClipboard, hdlComposition, hdlFocus, hdlForm, hdlImage, hdlKeyboard, hdlMedia, hdlMouse, hdlScroll, hdlSelection, hdlTouch, hdlTransition, hdlWheel, isCallFromPragma, isChildOfJSXElement, isChildrenOfCreateElement, isCloneElementCall, isCreateElementCall, isFragment, isFragmentElement, isFragmentHasLessThanTwoChildren, isFragmentSyntax, isFragmentWithOnlyTextAndIsNotChild, isFragmentWithSingleExpression, isFunctionReturningJSXValue, isInitializedFromPragma, isInsideCreateElementProps, isInsidePropValue, isJSXElementOfBuiltinComponent, isJSXElementOfUserDefinedComponent, isJSXValue, isLineBreak, isLiteral, isPaddingSpaces, isPropertyOfPragma, isWhiteSpace, traverseUpProp };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/jsx",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "AST Utility Module for Static Analysis of JSX",
5
5
  "homepage": "https://github.com/Rel1cx/eslint-react",
6
6
  "bugs": {
@@ -40,10 +40,10 @@
40
40
  "micro-memoize": "4.1.2"
41
41
  },
42
42
  "devDependencies": {
43
- "@eslint-react/ast": "0.5.8",
44
- "@eslint-react/types": "0.5.8",
45
- "@eslint-react/tools": "0.5.8",
46
- "@eslint-react/shared": "0.5.8"
43
+ "@eslint-react/shared": "0.5.9",
44
+ "@eslint-react/types": "0.5.9",
45
+ "@eslint-react/ast": "0.5.9",
46
+ "@eslint-react/tools": "0.5.9"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "rollup -c rollup.config.ts --configPlugin swc3 && cp dist/index.d.ts dist/index.d.mts",