eslint-plugin-code-style 2.0.13 → 2.0.15

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 +14 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -52,9 +52,9 @@ ${n} }`)},message:"Destructured properties in array callback should each be o
52
52
  `+b),message:"First props type property must be on a new line when there are multiple properties",node:k})}if(c.length>1&&S){let k=c[c.length-1];S.loc.start.line===k.loc.end.line&&e.report({fix:$=>$.replaceTextRange([k.range[1],S.range[0]],`
53
53
  `+u),message:"Closing brace must be on its own line when there are multiple properties",node:S})}if(c.length===1&&x&&S){let k=c[0];if(x.loc.end.line!==S.loc.start.line){let $=t.getText(k);$=$.replace(/[,;]\s*$/,""),e.report({fix:v=>v.replaceTextRange([x.range[0],S.range[1]],`{ ${$} }`),message:"Single props type property should be on a single line",node:o})}}if(c.forEach((k,$)=>{let v=t.getText(k);if(k.type==="TSPropertySignature"&&k.optional){let p=t.getFirstToken(k),d=t.getTokenAfter(p);d&&d.value==="?"&&t.getText().slice(p.range[1],d.range[0])!==""&&e.report({fix:L=>L.replaceTextRange([p.range[1],d.range[0]],""),message:'No space allowed before "?" in optional property',node:k})}if(v.trimEnd().endsWith(";")&&e.report({fix:p=>{let d=v.lastIndexOf(";"),w=k.range[0]+d;return p.replaceTextRange([w,w+1],",")},message:"Props type properties must end with comma (,) not semicolon (;)",node:k}),c.length>1&&$>0){let p=c[$-1];k.loc.start.line===p.loc.end.line&&e.report({fix:d=>{let w=t.getTokenAfter(p);for(;w&&w.value!==","&&w.range[0]<k.range[0];)w=t.getTokenAfter(w);let L=w&&w.value===","?w.range[1]:p.range[1];return d.replaceTextRange([L,k.range[0]],`
54
54
  `+b)},message:"Each props type property must be on its own line when there are multiple properties",node:k}),k.loc.start.line-p.loc.end.line>1&&e.report({fix:d=>{let L=t.getText().slice(p.range[1],k.range[0]).replace(/\n\s*\n/g,`
55
- `);return d.replaceTextRange([p.range[1],k.range[0]],L)},message:"No empty lines allowed between props type properties",node:k})}}),c.length>1){let k=c[c.length-1];t.getText(k).trimEnd().endsWith(",")||e.report({fix:v=>v.insertTextAfter(k,","),message:"Last props type property must have trailing comma",node:k})}if(c.length===1){let k=c[0],$=t.getText(k);$.trimEnd().endsWith(",")&&e.report({fix:v=>{let p=$.lastIndexOf(","),d=k.range[0]+p;return v.removeRange([d,d+1])},message:"Single props type property should not have trailing comma",node:k})}}},s=g=>{if(!g.returnType||!g.returnType.typeAnnotation)return;let i=g.returnType,r=i.typeAnnotation;if(!C(g)&&r.type==="TSTypeLiteral"){e.report({message:"Function return type must be a type reference (interface, type, or built-in type), not an inline object type. Define the return type separately.",node:r});return}let o;if(g.params.length>0){let a=g.params[g.params.length-1];o=t.getTokenAfter(a,u=>u.value===")")}else{let u=t.getFirstToken(g);for(;u&&u.value!=="(";)u=t.getTokenAfter(u);u&&(o=t.getTokenAfter(u,b=>b.value===")"))}if(!o)return;let n=t.getFirstToken(i);if(!n||n.value!==":")return;let h=t.getFirstToken(r);if(!h)return;let f=t.getText().slice(o.range[1],n.range[0]),c=t.getText().slice(n.range[1],h.range[0]);(f!==""||c!==" ")&&e.report({fix:a=>a.replaceTextRange([o.range[1],h.range[0]],": "),message:'Return type annotation must have no space before colon and one space after: "): TypeName"',node:i})};return{ArrowFunctionExpression(g){y(g),s(g)},FunctionDeclaration(g){y(g),s(g)},FunctionExpression(g){y(g),s(g)}}},meta:{docs:{description:"Enforce inline type annotation for React component props and return types with proper formatting"},fixable:"code",schema:[],type:"suggestion"}},Je={create(e){let t=g=>g.parent&&g.parent.type==="VariableDeclarator"&&g.parent.id&&g.parent.id.type==="Identifier"?g.parent.id.name:g.id&&g.id.type==="Identifier"?g.id.name:null,I=g=>g&&/^[A-Z]/.test(g),C=g=>g&&g.endsWith("Icon"),y=g=>{let i=g.body;if(!i)return!1;if(i.type==="JSXElement")return i.openingElement&&i.openingElement.name&&i.openingElement.name.name==="svg";if(i.type==="ParenthesizedExpression"&&i.expression&&i.expression.type==="JSXElement")return i.expression.openingElement&&i.expression.openingElement.name&&i.expression.openingElement.name.name==="svg";if(i.type==="BlockStatement"){let r=i.body.filter(l=>l.type==="ReturnStatement"&&l.argument);if(r.length===1){let l=r[0].argument;if(l.type==="JSXElement")return l.openingElement&&l.openingElement.name&&l.openingElement.name.name==="svg";if(l.type==="ParenthesizedExpression"&&l.expression&&l.expression.type==="JSXElement")return l.expression.openingElement&&l.expression.openingElement.name&&l.expression.openingElement.name.name==="svg"}}return!1},s=g=>{let i=t(g);if(!I(i))return;let r=y(g),l=C(i);r&&!l&&e.report({message:`Component "${i}" returns an SVG element and should end with "Icon" suffix (e.g., "${i}Icon")`,node:g.parent&&g.parent.type==="VariableDeclarator"?g.parent.id:g.id||g}),l&&!r&&e.report({message:`Component "${i}" has "Icon" suffix but doesn't return an SVG element. Either rename it or make it return an SVG.`,node:g.parent&&g.parent.type==="VariableDeclarator"?g.parent.id:g.id||g})};return{ArrowFunctionExpression:s,FunctionDeclaration:s,FunctionExpression:s}},meta:{docs:{description:"Enforce SVG components to have 'Icon' suffix and vice versa"},fixable:null,schema:[],type:"suggestion"}},Xe={create(e){let I=(e.filename||e.getFilename()).replace(/\\/g,"/"),C={atoms:"",components:"",constants:"Constants",contexts:"Context",data:"Data",layouts:"Layout",pages:"Page",providers:"Provider",reducers:"Reducer",schemas:"Schema",services:"Service",strings:"Strings",theme:"Theme",themes:"Theme",views:"View"},y=new Set(["atoms","components","layouts","pages","providers","views"]),s=new Set(["constants","data","reducers","schemas","services","strings"]),g=S=>S.split("-").map(k=>k.charAt(0).toUpperCase()+k.slice(1)).join(""),i=S=>S.charAt(0).toLowerCase()+S.slice(1),r=Object.keys(C).join("|"),l=()=>{let S=new RegExp(`\\/(${r})\\/(.+)\\.(jsx?|tsx?)$`),k=I.match(S);if(!k)return null;let $=k[1],v=C[$],d=k[2].split("/"),w=d[d.length-1],L=d.slice(0,-1);return{fileName:w,folder:$,intermediateFolders:L,suffix:v}},o=new Set(["shared","common","ui","base","general","core"]),n=S=>{let{fileName:k,folder:$,intermediateFolders:v,suffix:p}=S;if(k==="index"&&v.length===0)return null;let d=v.filter(R=>!o.has(R)),w;if(k==="index"){if(w=[...d].reverse(),w.length===0)return null}else w=[k,...[...d].reverse()];let L=w.map(g).join("")+p;return s.has($)?i(L):L},h=S=>S.parent&&S.parent.type==="VariableDeclarator"&&S.parent.id&&S.parent.id.type==="Identifier"?{name:S.parent.id.name,identifierNode:S.parent.id}:S.id&&S.id.type==="Identifier"?{name:S.id.name,identifierNode:S.id}:null,f=S=>S&&/^[A-Z]/.test(S),c=S=>{let k=S.body;return k?k.type==="JSXElement"||k.type==="JSXFragment"||k.type==="ParenthesizedExpression"&&k.expression&&(k.expression.type==="JSXElement"||k.expression.type==="JSXFragment")?!0:k.type==="BlockStatement"?k.body.some(v=>{if(v.type==="ReturnStatement"&&v.argument){let p=v.argument;return p.type==="JSXElement"||p.type==="JSXFragment"||p.type==="ParenthesizedExpression"&&p.expression&&(p.expression.type==="JSXElement"||p.expression.type==="JSXFragment")}return!1}):!1:!1},a=(S,k,$,v)=>p=>{let d=e.sourceCode?e.sourceCode.getScope(S):e.getScope(),w=(H,F)=>{let M=H.variables.find(j=>j.name===F);return M||(H.upper?w(H.upper,F):null)},L=w(d,k);if(!L)return p.replaceText(v,$);let R=[],P=new Set;return L.defs.forEach(H=>{let F=`${H.name.range[0]}-${H.name.range[1]}`;P.has(F)||(P.add(F),R.push(p.replaceText(H.name,$)))}),L.references.forEach(H=>{let F=`${H.identifier.range[0]}-${H.identifier.range[1]}`;P.has(F)||(P.add(F),R.push(p.replaceText(H.identifier,$)))}),R},u=(S,k,$,v)=>$?`"${S}" in "${k}" folder must be named "${v}" (expected "${$}" suffix with chained folder names)`:`"${S}" in "${k}" folder must be named "${v}" (expected chained folder names)`,b=(S,k)=>{let $=Object.entries(C).filter(([v,p])=>v!==k&&p&&S.endsWith(p)).sort((v,p)=>p[1].length-v[1].length)[0];return $?$[0]:null},x=S=>S&&/^[a-z]/.test(S),T=(S,k)=>{let $=S.length,v=k.length;if(Math.abs($-v)>2)return 3;let p=Array.from({length:$+1},()=>Array(v+1).fill(0));for(let d=0;d<=$;d++)p[d][0]=d;for(let d=0;d<=v;d++)p[0][d]=d;for(let d=1;d<=$;d++)for(let w=1;w<=v;w++)p[d][w]=S[d-1]===k[w-1]?p[d-1][w-1]:1+Math.min(p[d-1][w-1],p[d-1][w],p[d][w-1]);return p[$][v]},m=(S,k,$,v,p,d)=>{let L=d.fileName==="index"?"":g(d.fileName),P=[...d.intermediateFolders.filter(z=>!o.has(z))].reverse().map(g).join(""),H=L+P,F=H+$,M=i(F);if(S.endsWith(F)||S===M)return;let j,N=S.endsWith($)?S.slice(0,-$.length):S,D=N.charAt(0).toUpperCase()+N.slice(1);H.startsWith(D)||T(N,i(L))<=2?j=M:j=N+F,e.report({fix:a(p,S,j,v),message:`"${S}" in "${k}" folder must end with "${F}" (should be "${j}")`,node:v})},E=S=>{let k=l();if(!k)return;let $=h(S);if(!$)return;let{name:v,identifierNode:p}=$,{folder:d,suffix:w}=k;if(s.has(d)){if(!x(v)||!w)return;m(v,d,w,p,S,k);return}if(!f(v)||y.has(d)&&!c(S))return;let L=n(k);if(L&&v!==L){let R=b(v,d);if(R){e.report({message:`"${v}" belongs in "${R}/" folder, not "${d}/". Move it to the correct folder.`,node:p});return}e.report({fix:a(S,v,L,p),message:u(v,d,w,L),node:p})}};return{ArrowFunctionExpression:E,FunctionDeclaration:E,FunctionExpression:E,VariableDeclarator:S=>{if(!S.id||S.id.type!=="Identifier"||S.init&&(S.init.type==="ArrowFunctionExpression"||S.init.type==="FunctionExpression"))return;let k=l();if(!k)return;let{folder:$,suffix:v}=k;if(y.has($))return;let p=S.id.name;if(s.has($)){if(!x(p)||!v)return;m(p,$,v,S.id,S,k);return}if(!f(p))return;let d=n(k);if(d&&p!==d){let w=b(p,$);if(w){e.report({message:`"${p}" belongs in "${w}/" folder, not "${$}/". Move it to the correct folder.`,node:S.id});return}e.report({fix:a(S,p,d,S.id),message:u(p,$,v,d),node:S.id})}}}},meta:{docs:{description:"Enforce naming conventions based on folder location \u2014 suffix for views/layouts/pages/providers/reducers/contexts/themes, chained folder names for nested files"},fixable:"code",schema:[],type:"suggestion"}},ze={create(e){let I=(e.filename||e.getFilename()).replace(/\\/g,"/"),C=e.options[0]||{},y=["actions","apis","assets","atoms","components","config","configs","constants","contexts","data","enums","helpers","hooks","interfaces","layouts","lib","middlewares","molecules","organisms","pages","providers","reducers","redux","requests","routes","schemas","sections","services","store","strings","styles","theme","thunks","types","ui","utils","utilities","views","widgets"],s=C.moduleFolders||[...y,...C.extraModuleFolders||[]],i=(()=>{for(let T of s){let m=new RegExp(`(.*/${T})/`),E=I.match(m);if(E)return{folder:T,fullPath:E[1]}}return null})();if(!i){let T=I.replace(/.*\//,"").replace(/\.(jsx?|tsx?)$/,"");return s.includes(T)?{Program(m){e.report({message:`"${T}" should be a folder, not a standalone file. Use "${T}/" folder with an index file instead.`,node:m})}}:{}}let{folder:r,fullPath:l}=i,o;try{o=Me.readdirSync(l,{withFileTypes:!0})}catch{return{}}let n=/\.(tsx?|jsx?)$/,h=o.filter(T=>T.isFile()&&n.test(T.name)&&!T.name.startsWith("index.")),f=o.filter(T=>T.isDirectory());if(h.length===0&&f.length===0)return{};if(h.length<=1&&f.length===0)return{};let c=()=>{for(let T of f)try{let m=`${l}/${T.name}`;if(Me.readdirSync(m,{withFileTypes:!0}).filter(S=>S.isFile()&&n.test(S.name)).length>=2)return!0}catch{}return!1},a=h.length>0,u=f.length>0,b=a&&u,x=u?c():!1;return{Program(T){if(!a&&u&&!x){e.report({message:`Unnecessary wrapper folders in "${r}/". Each item has only one file, use direct files instead (e.g., ${r}/component.tsx).`,node:T});return}if(b&&x){!I.slice(l.length+1).includes("/")&&e.report({message:`Since some items in "${r}/" contain multiple files, all items should be wrapped in folders.`,node:T});return}b&&!x&&I.slice(l.length+1).includes("/")&&e.report({message:`Unnecessary wrapper folder. Each item in "${r}/" has only one file, use direct files instead.`,node:T})}}},meta:{docs:{description:"Enforce consistent folder structure (flat vs wrapped) in module folders like atoms, components, hooks, enums, views, layouts, and pages"},fixable:null,schema:[{additionalProperties:!1,properties:{extraModuleFolders:{items:{type:"string"},type:"array"},moduleFolders:{items:{type:"string"},type:"array"}},type:"object"}],type:"suggestion"}},We={create(e){let C=(e.filename||e.getFilename()).replace(/\\/g,"/").split("/"),y=C[C.length-1],s=y.replace(/\.(jsx?|tsx?)$/,""),g=h=>h.endsWith("ies")?h.slice(0,-3)+"y":h.endsWith("ses")||h.endsWith("xes")||h.endsWith("zes")?h.slice(0,-2):h.endsWith("s")?h.slice(0,-1):h,i=C.indexOf("src");if(i===-1)return{};let r=C.slice(i+1,C.length-1);if(r.length===0)return{};let l=[];for(let h=1;h<r.length;h++){let f=r[h];for(let c=0;c<h;c++){let a=r[c],u=g(a),b=`-${u}`;f.endsWith(b)&&l.push({ancestorFolder:a,folderName:f,singular:u,suffix:b,suggestedName:f.slice(0,-b.length)})}}let o=null;if(s!=="index"&&r.length>=2){let h=r[r.length-1];s===h&&(o=h)}let n=null;if(s!=="index"&&!o)for(let h of r){let f=g(h),c=`-${f}`;if(s.endsWith(c)){n={folder:h,singular:f,suffix:c};break}}return l.length===0&&!n&&!o?{}:{Program(h){for(let f of l)e.report({message:`Folder name "${f.folderName}" has redundant suffix "${f.suffix}" \u2014 the "${f.ancestorFolder}/" ancestor folder already provides this context. Rename to "${f.suggestedName}".`,node:h});o&&e.report({message:`File name "${s}" is the same as its parent folder "${o}/". Use "index" instead (e.g., "${o}/index${y.match(/\.\w+$/)[0]}").`,node:h}),n&&e.report({message:`File name "${s}" has redundant suffix "${n.suffix}" \u2014 the "${n.folder}/" folder already provides this context. Rename to "${s.slice(0,-n.suffix.length)}".`,node:h})}}},meta:{docs:{description:"Disallow file and folder names that redundantly include the parent or ancestor folder name as a suffix"},fixable:null,schema:[],type:"suggestion"}};var Ue={create(e){let t=e.sourceCode||e.getSourceCode();return{BlockStatement:C=>{let{body:y}=C;if(y.length===0)return;let s=t.getFirstToken(C),g=t.getLastToken(C),i=y[0],r=y[y.length-1],l=" ".repeat(i.loc.start.column),o=" ".repeat(s.loc.start.column);s.loc.end.line===i.loc.start.line&&e.report({fix:n=>n.replaceTextRange([s.range[1],i.range[0]],`
55
+ `);return d.replaceTextRange([p.range[1],k.range[0]],L)},message:"No empty lines allowed between props type properties",node:k})}}),c.length>1){let k=c[c.length-1];t.getText(k).trimEnd().endsWith(",")||e.report({fix:v=>v.insertTextAfter(k,","),message:"Last props type property must have trailing comma",node:k})}if(c.length===1){let k=c[0],$=t.getText(k);$.trimEnd().endsWith(",")&&e.report({fix:v=>{let p=$.lastIndexOf(","),d=k.range[0]+p;return v.removeRange([d,d+1])},message:"Single props type property should not have trailing comma",node:k})}}},s=g=>{if(!g.returnType||!g.returnType.typeAnnotation)return;let i=g.returnType,r=i.typeAnnotation;if(!C(g)&&r.type==="TSTypeLiteral"){e.report({message:"Function return type must be a type reference (interface, type, or built-in type), not an inline object type. Define the return type separately.",node:r});return}let o;if(g.params.length>0){let a=g.params[g.params.length-1];o=t.getTokenAfter(a,u=>u.value===")")}else{let u=t.getFirstToken(g);for(;u&&u.value!=="(";)u=t.getTokenAfter(u);u&&(o=t.getTokenAfter(u,b=>b.value===")"))}if(!o)return;let n=t.getFirstToken(i);if(!n||n.value!==":")return;let h=t.getFirstToken(r);if(!h)return;let f=t.getText().slice(o.range[1],n.range[0]),c=t.getText().slice(n.range[1],h.range[0]);(f!==""||c!==" ")&&e.report({fix:a=>a.replaceTextRange([o.range[1],h.range[0]],": "),message:'Return type annotation must have no space before colon and one space after: "): TypeName"',node:i})};return{ArrowFunctionExpression(g){y(g),s(g)},FunctionDeclaration(g){y(g),s(g)},FunctionExpression(g){y(g),s(g)}}},meta:{docs:{description:"Enforce inline type annotation for React component props and return types with proper formatting"},fixable:"code",schema:[],type:"suggestion"}},Je={create(e){let t=g=>g.parent&&g.parent.type==="VariableDeclarator"&&g.parent.id&&g.parent.id.type==="Identifier"?g.parent.id.name:g.id&&g.id.type==="Identifier"?g.id.name:null,I=g=>g&&/^[A-Z]/.test(g),C=g=>g&&g.endsWith("Icon"),y=g=>{let i=g.body;if(!i)return!1;if(i.type==="JSXElement")return i.openingElement&&i.openingElement.name&&i.openingElement.name.name==="svg";if(i.type==="ParenthesizedExpression"&&i.expression&&i.expression.type==="JSXElement")return i.expression.openingElement&&i.expression.openingElement.name&&i.expression.openingElement.name.name==="svg";if(i.type==="BlockStatement"){let r=i.body.filter(l=>l.type==="ReturnStatement"&&l.argument);if(r.length===1){let l=r[0].argument;if(l.type==="JSXElement")return l.openingElement&&l.openingElement.name&&l.openingElement.name.name==="svg";if(l.type==="ParenthesizedExpression"&&l.expression&&l.expression.type==="JSXElement")return l.expression.openingElement&&l.expression.openingElement.name&&l.expression.openingElement.name.name==="svg"}}return!1},s=g=>{let i=t(g);if(!I(i))return;let r=y(g),l=C(i);r&&!l&&e.report({message:`Component "${i}" returns an SVG element and should end with "Icon" suffix (e.g., "${i}Icon")`,node:g.parent&&g.parent.type==="VariableDeclarator"?g.parent.id:g.id||g}),l&&!r&&e.report({message:`Component "${i}" has "Icon" suffix but doesn't return an SVG element. Either rename it or make it return an SVG.`,node:g.parent&&g.parent.type==="VariableDeclarator"?g.parent.id:g.id||g})};return{ArrowFunctionExpression:s,FunctionDeclaration:s,FunctionExpression:s}},meta:{docs:{description:"Enforce SVG components to have 'Icon' suffix and vice versa"},fixable:null,schema:[],type:"suggestion"}},Xe={create(e){let I=(e.filename||e.getFilename()).replace(/\\/g,"/"),C={atoms:"",components:"",constants:"Constants",contexts:"Context",data:"Data",layouts:"Layout",pages:"Page",providers:"Provider",reducers:"Reducer",schemas:"Schema",services:"Service",strings:"Strings",theme:"Theme",themes:"Theme",views:"View"},y=new Set(["atoms","components","layouts","pages","views"]),s=new Set(["constants","data","reducers","schemas","services","strings"]),g=S=>S.split("-").map(k=>k.charAt(0).toUpperCase()+k.slice(1)).join(""),i=S=>S.charAt(0).toLowerCase()+S.slice(1),r=Object.keys(C).join("|"),l=()=>{let S=new RegExp(`\\/(${r})\\/(.+)\\.(jsx?|tsx?)$`),k=I.match(S);if(!k)return null;let $=k[1],v=C[$],d=k[2].split("/"),w=d[d.length-1],L=d.slice(0,-1);return{fileName:w,folder:$,intermediateFolders:L,suffix:v}},o=new Set(["shared","common","ui","base","general","core"]),n=S=>{let{fileName:k,folder:$,intermediateFolders:v,suffix:p}=S;if(k==="index"&&v.length===0)return null;let d=v.filter(R=>!o.has(R)),w;if(k==="index"){if(w=[...d].reverse(),w.length===0)return null}else w=[k,...[...d].reverse()];let L=w.map(g).join("")+p;return s.has($)?i(L):L},h=S=>S.parent&&S.parent.type==="VariableDeclarator"&&S.parent.id&&S.parent.id.type==="Identifier"?{name:S.parent.id.name,identifierNode:S.parent.id}:S.id&&S.id.type==="Identifier"?{name:S.id.name,identifierNode:S.id}:null,f=S=>S&&/^[A-Z]/.test(S),c=S=>{let k=S.body;return k?k.type==="JSXElement"||k.type==="JSXFragment"||k.type==="ParenthesizedExpression"&&k.expression&&(k.expression.type==="JSXElement"||k.expression.type==="JSXFragment")?!0:k.type==="BlockStatement"?k.body.some(v=>{if(v.type==="ReturnStatement"&&v.argument){let p=v.argument;return p.type==="JSXElement"||p.type==="JSXFragment"||p.type==="ParenthesizedExpression"&&p.expression&&(p.expression.type==="JSXElement"||p.expression.type==="JSXFragment")}return!1}):!1:!1},a=(S,k,$,v)=>p=>{let d=e.sourceCode?e.sourceCode.getScope(S):e.getScope(),w=(H,F)=>{let M=H.variables.find(j=>j.name===F);return M||(H.upper?w(H.upper,F):null)},L=w(d,k);if(!L)return p.replaceText(v,$);let R=[],P=new Set;return L.defs.forEach(H=>{let F=`${H.name.range[0]}-${H.name.range[1]}`;P.has(F)||(P.add(F),R.push(p.replaceText(H.name,$)))}),L.references.forEach(H=>{let F=`${H.identifier.range[0]}-${H.identifier.range[1]}`;P.has(F)||(P.add(F),R.push(p.replaceText(H.identifier,$)))}),R},u=(S,k,$,v)=>$?`"${S}" in "${k}" folder must be named "${v}" (expected "${$}" suffix with chained folder names)`:`"${S}" in "${k}" folder must be named "${v}" (expected chained folder names)`,b=(S,k)=>{let $=Object.entries(C).filter(([v,p])=>v!==k&&p&&S.endsWith(p)).sort((v,p)=>p[1].length-v[1].length)[0];return $?$[0]:null},x=S=>S&&/^[a-z]/.test(S),T=(S,k)=>{let $=S.length,v=k.length;if(Math.abs($-v)>2)return 3;let p=Array.from({length:$+1},()=>Array(v+1).fill(0));for(let d=0;d<=$;d++)p[d][0]=d;for(let d=0;d<=v;d++)p[0][d]=d;for(let d=1;d<=$;d++)for(let w=1;w<=v;w++)p[d][w]=S[d-1]===k[w-1]?p[d-1][w-1]:1+Math.min(p[d-1][w-1],p[d-1][w],p[d][w-1]);return p[$][v]},m=(S,k,$,v,p,d)=>{let L=d.fileName==="index"?"":g(d.fileName),P=[...d.intermediateFolders.filter(z=>!o.has(z))].reverse().map(g).join(""),H=L+P,F=H+$,M=i(F);if(S.endsWith(F)||S===M)return;let j,N=S.endsWith($)?S.slice(0,-$.length):S,D=N.charAt(0).toUpperCase()+N.slice(1);H.startsWith(D)||T(N,i(L))<=2?j=M:j=N+F,e.report({fix:a(p,S,j,v),message:`"${S}" in "${k}" folder must end with "${F}" (should be "${j}")`,node:v})},E=S=>{let k=l();if(!k)return;let $=h(S);if(!$)return;let{name:v,identifierNode:p}=$,{folder:d,suffix:w}=k;if(s.has(d)){if(!w)return;if(x(v))m(v,d,w,p,S,k);else if(f(v)){let R=i(v);e.report({fix:a(S,v,R,p),message:`"${v}" in "${d}" folder should be camelCase. Rename to "${R}"`,node:p})}return}if(!f(v)){let R=S.parent&&S.parent.type==="VariableDeclarator"&&S.parent.parent;if(R&&R.parent&&R.parent.type==="ExportNamedDeclaration"&&x(v)){let H=n(k);H&&e.report({fix:a(S,v,H,p),message:`"${v}" in "${d}" folder should be PascalCase. Rename to "${H}"`,node:p})}return}if(y.has(d)&&!c(S))return;let L=n(k);if(L&&v!==L){let R=b(v,d);if(R){e.report({message:`"${v}" belongs in "${R}/" folder, not "${d}/". Move it to the correct folder.`,node:p});return}e.report({fix:a(S,v,L,p),message:u(v,d,w,L),node:p})}};return{ArrowFunctionExpression:E,FunctionDeclaration:E,FunctionExpression:E,VariableDeclarator:S=>{if(!S.id||S.id.type!=="Identifier"||S.init&&(S.init.type==="ArrowFunctionExpression"||S.init.type==="FunctionExpression"))return;let k=l();if(!k)return;let{folder:$,suffix:v}=k;if(y.has($))return;let p=S.id.name;if(s.has($)){if(!v)return;if(x(p))m(p,$,v,S.id,S,k);else if(f(p)){let w=i(p);e.report({fix:a(S,p,w,S.id),message:`"${p}" in "${$}" folder should be camelCase. Rename to "${w}"`,node:S.id})}return}if(!f(p)){if(S.parent&&S.parent.parent&&S.parent.parent.type==="ExportNamedDeclaration"&&x(p)){let L=n(k);L&&e.report({fix:a(S,p,L,S.id),message:`"${p}" in "${$}" folder should be PascalCase. Rename to "${L}"`,node:S.id})}return}let d=n(k);if(d&&p!==d){let w=b(p,$);if(w){e.report({message:`"${p}" belongs in "${w}/" folder, not "${$}/". Move it to the correct folder.`,node:S.id});return}e.report({fix:a(S,p,d,S.id),message:u(p,$,v,d),node:S.id})}}}},meta:{docs:{description:"Enforce naming conventions based on folder location \u2014 suffix for views/layouts/pages/providers/reducers/contexts/themes, chained folder names for nested files"},fixable:"code",schema:[],type:"suggestion"}},ze={create(e){let I=(e.filename||e.getFilename()).replace(/\\/g,"/"),C=e.options[0]||{},y=["actions","apis","assets","atoms","components","config","configs","constants","contexts","data","enums","helpers","hooks","interfaces","layouts","lib","middlewares","molecules","organisms","pages","providers","reducers","redux","requests","routes","schemas","sections","services","store","strings","styles","theme","thunks","types","ui","utils","utilities","views","widgets"],s=C.moduleFolders||[...y,...C.extraModuleFolders||[]],i=(()=>{for(let T of s){let m=new RegExp(`(.*/${T})/`),E=I.match(m);if(E)return{folder:T,fullPath:E[1]}}return null})();if(!i){let T=I.replace(/.*\//,"").replace(/\.(jsx?|tsx?)$/,"");return s.includes(T)?{Program(m){e.report({message:`"${T}" should be a folder, not a standalone file. Use "${T}/" folder with an index file instead.`,node:m})}}:{}}let{folder:r,fullPath:l}=i,o;try{o=Me.readdirSync(l,{withFileTypes:!0})}catch{return{}}let n=/\.(tsx?|jsx?)$/,h=o.filter(T=>T.isFile()&&n.test(T.name)&&!T.name.startsWith("index.")),f=o.filter(T=>T.isDirectory());if(h.length===0&&f.length===0)return{};if(h.length<=1&&f.length===0)return{};let c=()=>{for(let T of f)try{let m=`${l}/${T.name}`;if(Me.readdirSync(m,{withFileTypes:!0}).filter(S=>S.isFile()&&n.test(S.name)).length>=2)return!0}catch{}return!1},a=h.length>0,u=f.length>0,b=a&&u,x=u?c():!1;return{Program(T){if(!a&&u&&!x){e.report({message:`Unnecessary wrapper folders in "${r}/". Each item has only one file, use direct files instead (e.g., ${r}/component.tsx).`,node:T});return}if(b&&x){!I.slice(l.length+1).includes("/")&&e.report({message:`Since some items in "${r}/" contain multiple files, all items should be wrapped in folders.`,node:T});return}b&&!x&&I.slice(l.length+1).includes("/")&&e.report({message:`Unnecessary wrapper folder. Each item in "${r}/" has only one file, use direct files instead.`,node:T})}}},meta:{docs:{description:"Enforce consistent folder structure (flat vs wrapped) in module folders like atoms, components, hooks, enums, views, layouts, and pages"},fixable:null,schema:[{additionalProperties:!1,properties:{extraModuleFolders:{items:{type:"string"},type:"array"},moduleFolders:{items:{type:"string"},type:"array"}},type:"object"}],type:"suggestion"}},We={create(e){let C=(e.filename||e.getFilename()).replace(/\\/g,"/").split("/"),y=C[C.length-1],s=y.replace(/\.(jsx?|tsx?)$/,""),g=h=>h.endsWith("ies")?h.slice(0,-3)+"y":h.endsWith("ses")||h.endsWith("xes")||h.endsWith("zes")?h.slice(0,-2):h.endsWith("s")?h.slice(0,-1):h,i=C.indexOf("src");if(i===-1)return{};let r=C.slice(i+1,C.length-1);if(r.length===0)return{};let l=[];for(let h=1;h<r.length;h++){let f=r[h];for(let c=0;c<h;c++){let a=r[c],u=g(a),b=`-${u}`;f.endsWith(b)&&l.push({ancestorFolder:a,folderName:f,singular:u,suffix:b,suggestedName:f.slice(0,-b.length)})}}let o=null;if(s!=="index"&&r.length>=2){let h=r[r.length-1];s===h&&(o=h)}let n=null;if(s!=="index"&&!o)for(let h of r){let f=g(h),c=`-${f}`;if(s.endsWith(c)){n={folder:h,singular:f,suffix:c};break}}return l.length===0&&!n&&!o?{}:{Program(h){for(let f of l)e.report({message:`Folder name "${f.folderName}" has redundant suffix "${f.suffix}" \u2014 the "${f.ancestorFolder}/" ancestor folder already provides this context. Rename to "${f.suggestedName}".`,node:h});o&&e.report({message:`File name "${s}" is the same as its parent folder "${o}/". Use "index" instead (e.g., "${o}/index${y.match(/\.\w+$/)[0]}").`,node:h}),n&&e.report({message:`File name "${s}" has redundant suffix "${n.suffix}" \u2014 the "${n.folder}/" folder already provides this context. Rename to "${s.slice(0,-n.suffix.length)}".`,node:h})}}},meta:{docs:{description:"Disallow file and folder names that redundantly include the parent or ancestor folder name as a suffix"},fixable:null,schema:[],type:"suggestion"}};var Ve={create(e){let t=e.sourceCode||e.getSourceCode();return{BlockStatement:C=>{let{body:y}=C;if(y.length===0)return;let s=t.getFirstToken(C),g=t.getLastToken(C),i=y[0],r=y[y.length-1],l=" ".repeat(i.loc.start.column),o=" ".repeat(s.loc.start.column);s.loc.end.line===i.loc.start.line&&e.report({fix:n=>n.replaceTextRange([s.range[1],i.range[0]],`
56
56
  `+l),message:"Statement should be on its own line after opening brace",node:i}),g.loc.start.line===r.loc.end.line&&e.report({fix:n=>n.replaceTextRange([r.range[1],g.range[0]],`
57
- `+o),message:"Closing brace should be on its own line",node:g})}}},meta:{docs:{description:"Enforce newlines after opening brace and before closing brace in blocks"},fixable:"whitespace",schema:[],type:"layout"}},Ve={create(e){let t=e.sourceCode||e.getSourceCode(),I=(y,s)=>["Identifier","MemberExpression","UnaryExpression","Literal"].includes(y.type)||y.type==="CallExpression"&&y.arguments.length===0?!0:y.type==="LogicalExpression"?/\n\s*(\|\||&&)/.test(s)?!1:s.replace(/\s+/g," ").trim().length<=80:!1;return{IfStatement:y=>{let{consequent:s,test:g}=y,i=s.type==="BlockStatement",r=t.getFirstToken(y),l=t.getTokenAfter(r,c=>c.value==="("),o=t.getTokenAfter(g,c=>c.value===")");if(!l||!o)return;let n=i?t.getFirstToken(s):null;if(r.loc.end.line!==l.loc.start.line){e.report({fix:c=>c.replaceTextRange([r.range[1],l.range[0]]," "),message:"Opening parenthesis should be on the same line as 'if'",node:l});return}let h=l.loc.end.line!==o.loc.start.line,f=t.getText(g);if(h&&I(g,f)){let c=f.replace(/\s+/g," ").trim();e.report({fix:a=>a.replaceTextRange([l.range[1],o.range[0]],c),message:"If condition should be on a single line",node:g});return}n&&o.loc.end.line!==n.loc.start.line&&e.report({fix:c=>c.replaceTextRange([o.range[1],n.range[0]]," "),message:"Opening brace should be on the same line as closing parenthesis",node:n})}}},meta:{docs:{description:"Ensure if statement has proper formatting: if (...) {"},fixable:"whitespace",schema:[],type:"layout"}},_e={create(e){let t=e.sourceCode||e.getSourceCode(),I=s=>{if(s.type!=="IfStatement")return!1;let{consequent:g}=s;return g.type!=="BlockStatement"?!0:g.loc.start.line===g.loc.end.line},C=s=>{let{alternate:g}=s;if(!g||!I(s))return;let{consequent:i}=s,r=(i.type==="BlockStatement",t.getLastToken(i)),l=t.getTokenAfter(r,n=>n.value==="else");if(!l)return;l.loc.start.line-r.loc.end.line>1&&e.report({fix:n=>n.replaceTextRange([r.range[1],l.range[0]],`
57
+ `+o),message:"Closing brace should be on its own line",node:g})}}},meta:{docs:{description:"Enforce newlines after opening brace and before closing brace in blocks"},fixable:"whitespace",schema:[],type:"layout"}},Ue={create(e){let t=e.sourceCode||e.getSourceCode(),I=(y,s)=>["Identifier","MemberExpression","UnaryExpression","Literal"].includes(y.type)||y.type==="CallExpression"&&y.arguments.length===0?!0:y.type==="LogicalExpression"?/\n\s*(\|\||&&)/.test(s)?!1:s.replace(/\s+/g," ").trim().length<=80:!1;return{IfStatement:y=>{let{consequent:s,test:g}=y,i=s.type==="BlockStatement",r=t.getFirstToken(y),l=t.getTokenAfter(r,c=>c.value==="("),o=t.getTokenAfter(g,c=>c.value===")");if(!l||!o)return;let n=i?t.getFirstToken(s):null;if(r.loc.end.line!==l.loc.start.line){e.report({fix:c=>c.replaceTextRange([r.range[1],l.range[0]]," "),message:"Opening parenthesis should be on the same line as 'if'",node:l});return}let h=l.loc.end.line!==o.loc.start.line,f=t.getText(g);if(h&&I(g,f)){let c=f.replace(/\s+/g," ").trim();e.report({fix:a=>a.replaceTextRange([l.range[1],o.range[0]],c),message:"If condition should be on a single line",node:g});return}n&&o.loc.end.line!==n.loc.start.line&&e.report({fix:c=>c.replaceTextRange([o.range[1],n.range[0]]," "),message:"Opening brace should be on the same line as closing parenthesis",node:n})}}},meta:{docs:{description:"Ensure if statement has proper formatting: if (...) {"},fixable:"whitespace",schema:[],type:"layout"}},_e={create(e){let t=e.sourceCode||e.getSourceCode(),I=s=>{if(s.type!=="IfStatement")return!1;let{consequent:g}=s;return g.type!=="BlockStatement"?!0:g.loc.start.line===g.loc.end.line},C=s=>{let{alternate:g}=s;if(!g||!I(s))return;let{consequent:i}=s,r=(i.type==="BlockStatement",t.getLastToken(i)),l=t.getTokenAfter(r,n=>n.value==="else");if(!l)return;l.loc.start.line-r.loc.end.line>1&&e.report({fix:n=>n.replaceTextRange([r.range[1],l.range[0]],`
58
58
  `+" ".repeat(l.loc.start.column)),message:"No empty line allowed between single-line if and else",node:l})},y=s=>{let{body:g}=s;if(!(!g||!Array.isArray(g)))for(let i=0;i<g.length-1;i+=1){let r=g[i],l=g[i+1];if(r.type!=="IfStatement"||l.type!=="IfStatement")continue;let o=r;for(;o.alternate&&o.alternate.type==="IfStatement";)o=o.alternate;let n=o.alternate||o.consequent,h=n.type==="BlockStatement",f=l.consequent.type==="BlockStatement";(h||f)&&l.loc.start.line-n.loc.end.line===1&&e.report({fix:a=>a.insertTextAfter(n,`
59
59
  `),message:"Expected empty line between consecutive if statements with block bodies",node:l})}};return{BlockStatement:y,IfStatement:C,Program:y}},meta:{docs:{description:"Enforce proper spacing between if statements and if-else chains"},fixable:"whitespace",schema:[],type:"layout"}},qe={create(e){let t=e.sourceCode||e.getSourceCode(),I=e.options[0]||{},C=I.maxOperands!==void 0?I.maxOperands:3,y=2,s=c=>{let a=t.getTokenBefore(c),u=t.getTokenAfter(c);if(!a||!u)return!1;if(a.value==="("&&u.value===")"){if(c.parent.type==="IfStatement"&&c.parent.test===c){let b=t.getTokenBefore(a);if(b&&b.value==="if")return!1}return!0}return!1},g=c=>{let a=c.range[0],u=c.range[1],b=t.getTokenBefore(c),x=t.getTokenAfter(c);for(;b&&b.value==="("&&x&&x.value===")";){if(c.parent.type==="IfStatement"&&c.parent.test===c){let T=t.getTokenBefore(b);if(T&&T.value==="if")break}a=b.range[0],u=x.range[1],b=t.getTokenBefore(b),x=t.getTokenAfter(x)}return t.text.slice(a,u)},i=c=>{let a=[],u=b=>{b.type==="LogicalExpression"&&!s(b)?(u(b.left),u(b.right)):a.push(b)};return u(c),a},r=(c,a=0)=>{if(c.type!=="LogicalExpression")return a;let u=a;if(c.left.type==="LogicalExpression"){let b=s(c.left)?r(c.left,a+1):r(c.left,a);u=Math.max(u,b)}if(c.right.type==="LogicalExpression"){let b=s(c.right)?r(c.right,a+1):r(c.right,a);u=Math.max(u,b)}return u},l=(c,a=0,u=null)=>{if(c.type!=="LogicalExpression")return null;let b=null;if(c.left.type==="LogicalExpression"){let x=s(c.left),T=x?a+1:a;x&&T>y&&(b={node:c.left,depth:T,parent:c,side:"left"});let m=l(c.left,T,{node:c,side:"left"});m&&(!b||m.depth>b.depth)&&(b=m)}if(c.right.type==="LogicalExpression"){let x=s(c.right),T=x?a+1:a;if(x&&T>y){let E={node:c.right,depth:T,parent:c,side:"right"};(!b||E.depth>b.depth)&&(b=E)}let m=l(c.right,T,{node:c,side:"right"});m&&(!b||m.depth>b.depth)&&(b=m)}return b},o=c=>{if(c.type!=="LogicalExpression")return 1;let a=0,u=b=>{b.type==="LogicalExpression"&&!s(b)?(u(b.left),u(b.right)):a+=1};return u(c.left),u(c.right),a},n=c=>{if(c.type!=="LogicalExpression")return null;if(s(c)&&o(c)>C)return c;if(c.left.type==="LogicalExpression"){let a=n(c.left);if(a)return a}if(c.right.type==="LogicalExpression"){let a=n(c.right);if(a)return a}return null};return{IfStatement:c=>{let{test:a}=c;if(a.type!=="LogicalExpression")return;let u=i(a),b=t.getTokenBefore(a),x=t.getTokenAfter(a);if(!b||!x)return;let T=r(a);if(T>y){let v=l(a);if(v){let p=g(v.node),d=L=>{if(L.type==="LogicalExpression"){let R=d(L.left),P=d(L.right),H=L.operator==="&&"?"And":"Or";return`${R}${H}${P}`}return L.type==="Identifier"?L.name.charAt(0).toUpperCase()+L.name.slice(1):L.type==="BinaryExpression"||L.type==="CallExpression"||L.type==="MemberExpression"?"Expr":"Cond"},w=`is${d(v.node)}`;w.length>30&&(w="isNestedCondition"),e.report({fix:L=>{let R=[],P=c.loc.start.line,H=t.getIndexFromLoc({line:P,column:0}),M=t.lines[P-1].match(/^\s*/)[0];R.push(L.insertTextBeforeRange([H,H],`const ${w} = ${p};
60
60
  ${M}`));let j=t.getTokenBefore(v.node),N=t.getTokenAfter(v.node);return j&&N&&j.value==="("&&N.value===")"?R.push(L.replaceTextRange([j.range[0],N.range[1]],w)):R.push(L.replaceText(v.node,w)),R},message:`Condition nesting depth (${T}) exceeds maximum (${y}). Extract deeply nested condition to a variable.`,node:v.node});return}}let m=b.loc.start.line!==x.loc.end.line,E=v=>{if(v.type!=="BinaryExpression")return!1;let{left:p,right:d}=v;return!!(p.loc.end.line!==d.loc.start.line||E(p)||E(d))},A=v=>{if(v.type==="BinaryExpression"){let p=A(v.left),d=A(v.right);return`${p} ${v.operator} ${d}`}return t.getText(v)},S=n(a);if(S){let p=t.lines[c.loc.start.line-1].match(/^\s*/)[0],d=p+" ",w=(F,M=!1,j=d)=>{if(F.type==="LogicalExpression"&&(M||!s(F))){let N=w(F.left,!1,j),D=w(F.right,!1,j);return`${N}
@@ -72,17 +72,17 @@ ${M}${P.operator} ${D}
72
72
  ${H})`}return g(P)};return v.replaceTextRange([b.range[0],x.range[1]],`(
73
73
  ${w}${R(a,w)}
74
74
  ${d})`)},message:`If conditions with more than ${C} operands should be multiline, with each operand on its own line`,node:a})},Property:c=>{let{value:a}=c;if(!a||a.type!=="LogicalExpression")return;let u=i(a);if(u.length<2)return;let b=a.loc.start.line,x=a.loc.end.line,T=b!==x,m=k=>{if(k.type!=="BinaryExpression")return!1;let{left:$,right:v}=k;return!!($.loc.end.line!==v.loc.start.line||m($)||m(v))},E=k=>{if(k.type==="BinaryExpression"){let $=E(k.left),v=E(k.right);return`${$} ${k.operator} ${v}`}return t.getText(k)},A=n(a);if(u.length<=C&&!A){let k=u[0].loc.start.line,$=u.every(p=>p.loc.start.line===k),v=u.some(p=>m(p));(!$||v)&&e.report({fix:p=>{let d=w=>{if(w.type==="LogicalExpression"&&!s(w)){let L=d(w.left),R=d(w.right);return`${L} ${w.operator} ${R}`}return w.type==="BinaryExpression"&&m(w)?E(w):g(w)};return p.replaceText(a,d(a))},message:`Property conditions with \u2264${C} operands should be single line: condition: a && b && c. Multi-line only for >${C} operands`,node:a});return}let S=!T;if(T){for(let k=0;k<u.length-1;k+=1)if(u[k].loc.end.line===u[k+1].loc.start.line){S=!0;break}}S&&e.report({fix:k=>{let p=t.lines[c.loc.start.line-1].match(/^\s*/)[0]+" ",d=w=>{if(w.type==="LogicalExpression"&&!s(w)){let L=d(w.left),R=d(w.right);return`${L}
75
- ${p}${w.operator} ${R}`}return g(w)};return k.replaceText(a,d(a))},message:`Property conditions with more than ${C} operands should be multiline, with each operand on its own line`,node:a})}}},meta:{docs:{description:"Enforce multiline if/property conditions when exceeding threshold (default: >3 operands)"},fixable:"whitespace",schema:[{additionalProperties:!1,properties:{maxOperands:{default:3,description:"Maximum operands to keep on single line (default: 3). Also applies to nested groups.",minimum:1,type:"integer"}},type:"object"}],type:"layout"}},Ze={create(e){let t=e.sourceCode||e.getSourceCode(),C=(e.options[0]||{}).maxOperands??3,y=2,s=p=>{let d=t.getTokenBefore(p),w=t.getTokenAfter(p);return!d||!w?!1:d.value==="("&&w.value===")"},g=p=>{let d=p.range[0],w=p.range[1],L=t.getTokenBefore(p),R=t.getTokenAfter(p);for(;L&&L.value==="("&&R&&R.value===")";)d=L.range[0],w=R.range[1],L=t.getTokenBefore(L),R=t.getTokenAfter(R);return t.text.slice(d,w)},i=p=>{let d=[],w=L=>{L.type==="LogicalExpression"&&!s(L)?(w(L.left),w(L.right)):d.push(L)};return w(p),d},r=(p,d=0)=>{if(p.type!=="LogicalExpression")return d;let w=d;if(p.left.type==="LogicalExpression"){let L=s(p.left)?r(p.left,d+1):r(p.left,d);w=Math.max(w,L)}if(p.right.type==="LogicalExpression"){let L=s(p.right)?r(p.right,d+1):r(p.right,d);w=Math.max(w,L)}return w},l=(p,d=0)=>{if(p.type!=="LogicalExpression")return null;let w=null;if(p.left.type==="LogicalExpression"){let L=s(p.left),R=L?d+1:d;L&&R>y&&(w={node:p.left,depth:R,parent:p,side:"left"});let P=l(p.left,R);P&&(!w||P.depth>w.depth)&&(w=P)}if(p.right.type==="LogicalExpression"){let L=s(p.right),R=L?d+1:d;if(L&&R>y){let H={node:p.right,depth:R,parent:p,side:"right"};(!w||H.depth>w.depth)&&(w=H)}let P=l(p.right,R);P&&(!w||P.depth>w.depth)&&(w=P)}return w},o=p=>{if(p.type==="LogicalExpression"){let d=o(p.left),w=o(p.right),L=p.operator==="&&"?"And":"Or";return`${d}${L}${w}`}return p.type==="Identifier"?p.name.charAt(0).toUpperCase()+p.name.slice(1):p.type==="BinaryExpression"||p.type==="CallExpression"||p.type==="MemberExpression"?"Expr":"Cond"},n=p=>{if(p.type!=="LogicalExpression")return 1;let d=0,w=L=>{L.type==="LogicalExpression"&&!s(L)?(w(L.left),w(L.right)):d+=1};return w(p.left),w(p.right),d},h=p=>{if(p.type!=="LogicalExpression")return null;if(s(p)&&n(p)>C)return p;if(p.left.type==="LogicalExpression"){let d=h(p.left);if(d)return d}if(p.right.type==="LogicalExpression"){let d=h(p.right);if(d)return d}return null},f=p=>{if(p.type!=="BinaryExpression")return!1;let{left:d,right:w}=p;return!!(d.loc.end.line!==w.loc.start.line||f(d)||f(w))},c=p=>{if(p.type==="BinaryExpression"){let d=c(p.left),w=c(p.right);return`${d} ${p.operator} ${w}`}return t.getText(p)},a=p=>{if(p.type!=="LogicalExpression")return!1;let d=t.getTokenAfter(p.left,w=>w.value==="||"||w.value==="&&");if(d){let w=t.getTokenAfter(d);if(w&&d.loc.end.line<w.loc.start.line)return!0}return!!(a(p.left)||a(p.right))},u=p=>{if(p.type==="Identifier"||p.type==="MemberExpression"||p.type==="UnaryExpression"||p.type==="BinaryExpression"||p.type==="CallExpression")return!0;if(p.type==="LogicalExpression"){let d=i(p).length,w=h(p);return d<=C&&!w}return!1},b=p=>{let d=t.getText(p.test).replace(/\s+/g," ").trim(),w=g(p.consequent).replace(/\s+/g," ").trim(),L=g(p.alternate).replace(/\s+/g," ").trim();return`${d} ? ${w} : ${L}`},x=p=>t.lines[p.loc.start.line-1].match(/^\s*/)[0].length,T=p=>p?p.type==="JSXElement"||p.type==="JSXFragment"?!0:p.type==="ParenthesizedExpression"?T(p.expression):p.type==="ConditionalExpression"?T(p.consequent)||T(p.alternate):p.type==="LogicalExpression"?T(p.left)||T(p.right):!1:!1,m=p=>p.type==="ObjectExpression"&&p.properties.length>=2||p.type==="ArrayExpression"&&p.elements.length>=3,E=p=>T(p.consequent)||T(p.alternate),A=p=>{let d=w=>w.type==="ConditionalExpression"&&s(w)?i(w.test).length>C:!1;return d(p.consequent)||d(p.alternate)},S=p=>{let d=t.getTokenAfter(p.test,L=>L.value==="?"),w=t.getTokenAfter(p.consequent,L=>L.value===":");return!!(d&&p.consequent.loc.start.line!==d.loc.start.line||w&&p.alternate.loc.start.line!==w.loc.start.line)},k=p=>{let d=p.loc.start.line===p.loc.end.line,w=S(p);if(p.consequent.type==="ConditionalExpression"&&!s(p.consequent)||p.alternate.type==="ConditionalExpression"&&!s(p.alternate)||m(p.consequent)||m(p.alternate)||E(p)||A(p)||d&&!w)return!1;let R=b(p);return e.report({fix:P=>P.replaceText(p,R),message:`Ternary with \u2264${C} operands should be on a single line`,node:p}),!0},$=p=>{let{test:d}=p,w=i(d),L=d.loc.start.line,R=d.loc.end.line,P=L!==R,H=h(d);if(H){let j=p.parent,N="";j&&j.loc&&(N=t.lines[j.loc.start.line-1].match(/^\s*/)[0]);let D=N+" ",z=(J,V=!1,U=D)=>{if(J.type==="LogicalExpression"&&(V||!s(J))){let W=z(J.left,!1,U),G=z(J.right,!1,U);return`${W}
76
- ${U}${J.operator} ${G}`}if(J.type==="LogicalExpression"&&s(J)&&n(J)>C){let G=U+" ",le=X=>{if(X.type==="LogicalExpression"&&!s(X)){let Z=le(X.left),Q=le(X.right);return`${Z}
75
+ ${p}${w.operator} ${R}`}return g(w)};return k.replaceText(a,d(a))},message:`Property conditions with more than ${C} operands should be multiline, with each operand on its own line`,node:a})}}},meta:{docs:{description:"Enforce multiline if/property conditions when exceeding threshold (default: >3 operands)"},fixable:"whitespace",schema:[{additionalProperties:!1,properties:{maxOperands:{default:3,description:"Maximum operands to keep on single line (default: 3). Also applies to nested groups.",minimum:1,type:"integer"}},type:"object"}],type:"layout"}},Ze={create(e){let t=e.sourceCode||e.getSourceCode(),C=(e.options[0]||{}).maxOperands??3,y=2,s=p=>{let d=t.getTokenBefore(p),w=t.getTokenAfter(p);return!d||!w?!1:d.value==="("&&w.value===")"},g=p=>{let d=p.range[0],w=p.range[1],L=t.getTokenBefore(p),R=t.getTokenAfter(p);for(;L&&L.value==="("&&R&&R.value===")";)d=L.range[0],w=R.range[1],L=t.getTokenBefore(L),R=t.getTokenAfter(R);return t.text.slice(d,w)},i=p=>{let d=[],w=L=>{L.type==="LogicalExpression"&&!s(L)?(w(L.left),w(L.right)):d.push(L)};return w(p),d},r=(p,d=0)=>{if(p.type!=="LogicalExpression")return d;let w=d;if(p.left.type==="LogicalExpression"){let L=s(p.left)?r(p.left,d+1):r(p.left,d);w=Math.max(w,L)}if(p.right.type==="LogicalExpression"){let L=s(p.right)?r(p.right,d+1):r(p.right,d);w=Math.max(w,L)}return w},l=(p,d=0)=>{if(p.type!=="LogicalExpression")return null;let w=null;if(p.left.type==="LogicalExpression"){let L=s(p.left),R=L?d+1:d;L&&R>y&&(w={node:p.left,depth:R,parent:p,side:"left"});let P=l(p.left,R);P&&(!w||P.depth>w.depth)&&(w=P)}if(p.right.type==="LogicalExpression"){let L=s(p.right),R=L?d+1:d;if(L&&R>y){let H={node:p.right,depth:R,parent:p,side:"right"};(!w||H.depth>w.depth)&&(w=H)}let P=l(p.right,R);P&&(!w||P.depth>w.depth)&&(w=P)}return w},o=p=>{if(p.type==="LogicalExpression"){let d=o(p.left),w=o(p.right),L=p.operator==="&&"?"And":"Or";return`${d}${L}${w}`}return p.type==="Identifier"?p.name.charAt(0).toUpperCase()+p.name.slice(1):p.type==="BinaryExpression"||p.type==="CallExpression"||p.type==="MemberExpression"?"Expr":"Cond"},n=p=>{if(p.type!=="LogicalExpression")return 1;let d=0,w=L=>{L.type==="LogicalExpression"&&!s(L)?(w(L.left),w(L.right)):d+=1};return w(p.left),w(p.right),d},h=p=>{if(p.type!=="LogicalExpression")return null;if(s(p)&&n(p)>C)return p;if(p.left.type==="LogicalExpression"){let d=h(p.left);if(d)return d}if(p.right.type==="LogicalExpression"){let d=h(p.right);if(d)return d}return null},f=p=>{if(p.type!=="BinaryExpression")return!1;let{left:d,right:w}=p;return!!(d.loc.end.line!==w.loc.start.line||f(d)||f(w))},c=p=>{if(p.type==="BinaryExpression"){let d=c(p.left),w=c(p.right);return`${d} ${p.operator} ${w}`}return t.getText(p)},a=p=>{if(p.type!=="LogicalExpression")return!1;let d=t.getTokenAfter(p.left,w=>w.value==="||"||w.value==="&&");if(d){let w=t.getTokenAfter(d);if(w&&d.loc.end.line<w.loc.start.line)return!0}return!!(a(p.left)||a(p.right))},u=p=>{if(p.type==="Identifier"||p.type==="MemberExpression"||p.type==="UnaryExpression"||p.type==="BinaryExpression"||p.type==="CallExpression")return!0;if(p.type==="LogicalExpression"){let d=i(p).length,w=h(p);return d<=C&&!w}return!1},b=p=>{let d=t.getText(p.test).replace(/\s+/g," ").trim(),w=g(p.consequent).replace(/\s+/g," ").trim(),L=g(p.alternate).replace(/\s+/g," ").trim();return`${d} ? ${w} : ${L}`},x=p=>t.lines[p.loc.start.line-1].match(/^\s*/)[0].length,T=p=>p?p.type==="JSXElement"||p.type==="JSXFragment"?!0:p.type==="ParenthesizedExpression"?T(p.expression):p.type==="ConditionalExpression"?T(p.consequent)||T(p.alternate):p.type==="LogicalExpression"?T(p.left)||T(p.right):!1:!1,m=p=>p.type==="ObjectExpression"&&p.properties.length>=2||p.type==="ArrayExpression"&&p.elements.length>=3,E=p=>T(p.consequent)||T(p.alternate),A=p=>{let d=w=>w.type==="ConditionalExpression"&&s(w)?i(w.test).length>C:!1;return d(p.consequent)||d(p.alternate)},S=p=>{let d=t.getTokenAfter(p.test,L=>L.value==="?"),w=t.getTokenAfter(p.consequent,L=>L.value===":");return!!(d&&p.consequent.loc.start.line!==d.loc.start.line||w&&p.alternate.loc.start.line!==w.loc.start.line)},k=p=>{let d=p.loc.start.line===p.loc.end.line,w=S(p);if(p.consequent.type==="ConditionalExpression"&&!s(p.consequent)||p.alternate.type==="ConditionalExpression"&&!s(p.alternate)||m(p.consequent)||m(p.alternate)||E(p)||A(p)||d&&!w)return!1;let R=b(p);return e.report({fix:P=>P.replaceText(p,R),message:`Ternary with \u2264${C} operands should be on a single line`,node:p}),!0},$=p=>{let{test:d}=p,w=i(d),L=d.loc.start.line,R=d.loc.end.line,P=L!==R,H=h(d);if(H){let j=p.parent,N="";j&&j.loc&&(N=t.lines[j.loc.start.line-1].match(/^\s*/)[0]);let D=N+" ",z=(J,U=!1,V=D)=>{if(J.type==="LogicalExpression"&&(U||!s(J))){let W=z(J.left,!1,V),G=z(J.right,!1,V);return`${W}
76
+ ${V}${J.operator} ${G}`}if(J.type==="LogicalExpression"&&s(J)&&n(J)>C){let G=V+" ",le=X=>{if(X.type==="LogicalExpression"&&!s(X)){let Z=le(X.left),Q=le(X.right);return`${Z}
77
77
  ${G}${X.operator} ${Q}`}return g(X)},B=le(J.left),O=le(J.right);return`(
78
78
  ${G}${B}
79
79
  ${G}${J.operator} ${O}
80
- ${U})`}return g(J)},q=(J,V)=>{if(J===V){let U=z(J,!0);return`(
81
- ${D}${U}
82
- ${N})`}if(J.type==="LogicalExpression"&&!s(J)){let U=q(J.left,V),W=q(J.right,V);return`${U} ${J.operator} ${W}`}if(J.type==="LogicalExpression"&&s(J)){let U=(W,G)=>W===G?!0:W.type==="LogicalExpression"?U(W.left,G)||U(W.right,G):!1;if(U(J,V))return`(${q(J,V)})`}return g(J)},Y=(J=>{let V=[],U=W=>{W.type==="LogicalExpression"&&!s(W)?(U(W.left),U(W.right)):V.push(W)};return J.type==="LogicalExpression"&&(U(J.left),U(J.right)),V})(H);if(!Y.every((J,V)=>V===0?!0:J.loc.start.line!==Y[V-1].loc.start.line)){let J=q(d,H),V=g(p.consequent).replace(/\s+/g," ").trim(),U=g(p.alternate).replace(/\s+/g," ").trim();e.report({fix:W=>W.replaceText(p,`${J} ? ${V} : ${U}`),message:`Nested condition with >${C} operands should be formatted multiline`,node:H});return}}if(w.length<=C){if(h(d))return;let N=m(p.consequent)||m(p.alternate);if(E(p))return;let D=p.consequent.type==="ConditionalExpression"&&!s(p.consequent)||p.alternate.type==="ConditionalExpression"&&!s(p.alternate);if(N||D||A(p))return;let z=p.loc.start.line===p.loc.end.line,q=S(p);if(z&&!q)return;let _=b(p);e.report({fix:Y=>Y.replaceText(p,_),message:`Ternary with \u2264${C} operands should be on a single line`,node:p});return}let F=!P,M=p.parent;if(P){for(let j=0;j<w.length-1;j+=1)if(w[j].loc.end.line===w[j+1].loc.start.line){F=!0;break}if(!F&&a(d)&&(F=!0),!F){let j=t.getTokenAfter(d,N=>N.value==="?");j&&j.loc.start.line===d.loc.end.line&&(F=!0)}if(!F){let j=t.getTokenAfter(d,N=>N.value==="?");j&&j.loc.start.line>d.loc.end.line+1&&(F=!0)}if(!F){let j=t.getTokenAfter(p.consequent,N=>N.value===":");j&&j.loc.start.line>p.consequent.loc.end.line+1&&(F=!0)}if(!F&&S(p)&&(F=!0),!F){let j=t.getTokenAfter(d,D=>D.value==="?"),N=t.getTokenAfter(p.consequent,D=>D.value===":");j&&N&&j.loc.start.line===N.loc.start.line&&(F=!0)}if(!F&&M&&M.type==="Property"&&M.value===p){let j=M.key.loc.end.line;w[0].loc.start.line!==j&&(F=!0)}}F&&e.report({fix:j=>{let N,D=!1,z="";if(M&&M.type==="Property"&&M.value===p){let U=M.key.loc.end.line;w[0].loc.start.line!==U&&(D=!0,z=t.getText(M.key)+": ",N=t.lines[M.loc.start.line-1].match(/^\s*/)[0])}N||(N=t.lines[p.loc.start.line-1].match(/^\s*/)[0]);let q=N+" ",_=U=>{if(U.type==="LogicalExpression"&&!s(U)){let W=_(U.left),G=_(U.right);return`${W}
83
- ${q}${U.operator} ${G}`}return g(U)},Y=t.getText(p.consequent),ne=t.getText(p.alternate),V=`${_(d)}
80
+ ${V})`}return g(J)},q=(J,U)=>{if(J===U){let V=z(J,!0);return`(
81
+ ${D}${V}
82
+ ${N})`}if(J.type==="LogicalExpression"&&!s(J)){let V=q(J.left,U),W=q(J.right,U);return`${V} ${J.operator} ${W}`}if(J.type==="LogicalExpression"&&s(J)){let V=(W,G)=>W===G?!0:W.type==="LogicalExpression"?V(W.left,G)||V(W.right,G):!1;if(V(J,U))return`(${q(J,U)})`}return g(J)},Y=(J=>{let U=[],V=W=>{W.type==="LogicalExpression"&&!s(W)?(V(W.left),V(W.right)):U.push(W)};return J.type==="LogicalExpression"&&(V(J.left),V(J.right)),U})(H);if(!Y.every((J,U)=>U===0?!0:J.loc.start.line!==Y[U-1].loc.start.line)){let J=q(d,H),U=g(p.consequent).replace(/\s+/g," ").trim(),V=g(p.alternate).replace(/\s+/g," ").trim();e.report({fix:W=>W.replaceText(p,`${J} ? ${U} : ${V}`),message:`Nested condition with >${C} operands should be formatted multiline`,node:H});return}}if(w.length<=C){if(h(d))return;let N=m(p.consequent)||m(p.alternate);if(E(p))return;let D=p.consequent.type==="ConditionalExpression"&&!s(p.consequent)||p.alternate.type==="ConditionalExpression"&&!s(p.alternate);if(N||D||A(p))return;let z=p.loc.start.line===p.loc.end.line,q=S(p);if(z&&!q)return;let _=b(p);e.report({fix:Y=>Y.replaceText(p,_),message:`Ternary with \u2264${C} operands should be on a single line`,node:p});return}let F=!P,M=p.parent;if(P){for(let j=0;j<w.length-1;j+=1)if(w[j].loc.end.line===w[j+1].loc.start.line){F=!0;break}if(!F&&a(d)&&(F=!0),!F){let j=t.getTokenAfter(d,N=>N.value==="?");j&&j.loc.start.line===d.loc.end.line&&(F=!0)}if(!F){let j=t.getTokenAfter(d,N=>N.value==="?");j&&j.loc.start.line>d.loc.end.line+1&&(F=!0)}if(!F){let j=t.getTokenAfter(p.consequent,N=>N.value===":");j&&j.loc.start.line>p.consequent.loc.end.line+1&&(F=!0)}if(!F&&S(p)&&(F=!0),!F){let j=t.getTokenAfter(d,D=>D.value==="?"),N=t.getTokenAfter(p.consequent,D=>D.value===":");j&&N&&j.loc.start.line===N.loc.start.line&&(F=!0)}if(!F&&M&&M.type==="Property"&&M.value===p){let j=M.key.loc.end.line;w[0].loc.start.line!==j&&(F=!0)}}F&&e.report({fix:j=>{let N,D=!1,z="";if(M&&M.type==="Property"&&M.value===p){let V=M.key.loc.end.line;w[0].loc.start.line!==V&&(D=!0,z=t.getText(M.key)+": ",N=t.lines[M.loc.start.line-1].match(/^\s*/)[0])}N||(N=t.lines[p.loc.start.line-1].match(/^\s*/)[0]);let q=N+" ",_=V=>{if(V.type==="LogicalExpression"&&!s(V)){let W=_(V.left),G=_(V.right);return`${W}
83
+ ${q}${V.operator} ${G}`}return g(V)},Y=t.getText(p.consequent),ne=t.getText(p.alternate),U=`${_(d)}
84
84
  ${q}? ${Y}
85
- ${q}: ${ne}`;return D?j.replaceTextRange([M.key.range[0],p.range[1]],`${z}${V}`):j.replaceText(p,V)},message:`Ternary conditions with more than ${C} operands should be multiline, with each operand on its own line`,node:d})},v=p=>{let d=p.parent;for(;d&&d.type==="ParenthesizedExpression";)d=d.parent;return d&&d.type==="ConditionalExpression"?d.consequent===p||d.alternate===p||p.parent.type==="ParenthesizedExpression"&&(d.consequent===p.parent||d.alternate===p.parent):!1};return{ConditionalExpression(p){let{test:d}=p;if(!v(p)){if(d.type==="LogicalExpression"){let w=r(d);if(w>y){let L=l(d);if(L){let R=g(L.node),P=`is${o(L.node)}`;P.length>30&&(P="isNestedCondition"),e.report({fix:H=>{let F=[],M=p;for(;M.parent&&M.parent.type!=="Program"&&M.parent.type!=="BlockStatement";)M=M.parent;let j=M.loc.start.line,N=t.getIndexFromLoc({line:j,column:0}),z=t.lines[j-1].match(/^\s*/)[0];F.push(H.insertTextBeforeRange([N,N],`const ${P} = ${R};
85
+ ${q}: ${ne}`;return D?j.replaceTextRange([M.key.range[0],p.range[1]],`${z}${U}`):j.replaceText(p,U)},message:`Ternary conditions with more than ${C} operands should be multiline, with each operand on its own line`,node:d})},v=p=>{let d=p.parent;for(;d&&d.type==="ParenthesizedExpression";)d=d.parent;return d&&d.type==="ConditionalExpression"?d.consequent===p||d.alternate===p||p.parent.type==="ParenthesizedExpression"&&(d.consequent===p.parent||d.alternate===p.parent):!1};return{ConditionalExpression(p){let{test:d}=p;if(!v(p)){if(d.type==="LogicalExpression"){let w=r(d);if(w>y){let L=l(d);if(L){let R=g(L.node),P=`is${o(L.node)}`;P.length>30&&(P="isNestedCondition"),e.report({fix:H=>{let F=[],M=p;for(;M.parent&&M.parent.type!=="Program"&&M.parent.type!=="BlockStatement";)M=M.parent;let j=M.loc.start.line,N=t.getIndexFromLoc({line:j,column:0}),z=t.lines[j-1].match(/^\s*/)[0];F.push(H.insertTextBeforeRange([N,N],`const ${P} = ${R};
86
86
  ${z}`));let q=t.getTokenBefore(L.node),_=t.getTokenAfter(L.node);return q&&_&&q.value==="("&&_.value===")"?F.push(H.replaceTextRange([q.range[0],_.range[1]],P)):F.push(H.replaceText(L.node,P)),F},message:`Ternary condition nesting depth (${w}) exceeds maximum (${y}). Extract deeply nested condition to a variable.`,node:L.node});return}}}u(d)&&k(p)||d.type==="LogicalExpression"&&$(p)}}}},meta:{docs:{description:"Enforce consistent ternary formatting based on condition operand count: \u2264maxOperands collapses to single line, >maxOperands expands to multiline"},fixable:"code",schema:[{additionalProperties:!1,properties:{maxOperands:{default:3,description:"Maximum condition operands to keep ternary on single line (default: 3). Also applies to nested groups.",minimum:1,type:"integer"}},type:"object"}],type:"layout"}},Ke={create(e){let t=e.sourceCode||e.getSourceCode(),I=e.options[0]||{},C=I.maxOperands!==void 0?I.maxOperands:3,y=o=>{let n=t.getTokenBefore(o),h=t.getTokenAfter(o);return!n||!h?!1:n.value==="("&&h.value===")"},s=o=>{let n=[],h=f=>{f.type==="LogicalExpression"&&!y(f)?(h(f.left),h(f.right)):n.push(f)};return h(o),n},g=(o,n)=>{let f=t.getTokensBetween(o,n).find(c=>c.value==="||"||c.value==="&&"||c.value==="??"||c.value==="|"||c.value==="&");return f?f.value:"||"},i=o=>o.loc.start.line!==o.loc.end.line,r=o=>{let n=o.parent;for(;n;){if(n.type==="IfStatement"&&n.test===o||n.type==="ConditionalExpression"&&n.test===o)return!0;if(n.type.includes("Statement")||n.type.includes("Declaration"))return!1;n=n.parent}return!1};return{LogicalExpression:o=>{if(o.parent.type==="LogicalExpression"&&!y(o)||r(o))return;let n=s(o);if(n.length<=C){if(i(o)){if(n.some(f=>f.loc.start.line!==f.loc.end.line))return;e.report({fix(f){let c=[t.getText(n[0])];for(let a=1;a<n.length;a++){let u=g(n[a-1],n[a]);c.push(` ${u} ${t.getText(n[a])}`)}return f.replaceText(o,c.join(""))},message:`Logical expression with ${n.length} operands should be on a single line (max for multiline: ${C})`,node:o})}return}if(i(o)){let h=!0;for(let f=1;f<n.length;f++)if(n[f].loc.start.line===n[f-1].loc.end.line){h=!1;break}if(h)return}e.report({fix(h){let f=t.getText(n[0]),c=t.getFirstToken(n[0]),a=t.text.lastIndexOf(`
87
87
  `,c.range[0])+1,b=t.text.slice(a,c.range[0]).match(/^(\s*)/),x=b?b[1]:"",T=[f];for(let E=1;E<n.length;E++){let A=g(n[E-1],n[E]),S=t.getText(n[E]);T.push(`${x} ${A} ${S}`)}let m=T.join(`
88
88
  `);return h.replaceText(o,m)},message:`Logical expression with ${n.length} operands should be on multiple lines (max: ${C})`,node:o})}}},meta:{docs:{description:"Enforce single line for \u2264maxOperands, multiline for >maxOperands logical expressions"},fixable:"code",schema:[{additionalProperties:!1,properties:{maxOperands:{default:3,description:"Maximum operands to keep on single line (default: 3)",minimum:1,type:"integer"}},type:"object"}],type:"layout"}},Ge={create(e){let t=e.sourceCode||e.getSourceCode(),I=y=>["IfStatement","ForStatement","ForInStatement","ForOfStatement","WhileStatement","DoWhileStatement","TryStatement","SwitchStatement","WithStatement"].includes(y.type),C=y=>{if(y.type==="IfStatement"&&y.alternate)return C(y.alternate);if(y.type==="TryStatement"){if(y.finalizer)return y.finalizer.loc.end.line;if(y.handler)return y.handler.loc.end.line}return y.loc.end.line};return{"BlockStatement:exit"(y){let s=y.parent;if(!s||!I(s)||s.type==="IfStatement"&&s.consequent===y&&s.alternate||s.type==="TryStatement"&&(s.block===y||s.handler?.body===y)&&(s.handler||s.finalizer)&&(s.block===y&&(s.handler||s.finalizer)||s.handler?.body===y&&s.finalizer))return;let g=s.parent;if(!g||g.type!=="BlockStatement")return;let i=g.body.indexOf(s);if(i===-1||i===g.body.length-1)return;let r=g.body[i+1];if(s.type==="IfStatement"&&r.type==="IfStatement")return;let l=C(s);r.loc.start.line-l<2&&e.report({fix:n=>{let h=t.getLastToken(s);return n.insertTextAfter(h,`
@@ -217,11 +217,11 @@ ${c}"`},r=(f,c,a)=>f.length+c>C||a>y,l=(f,c)=>{if(!/\n/.test(f))return!1;let a=c
217
217
  ${c} ${f.split(`
218
218
  `).join(`
219
219
  `+c+" ")}
220
- ${c})${x}`),message:"Multi-line JSX in object property must be wrapped in parentheses",node:s})}return}if(s.type==="ConditionalExpression"){let r=t.getText(s).replace(/\s*\n\s*/g," ").trim();if(s.loc.start.line!==s.loc.end.line&&r.length<=80){e.report({fix:h=>h.replaceText(s,r),message:"Short ternary expression should be on a single line",node:s});return}let o=t.getTokenAfter(s.test,h=>h.value==="?"),n=t.getTokenAfter(s.consequent,h=>h.value===":");if(o){let h=t.getTokenAfter(o);if(h&&o.loc.end.line<h.loc.start.line&&r.length<=80){e.report({fix:f=>f.replaceText(s,r),message:"Ternary operator '?' should not be at end of line",node:o});return}}if(n){let h=t.getTokenAfter(n);if(h&&n.loc.end.line<h.loc.start.line&&r.length<=80){e.report({fix:f=>f.replaceText(s,r),message:"Ternary operator ':' should not be at end of line",node:n});return}}return}if(s.loc.start.line>y.loc.end.line){if((s.type==="ObjectExpression"||s.type==="ArrayExpression")&&s.loc.start.line!==s.loc.end.line)return;let i=t.getTokenAfter(y);if(i&&i.value==="(")return;e.report({fix:r=>r.replaceTextRange([y.range[1],s.range[0]]," "),message:"Property value should be on the same line as the colon",node:s})}}}},meta:{docs:{description:"Enforce property value on same line as colon with proper spacing"},fixable:"whitespace",schema:[],type:"layout"}},Bt={create(e){let t=e.sourceCode||e.getSourceCode();return{Property(I){let{key:C}=I;if(C.type!=="Literal"||typeof C.value!="string")return;let y=C.value,s=y.trim();y!==s&&s.length>0&&e.report({fix:g=>g.replaceText(C,`"${s}"`),message:`String property key should not have extra spaces inside quotes: "${s}" not "${y}"`,node:C})}}},meta:{docs:{description:"Enforce no extra spaces inside string property keys"},fixable:"code",schema:[],type:"layout"}};var Ht={create(e){let t={CALLBACK:12,CONTEXT_HOOK:8,CUSTOM_HOOK:9,DERIVED_STATE:10,EFFECT:14,HANDLER_FUNCTION:13,MEMO:11,PROPS_DESTRUCTURE:1,PROPS_DESTRUCTURE_BODY:2,REDUCER:5,REF:3,RETURN:15,ROUTER_HOOK:7,SELECTOR_DISPATCH:6,STATE:4,UNKNOWN:99},I={1:"props destructure",2:"destructured variables from props",3:"useRef",4:"useState",5:"useReducer",6:"useSelector/useDispatch",7:"router hooks",8:"context hooks",9:"custom hooks",10:"derived state/computed variables",11:"useMemo",12:"useCallback",13:"handler functions",14:"useEffect/useLayoutEffect",15:"return statement",99:"unknown"},C=new Set(["useState"]),y=new Set(["useRef"]),s=new Set(["useReducer"]),g=new Set(["useEffect","useLayoutEffect"]),i=new Set(["useMemo"]),r=new Set(["useCallback"]),l=new Set(["useSelector","useDispatch","useStore"]),o=new Set(["useNavigate","useLocation","useParams","useSearchParams","useRouter","usePathname","useMatch","useMatches","useRouteLoaderData","useNavigation","useResolvedPath","useHref","useInRouterContext","useNavigationType","useOutlet","useOutletContext","useRouteError","useRoutes","useBlocker"]),n=new Set(["useContext","useToast","useTheme","useAuth","useModal","useDialog","useNotification","useI18n","useTranslation","useIntl","useForm","useFormContext"]),h=k=>{if(!k)return!1;if(k.type==="JSXElement"||k.type==="JSXFragment")return!0;if(k.type==="BlockStatement"){for(let $ of k.body)if($.type==="ReturnStatement"&&$.argument&&h($.argument))return!0}return k.type==="ConditionalExpression"?h(k.consequent)||h(k.alternate):k.type==="LogicalExpression"?h(k.left)||h(k.right):k.type==="ParenthesizedExpression"?h(k.expression):!1},f=k=>{if(k.parent){if(k.parent.type==="VariableDeclarator"&&k.parent.id&&k.parent.id.type==="Identifier")return k.parent.id.name;if(k.id&&k.id.type==="Identifier")return k.id.name}return null},c=k=>{let $=f(k);if($&&/^[A-Z]/.test($)){let v=k.body;return h(v)}return!1},a=k=>{let $=f(k);return $&&/^use[A-Z]/.test($)?!(k.body.type!=="BlockStatement"||h(k.body)):!1},u=k=>k.type!=="CallExpression"?null:k.callee.type==="Identifier"?k.callee.name:k.callee.type==="MemberExpression"&&k.callee.property.type==="Identifier"?k.callee.property.name:null,b=k=>{let $=u(k);return $&&/^use[A-Z]/.test($)},x=k=>k&&(k.type==="ArrowFunctionExpression"||k.type==="FunctionExpression"),T=k=>{if(k.type==="VariableDeclaration"){let $=k.declarations[0];if($&&$.init&&x($.init))return $.init.type!=="CallExpression"}return k.type==="FunctionDeclaration"},m=(k,$=new Set)=>{if(k.type==="ReturnStatement")return t.RETURN;if(k.type==="ExpressionStatement"&&k.expression.type==="CallExpression"){let v=u(k.expression);if(v){if(g.has(v))return t.EFFECT;if(b(k.expression))return t.CUSTOM_HOOK}return t.UNKNOWN}if(k.type==="VariableDeclaration"){let v=k.declarations;for(let p of v)if(p.init){if(p.init.type==="CallExpression"){let d=u(p.init);if(d){if(C.has(d))return t.STATE;if(y.has(d))return t.REF;if(s.has(d))return t.REDUCER;if(l.has(d))return t.SELECTOR_DISPATCH;if(o.has(d))return t.ROUTER_HOOK;if(n.has(d))return t.CONTEXT_HOOK;if(i.has(d))return t.MEMO;if(r.has(d))return t.CALLBACK;if(b(p.init))return t.CUSTOM_HOOK}}if(x(p.init))return t.HANDLER_FUNCTION}for(let p of v)if(p.id.type==="ObjectPattern"&&p.init){if(p.init.type==="Identifier"&&$.has(p.init.name))return t.PROPS_DESTRUCTURE_BODY;if(p.init.type==="MemberExpression"){let d=p.init;for(;d.type==="MemberExpression";)d=d.object;if(d.type==="Identifier"&&$.has(d.name))return t.PROPS_DESTRUCTURE_BODY}if(p.init.type==="Identifier"&&p.init.name==="props")return t.PROPS_DESTRUCTURE}for(let p of v)if(p.init&&p.init.type==="CallExpression"){let d=p.init.callee;if(d&&d.type==="Identifier"&&!b(p.init))return t.HANDLER_FUNCTION}return t.DERIVED_STATE}return k.type==="FunctionDeclaration"?t.HANDLER_FUNCTION:t.UNKNOWN},E=(k,$)=>{let v=k.body,p=e.sourceCode||e.getSourceCode();if(v.type!=="BlockStatement")return;let d=v.body;if(d.length===0)return;let w=new Set;for(let B of k.params)if(B.type==="Identifier")w.add(B.name);else if(B.type==="ObjectPattern")for(let O of B.properties)O.type==="Property"&&O.value?O.value.type==="Identifier"?w.add(O.value.name):O.value.type==="AssignmentPattern"&&O.value.left.type==="Identifier"&&w.add(O.value.left.name):O.type==="RestElement"&&O.argument.type==="Identifier"&&w.add(O.argument.name);else if(B.type==="AssignmentPattern"&&B.left){if(B.left.type==="Identifier")w.add(B.left.name);else if(B.left.type==="ObjectPattern")for(let O of B.left.properties)O.type==="Property"&&O.value&&(O.value.type==="Identifier"?w.add(O.value.name):O.value.type==="AssignmentPattern"&&O.value.left.type==="Identifier"&&w.add(O.value.left.name))}let L=B=>B.type==="VariableDeclaration"||B.type==="FunctionDeclaration"||B.type==="ExpressionStatement"||B.type==="ReturnStatement",R=B=>{let O=new Set;if(B.type==="VariableDeclaration"){for(let X of B.declarations)if(X.id.type==="Identifier")O.add(X.id.name);else if(X.id.type==="ObjectPattern")for(let Z of X.id.properties)Z.type==="Property"&&Z.value.type==="Identifier"?O.add(Z.value.name):Z.type==="RestElement"&&Z.argument.type==="Identifier"&&O.add(Z.argument.name);else if(X.id.type==="ArrayPattern")for(let Z of X.id.elements)Z&&Z.type==="Identifier"&&O.add(Z.name)}else B.type==="FunctionDeclaration"&&B.id&&O.add(B.id.name);return O},P=(B,O=new Set)=>(B&&(B.type==="Identifier"?O.add(B.name):B.type==="MemberExpression"?P(B.object,O):B.type==="CallExpression"?(P(B.callee,O),B.arguments.forEach(X=>P(X,O))):B.type==="BinaryExpression"||B.type==="LogicalExpression"?(P(B.left,O),P(B.right,O)):B.type==="ConditionalExpression"?(P(B.test,O),P(B.consequent,O),P(B.alternate,O)):B.type==="UnaryExpression"?P(B.argument,O):B.type==="ArrayExpression"?B.elements.forEach(X=>P(X,O)):B.type==="ObjectExpression"?B.properties.forEach(X=>{X.type==="Property"&&P(X.value,O)}):B.type==="TemplateLiteral"?B.expressions.forEach(X=>P(X,O)):(B.type==="ChainExpression"||B.type==="TSAsExpression"||B.type==="TSNonNullExpression")&&P(B.expression,O)),O),H=B=>{let O=new Set;if(B.type==="VariableDeclaration")for(let X of B.declarations)X.init&&P(X.init,O);return O},F=d.filter(L);if(F.length<2)return;let M=new Map,j=new Map;for(let B=0;B<d.length;B++){let O=d[B],X=R(O);for(let Z of X)j.set(Z,B)}for(let B=0;B<d.length;B++){let O=d[B],X=R(O),Z=H(O),Q=L(O)?m(O,w):t.UNKNOWN;M.set(B,{category:Q,declared:X,dependencies:Z,index:B,statement:O})}let N=new Map;for(let B=0;B<d.length;B++){let O=M.get(B),X=new Set;for(let Z of O.dependencies){let Q=j.get(Z);Q!==void 0&&Q!==B&&X.add(Q)}N.set(B,X)}let D=!1,z=!1,q=0,_=null,Y=null,ne=null,J=null,V=null;for(let B of F){let O=m(B,w);O!==t.UNKNOWN&&(O<q&&!D&&(D=!0,_=B,Y=O,ne=q),q=O)}for(let B=0;B<d.length;B++){let O=N.get(B)||new Set;for(let X of O)if(X>B){z=!0,J=d[B];let Z=M.get(X);for(let Q of Z.declared)if(M.get(B).dependencies.has(Q)){V=Q;break}break}if(z)break}if(!D&&!z)return;let W=(()=>{let B=[],O=new Set,X=new Set,Z=K=>{if(O.has(K)||X.has(K))return;X.add(K);let re=N.get(K)||new Set;for(let ee of re)Z(ee);X.delete(K),O.add(K),B.push(K)},Q=new Map;for(let K=0;K<d.length;K++){let re=M.get(K),ee=re.category;if(ee===t.UNKNOWN){for(let oe=K+1;oe<d.length;oe++){let ue=M.get(oe);if(ue.category!==t.UNKNOWN){ee=ue.category;break}}ee===t.UNKNOWN&&(ee=t.RETURN)}let ae=N.get(K)||new Set,ce=ee;for(let oe of ae){let ge=M.get(oe).category;ge===t.UNKNOWN&&(ge=t.DERIVED_STATE),ge>ce&&(ce=ge)}let se=Math.max(ee,ce);Q.has(se)||Q.set(se,[]),Q.get(se).push({deps:ae,effectiveCategory:ee,index:K,originalCategory:re.category})}let he=[...Q.keys()].sort((K,re)=>K-re),xe=[];for(let K of he){let re=Q.get(K),ee=new Set,ae=[],ce=se=>{if(!ee.has(se.index)){ee.add(se.index);for(let oe of se.deps){let ue=re.find(ge=>ge.index===oe);ue&&!ee.has(oe)&&ce(ue)}ae.push(se.index)}};re.sort((se,oe)=>se.index-oe.index);for(let se of re)ce(se);xe.push(...ae)}return xe})();if(!W.some((B,O)=>B!==O))return;let le=B=>{let X=p.lines[d[0].loc.start.line-1].match(/^\s*/)[0],Z="",Q=null;for(let K=0;K<W.length;K++){let re=W[K],ee=M.get(re),ae=ee.category!==t.UNKNOWN?ee.category:null;Q!==null&&ae!==null&&ae!==Q&&(Z+=`
220
+ ${c})${x}`),message:"Multi-line JSX in object property must be wrapped in parentheses",node:s})}return}if(s.type==="ConditionalExpression"){let r=t.getText(s).replace(/\s*\n\s*/g," ").trim();if(s.loc.start.line!==s.loc.end.line&&r.length<=80){e.report({fix:h=>h.replaceText(s,r),message:"Short ternary expression should be on a single line",node:s});return}let o=t.getTokenAfter(s.test,h=>h.value==="?"),n=t.getTokenAfter(s.consequent,h=>h.value===":");if(o){let h=t.getTokenAfter(o);if(h&&o.loc.end.line<h.loc.start.line&&r.length<=80){e.report({fix:f=>f.replaceText(s,r),message:"Ternary operator '?' should not be at end of line",node:o});return}}if(n){let h=t.getTokenAfter(n);if(h&&n.loc.end.line<h.loc.start.line&&r.length<=80){e.report({fix:f=>f.replaceText(s,r),message:"Ternary operator ':' should not be at end of line",node:n});return}}return}if(s.loc.start.line>y.loc.end.line){if((s.type==="ObjectExpression"||s.type==="ArrayExpression")&&s.loc.start.line!==s.loc.end.line)return;let i=t.getTokenAfter(y);if(i&&i.value==="(")return;e.report({fix:r=>r.replaceTextRange([y.range[1],s.range[0]]," "),message:"Property value should be on the same line as the colon",node:s})}}}},meta:{docs:{description:"Enforce property value on same line as colon with proper spacing"},fixable:"whitespace",schema:[],type:"layout"}},Bt={create(e){let t=e.sourceCode||e.getSourceCode();return{Property(I){let{key:C}=I;if(C.type!=="Literal"||typeof C.value!="string")return;let y=C.value,s=y.trim();y!==s&&s.length>0&&e.report({fix:g=>g.replaceText(C,`"${s}"`),message:`String property key should not have extra spaces inside quotes: "${s}" not "${y}"`,node:C})}}},meta:{docs:{description:"Enforce no extra spaces inside string property keys"},fixable:"code",schema:[],type:"layout"}};var Ht={create(e){let t={CALLBACK:12,CONTEXT_HOOK:8,CUSTOM_HOOK:9,DERIVED_STATE:10,EFFECT:14,HANDLER_FUNCTION:13,MEMO:11,PROPS_DESTRUCTURE:1,PROPS_DESTRUCTURE_BODY:2,REDUCER:5,REF:3,RETURN:15,ROUTER_HOOK:7,SELECTOR_DISPATCH:6,STATE:4,UNKNOWN:99},I={1:"props destructure",2:"destructured variables from props",3:"useRef",4:"useState",5:"useReducer",6:"useSelector/useDispatch",7:"router hooks",8:"context hooks",9:"custom hooks",10:"derived state/computed variables",11:"useMemo",12:"useCallback",13:"handler functions",14:"useEffect/useLayoutEffect",15:"return statement",99:"unknown"},C=new Set(["useState"]),y=new Set(["useRef"]),s=new Set(["useReducer"]),g=new Set(["useEffect","useLayoutEffect"]),i=new Set(["useMemo"]),r=new Set(["useCallback"]),l=new Set(["useSelector","useDispatch","useStore"]),o=new Set(["useNavigate","useLocation","useParams","useSearchParams","useRouter","usePathname","useMatch","useMatches","useRouteLoaderData","useNavigation","useResolvedPath","useHref","useInRouterContext","useNavigationType","useOutlet","useOutletContext","useRouteError","useRoutes","useBlocker"]),n=new Set(["useContext","useToast","useTheme","useAuth","useModal","useDialog","useNotification","useI18n","useTranslation","useIntl","useForm","useFormContext"]),h=k=>{if(!k)return!1;if(k.type==="JSXElement"||k.type==="JSXFragment")return!0;if(k.type==="BlockStatement"){for(let $ of k.body)if($.type==="ReturnStatement"&&$.argument&&h($.argument))return!0}return k.type==="ConditionalExpression"?h(k.consequent)||h(k.alternate):k.type==="LogicalExpression"?h(k.left)||h(k.right):k.type==="ParenthesizedExpression"?h(k.expression):!1},f=k=>{if(k.parent){if(k.parent.type==="VariableDeclarator"&&k.parent.id&&k.parent.id.type==="Identifier")return k.parent.id.name;if(k.id&&k.id.type==="Identifier")return k.id.name}return null},c=k=>{let $=f(k);if($&&/^[A-Z]/.test($)){let v=k.body;return h(v)}return!1},a=k=>{let $=f(k);return $&&/^use[A-Z]/.test($)?!(k.body.type!=="BlockStatement"||h(k.body)):!1},u=k=>k.type!=="CallExpression"?null:k.callee.type==="Identifier"?k.callee.name:k.callee.type==="MemberExpression"&&k.callee.property.type==="Identifier"?k.callee.property.name:null,b=k=>{let $=u(k);return $&&/^use[A-Z]/.test($)},x=k=>k&&(k.type==="ArrowFunctionExpression"||k.type==="FunctionExpression"),T=k=>{if(k.type==="VariableDeclaration"){let $=k.declarations[0];if($&&$.init&&x($.init))return $.init.type!=="CallExpression"}return k.type==="FunctionDeclaration"},m=(k,$=new Set)=>{if(k.type==="ReturnStatement")return t.RETURN;if(k.type==="ExpressionStatement"&&k.expression.type==="CallExpression"){let v=u(k.expression);if(v){if(g.has(v))return t.EFFECT;if(b(k.expression))return t.CUSTOM_HOOK}return t.UNKNOWN}if(k.type==="VariableDeclaration"){let v=k.declarations;for(let p of v)if(p.init){if(p.init.type==="CallExpression"){let d=u(p.init);if(d){if(C.has(d))return t.STATE;if(y.has(d))return t.REF;if(s.has(d))return t.REDUCER;if(l.has(d))return t.SELECTOR_DISPATCH;if(o.has(d))return t.ROUTER_HOOK;if(n.has(d))return t.CONTEXT_HOOK;if(i.has(d))return t.MEMO;if(r.has(d))return t.CALLBACK;if(b(p.init))return t.CUSTOM_HOOK}}if(x(p.init))return t.HANDLER_FUNCTION}for(let p of v)if(p.id.type==="ObjectPattern"&&p.init){if(p.init.type==="Identifier"&&$.has(p.init.name))return t.PROPS_DESTRUCTURE_BODY;if(p.init.type==="MemberExpression"){let d=p.init;for(;d.type==="MemberExpression";)d=d.object;if(d.type==="Identifier"&&$.has(d.name))return t.PROPS_DESTRUCTURE_BODY}if(p.init.type==="Identifier"&&p.init.name==="props")return t.PROPS_DESTRUCTURE}for(let p of v)if(p.init&&p.init.type==="CallExpression"){let d=p.init.callee;if(d&&d.type==="Identifier"&&!b(p.init))return t.HANDLER_FUNCTION}return t.DERIVED_STATE}return k.type==="FunctionDeclaration"?t.HANDLER_FUNCTION:t.UNKNOWN},E=(k,$)=>{let v=k.body,p=e.sourceCode||e.getSourceCode();if(v.type!=="BlockStatement")return;let d=v.body;if(d.length===0)return;let w=new Set;for(let B of k.params)if(B.type==="Identifier")w.add(B.name);else if(B.type==="ObjectPattern")for(let O of B.properties)O.type==="Property"&&O.value?O.value.type==="Identifier"?w.add(O.value.name):O.value.type==="AssignmentPattern"&&O.value.left.type==="Identifier"&&w.add(O.value.left.name):O.type==="RestElement"&&O.argument.type==="Identifier"&&w.add(O.argument.name);else if(B.type==="AssignmentPattern"&&B.left){if(B.left.type==="Identifier")w.add(B.left.name);else if(B.left.type==="ObjectPattern")for(let O of B.left.properties)O.type==="Property"&&O.value&&(O.value.type==="Identifier"?w.add(O.value.name):O.value.type==="AssignmentPattern"&&O.value.left.type==="Identifier"&&w.add(O.value.left.name))}let L=B=>B.type==="VariableDeclaration"||B.type==="FunctionDeclaration"||B.type==="ExpressionStatement"||B.type==="ReturnStatement",R=B=>{let O=new Set;if(B.type==="VariableDeclaration"){for(let X of B.declarations)if(X.id.type==="Identifier")O.add(X.id.name);else if(X.id.type==="ObjectPattern")for(let Z of X.id.properties)Z.type==="Property"&&Z.value.type==="Identifier"?O.add(Z.value.name):Z.type==="RestElement"&&Z.argument.type==="Identifier"&&O.add(Z.argument.name);else if(X.id.type==="ArrayPattern")for(let Z of X.id.elements)Z&&Z.type==="Identifier"&&O.add(Z.name)}else B.type==="FunctionDeclaration"&&B.id&&O.add(B.id.name);return O},P=(B,O=new Set)=>(B&&(B.type==="Identifier"?O.add(B.name):B.type==="MemberExpression"?P(B.object,O):B.type==="CallExpression"?(P(B.callee,O),B.arguments.forEach(X=>P(X,O))):B.type==="BinaryExpression"||B.type==="LogicalExpression"?(P(B.left,O),P(B.right,O)):B.type==="ConditionalExpression"?(P(B.test,O),P(B.consequent,O),P(B.alternate,O)):B.type==="UnaryExpression"?P(B.argument,O):B.type==="ArrayExpression"?B.elements.forEach(X=>P(X,O)):B.type==="ObjectExpression"?B.properties.forEach(X=>{X.type==="Property"&&P(X.value,O)}):B.type==="TemplateLiteral"?B.expressions.forEach(X=>P(X,O)):(B.type==="ChainExpression"||B.type==="TSAsExpression"||B.type==="TSNonNullExpression")&&P(B.expression,O)),O),H=B=>{let O=new Set;if(B.type==="VariableDeclaration")for(let X of B.declarations)X.init&&P(X.init,O);return O},F=d.filter(L);if(F.length<2)return;let M=new Map,j=new Map;for(let B=0;B<d.length;B++){let O=d[B],X=R(O);for(let Z of X)j.set(Z,B)}for(let B=0;B<d.length;B++){let O=d[B],X=R(O),Z=H(O),Q=L(O)?m(O,w):t.UNKNOWN;M.set(B,{category:Q,declared:X,dependencies:Z,index:B,statement:O})}let N=new Map;for(let B=0;B<d.length;B++){let O=M.get(B),X=new Set;for(let Z of O.dependencies){let Q=j.get(Z);Q!==void 0&&Q!==B&&X.add(Q)}N.set(B,X)}let D=!1,z=!1,q=0,_=null,Y=null,ne=null,J=null,U=null;for(let B of F){let O=m(B,w);O!==t.UNKNOWN&&(O<q&&!D&&(D=!0,_=B,Y=O,ne=q),q=O)}for(let B=0;B<d.length;B++){let O=N.get(B)||new Set;for(let X of O)if(X>B){z=!0,J=d[B];let Z=M.get(X);for(let Q of Z.declared)if(M.get(B).dependencies.has(Q)){U=Q;break}break}if(z)break}if(!D&&!z)return;let W=(()=>{let B=[],O=new Set,X=new Set,Z=K=>{if(O.has(K)||X.has(K))return;X.add(K);let re=N.get(K)||new Set;for(let ee of re)Z(ee);X.delete(K),O.add(K),B.push(K)},Q=new Map;for(let K=0;K<d.length;K++){let re=M.get(K),ee=re.category;if(ee===t.UNKNOWN){for(let oe=K+1;oe<d.length;oe++){let ue=M.get(oe);if(ue.category!==t.UNKNOWN){ee=ue.category;break}}ee===t.UNKNOWN&&(ee=t.RETURN)}let ae=N.get(K)||new Set,ce=ee;for(let oe of ae){let ge=M.get(oe).category;ge===t.UNKNOWN&&(ge=t.DERIVED_STATE),ge>ce&&(ce=ge)}let se=Math.max(ee,ce);Q.has(se)||Q.set(se,[]),Q.get(se).push({deps:ae,effectiveCategory:ee,index:K,originalCategory:re.category})}let he=[...Q.keys()].sort((K,re)=>K-re),xe=[];for(let K of he){let re=Q.get(K),ee=new Set,ae=[],ce=se=>{if(!ee.has(se.index)){ee.add(se.index);for(let oe of se.deps){let ue=re.find(ge=>ge.index===oe);ue&&!ee.has(oe)&&ce(ue)}ae.push(se.index)}};re.sort((se,oe)=>se.index-oe.index);for(let se of re)ce(se);xe.push(...ae)}return xe})();if(!W.some((B,O)=>B!==O))return;let le=B=>{let X=p.lines[d[0].loc.start.line-1].match(/^\s*/)[0],Z="",Q=null;for(let K=0;K<W.length;K++){let re=W[K],ee=M.get(re),ae=ee.category!==t.UNKNOWN?ee.category:null;Q!==null&&ae!==null&&ae!==Q&&(Z+=`
221
221
  `);let ce=p.getText(ee.statement);Z+=X+ce.trim()+`
222
- `,ae!==null&&(Q=ae)}let he=d[0],xe=d[d.length-1];return B.replaceTextRange([he.range[0],xe.range[1]],Z.trimEnd())};z&&J?e.report({data:{type:$?"hook":"component",varName:V||"variable"},fix:le,message:'"{{varName}}" is used before it is declared. Reorder statements so dependencies are declared first in {{type}}',node:J}):D&&_&&e.report({data:{current:I[Y],previous:I[ne],type:$?"hook":"component"},fix:le,message:'"{{current}}" should come before "{{previous}}" in {{type}}. Order: refs \u2192 state \u2192 redux \u2192 router \u2192 context \u2192 custom hooks \u2192 derived \u2192 useMemo \u2192 useCallback \u2192 handlers \u2192 useEffect \u2192 return',node:_})},A=(k,$)=>{let v=e.sourceCode||e.getSourceCode(),p=k;for(;p.parent;)p=p.parent;if(p.type!=="Program")return;let d=k.body;if(d.type!=="BlockStatement")return;let w=f(k);for(let L of p.body)if(L.type==="VariableDeclaration")for(let R of L.declarations){if(!R.init||!R.id||R.id.type!=="Identifier")continue;let P=R.id.name;if(!(R.init.type==="Literal"&&(typeof R.init.value=="number"||typeof R.init.value=="string"||typeof R.init.value=="boolean"))||/^[A-Z][A-Z0-9_]*$/.test(P))continue;let F=v.getText(k);if(new RegExp(`\\b${P}\\b`).test(F)){let j=N=>{let D=[],z=v.getText(R),q=L.kind;if(L.declarations.length===1){let V=v.getTokenAfter(L),U=L.range[1],W=v.text.slice(L.range[1],L.range[1]+2),G=W.startsWith(`
222
+ `,ae!==null&&(Q=ae)}let he=d[0],xe=d[d.length-1];return B.replaceTextRange([he.range[0],xe.range[1]],Z.trimEnd())};z&&J?e.report({data:{type:$?"hook":"component",varName:U||"variable"},fix:le,message:'"{{varName}}" is used before it is declared. Reorder statements so dependencies are declared first in {{type}}',node:J}):D&&_&&e.report({data:{current:I[Y],previous:I[ne],type:$?"hook":"component"},fix:le,message:'"{{current}}" should come before "{{previous}}" in {{type}}. Order: refs \u2192 state \u2192 redux \u2192 router \u2192 context \u2192 custom hooks \u2192 derived \u2192 useMemo \u2192 useCallback \u2192 handlers \u2192 useEffect \u2192 return',node:_})},A=(k,$)=>{let v=e.sourceCode||e.getSourceCode(),p=k;for(;p.parent;)p=p.parent;if(p.type!=="Program")return;let d=k.body;if(d.type!=="BlockStatement")return;let w=f(k);for(let L of p.body)if(L.type==="VariableDeclaration")for(let R of L.declarations){if(!R.init||!R.id||R.id.type!=="Identifier")continue;let P=R.id.name;if(!(R.init.type==="Literal"&&(typeof R.init.value=="number"||typeof R.init.value=="string"||typeof R.init.value=="boolean"))||/^[A-Z][A-Z0-9_]*$/.test(P))continue;let F=v.getText(k);if(new RegExp(`\\b${P}\\b`).test(F)){let j=N=>{let D=[],z=v.getText(R),q=L.kind;if(L.declarations.length===1){let U=v.getTokenAfter(L),V=L.range[1],W=v.text.slice(L.range[1],L.range[1]+2),G=W.startsWith(`
223
223
  `)?L.range[1]+1:W.startsWith(`\r
224
- `)?L.range[1]+2:L.range[1];D.push(N.removeRange([L.range[0],G]))}else{let V=L.declarations.indexOf(R);if(V===L.declarations.length-1){let W=L.declarations[V-1];D.push(N.removeRange([W.range[1],R.range[1]]))}else{let W=L.declarations[V+1];D.push(N.removeRange([R.range[0],W.range[0]]))}}let _=d.body,Y=" ";_.length>0&&(Y=v.lines[_[0].loc.start.line-1].match(/^\s*/)[0]);let ne=0;for(let V=0;V<_.length;V++){let U=_[V];if(U.type==="VariableDeclaration"){let W=U.declarations[0];if(W&&W.init){if(W.init.type==="CallExpression"){let G=W.init.callee,le=G.type==="Identifier"?G.name:G.type==="MemberExpression"&&G.property.type==="Identifier"?G.property.name:"";if(/^use[A-Z]/.test(le)){ne=V+1;continue}}if(W.init.type==="ArrowFunctionExpression"||W.init.type==="FunctionExpression")break;ne=V+1}}else if(U.type==="FunctionDeclaration")break}let J=`${Y}${q} ${z};
224
+ `)?L.range[1]+2:L.range[1];D.push(N.removeRange([L.range[0],G]))}else{let U=L.declarations.indexOf(R);if(U===L.declarations.length-1){let W=L.declarations[U-1];D.push(N.removeRange([W.range[1],R.range[1]]))}else{let W=L.declarations[U+1];D.push(N.removeRange([R.range[0],W.range[0]]))}}let _=d.body,Y=" ";_.length>0&&(Y=v.lines[_[0].loc.start.line-1].match(/^\s*/)[0]);let ne=0;for(let U=0;U<_.length;U++){let V=_[U];if(V.type==="VariableDeclaration"){let W=V.declarations[0];if(W&&W.init){if(W.init.type==="CallExpression"){let G=W.init.callee,le=G.type==="Identifier"?G.name:G.type==="MemberExpression"&&G.property.type==="Identifier"?G.property.name:"";if(/^use[A-Z]/.test(le)){ne=U+1;continue}}if(W.init.type==="ArrowFunctionExpression"||W.init.type==="FunctionExpression")break;ne=U+1}}else if(V.type==="FunctionDeclaration")break}let J=`${Y}${q} ${z};
225
225
 
226
226
  `;return ne===0&&_.length>0?D.push(N.insertTextBefore(_[0],J)):ne<_.length?D.push(N.insertTextBefore(_[ne],J)):_.length>0&&D.push(N.insertTextAfter(_[_.length-1],`
227
227
 
@@ -270,7 +270,7 @@ ${h})`;e.report({fix:u=>u.replaceTextRange([g.range[0],i.range[1]],a),message:"F
270
270
  `);return T.replaceTextRange([x.range[1],a.range[0]],E)},message:"No empty lines allowed between enum members",node:a})}}),i.length>1){let a=t.getText(f),u=a.trimEnd(),b=t.getTokenAfter(f),x=u.endsWith(",")||b&&b.value===",",T=u.endsWith(";"),m=n&&n.loc.start.line===f.loc.end.line;if(T){let E=a.lastIndexOf(";"),A=f.range[0]+E;m?e.report({fix:S=>S.replaceTextRange([A,n.range[0]],`,
271
271
  `+l),message:"Last enum member must end with comma and closing brace must be on its own line",node:f}):e.report({fix:S=>S.replaceTextRange([A,A+1],","),message:"Enum members must end with comma (,) not semicolon (;)",node:f})}else!x&&m?e.report({fix:E=>E.replaceTextRange([f.range[1],n.range[0]],`,
272
272
  `+l),message:"Last enum member must have trailing comma and closing brace must be on its own line",node:f}):x?m&&e.report({fix:E=>E.replaceTextRange([f.range[1],n.range[0]],`
273
- `+l),message:"Closing brace must be on its own line",node:n}):e.report({fix:E=>E.insertTextAfter(f,","),message:"Last enum member must have trailing comma",node:f})}}}},meta:{docs:{description:"Enforce enum naming (PascalCase + Enum suffix), UPPER_CASE members, proper formatting, and trailing commas"},fixable:"code",schema:[],type:"suggestion"}},Ut={create(e){let t=e.sourceCode||e.getSourceCode(),I=/^[A-Z][a-zA-Z0-9]*$/,C=/^[a-z][a-zA-Z0-9]*$/,y=s=>/^[A-Z][A-Z0-9_]*$/.test(s)?s.toLowerCase().replace(/_([a-z0-9])/g,(g,i)=>i.toUpperCase()):/_/.test(s)?s.toLowerCase().replace(/_([a-z0-9])/g,(g,i)=>i.toUpperCase()):/^[A-Z]/.test(s)?s[0].toLowerCase()+s.slice(1):s;return{TSInterfaceDeclaration(s){let g=s.id.name;I.test(g)?g.endsWith("Interface")||e.report({fix(a){return a.replaceText(s.id,`${g}Interface`)},message:`Interface name "${g}" must end with "Interface" suffix. Use "${g}Interface" instead of "${g}"`,node:s.id}):e.report({message:`Interface name "${g}" must be PascalCase`,node:s.id});let i=t.getFirstToken(s.body);i&&i.loc.start.line!==s.id.loc.end.line&&e.report({fix:a=>a.replaceTextRange([s.id.range[1],i.range[0]]," "),message:"Opening brace must be on the same line as interface name",node:i});let r=s.body.body;if(r.length===0)return;let o=t.lines[s.loc.start.line-1].match(/^\s*/)[0],n=o+" ",h=t.getLastToken(s.body),f=r[0];f.loc.start.line-i.loc.end.line>1&&e.report({fix:a=>a.replaceTextRange([i.range[1],f.range[0]],`
273
+ `+l),message:"Closing brace must be on its own line",node:n}):e.report({fix:E=>E.insertTextAfter(f,","),message:"Last enum member must have trailing comma",node:f})}}}},meta:{docs:{description:"Enforce enum naming (PascalCase + Enum suffix), UPPER_CASE members, proper formatting, and trailing commas"},fixable:"code",schema:[],type:"suggestion"}},Vt={create(e){let t=e.sourceCode||e.getSourceCode(),I=/^[A-Z][a-zA-Z0-9]*$/,C=/^[a-z][a-zA-Z0-9]*$/,y=s=>/^[A-Z][A-Z0-9_]*$/.test(s)?s.toLowerCase().replace(/_([a-z0-9])/g,(g,i)=>i.toUpperCase()):/_/.test(s)?s.toLowerCase().replace(/_([a-z0-9])/g,(g,i)=>i.toUpperCase()):/^[A-Z]/.test(s)?s[0].toLowerCase()+s.slice(1):s;return{TSInterfaceDeclaration(s){let g=s.id.name;I.test(g)?g.endsWith("Interface")||e.report({fix(a){return a.replaceText(s.id,`${g}Interface`)},message:`Interface name "${g}" must end with "Interface" suffix. Use "${g}Interface" instead of "${g}"`,node:s.id}):e.report({message:`Interface name "${g}" must be PascalCase`,node:s.id});let i=t.getFirstToken(s.body);i&&i.loc.start.line!==s.id.loc.end.line&&e.report({fix:a=>a.replaceTextRange([s.id.range[1],i.range[0]]," "),message:"Opening brace must be on the same line as interface name",node:i});let r=s.body.body;if(r.length===0)return;let o=t.lines[s.loc.start.line-1].match(/^\s*/)[0],n=o+" ",h=t.getLastToken(s.body),f=r[0];f.loc.start.line-i.loc.end.line>1&&e.report({fix:a=>a.replaceTextRange([i.range[1],f.range[0]],`
274
274
  `+n),message:"No empty line after opening brace in interface",node:f});let c=r[r.length-1];if(h.loc.start.line-c.loc.end.line>1&&e.report({fix:a=>a.replaceTextRange([c.range[1],h.range[0]],`
275
275
  `+o),message:"No empty line before closing brace in interface",node:c}),r.length===1){let a=r[0],u=i.loc.end.line!==h.loc.start.line,b=a.typeAnnotation?.typeAnnotation,x=b?.type==="TSTypeLiteral",T=x&&b.members?.length>=2,m=x&&b.members?.length===1,E=b?.type==="TSFunctionType"&&b.loc.start.line!==b.loc.end.line;if(u&&!T&&!E){let S;if(m){let $=b.members[0],v=t.getText($).trim();(v.endsWith(",")||v.endsWith(";"))&&(v=v.slice(0,-1));let p=a.key.name,d=a.optional?"?":"";S=`${p}${d}: { ${v} }`}else S=t.getText(a).trim(),(S.endsWith(",")||S.endsWith(";"))&&(S=S.slice(0,-1));let k=`{ ${S} }`;e.report({fix:$=>$.replaceTextRange([i.range[0],h.range[1]],k),message:"Single property interface should be on one line without trailing punctuation",node:s});return}let A=t.getText(a);if(A.trimEnd().endsWith(",")||A.trimEnd().endsWith(";")){let S=Math.max(A.lastIndexOf(","),A.lastIndexOf(";"));e.report({fix:k=>k.removeRange([a.range[0]+S,a.range[0]+S+1]),message:"Single property interface should not have trailing punctuation",node:a})}return}if(f.loc.start.line===i.loc.end.line&&e.report({fix:a=>a.replaceTextRange([i.range[1],f.range[0]],`
276
276
  `+n),message:"First interface property must be on a new line when there are multiple properties",node:f}),r.forEach((a,u)=>{if(a.type==="TSPropertySignature"&&a.key&&a.key.type==="Identifier"){let x=a.key.name;if(!C.test(x)){let T=y(x);e.report({fix:m=>m.replaceText(a.key,T),message:`Interface property "${x}" must be camelCase. Use "${T}" instead.`,node:a.key})}}if(a.type==="TSPropertySignature"&&a.typeAnnotation?.typeAnnotation?.type==="TSTypeLiteral"){let x=a.typeAnnotation.typeAnnotation;if(x.members&&x.members.length===1){let T=t.getFirstToken(x),m=t.getLastToken(x);if(T.loc.end.line!==m.loc.start.line){let A=x.members[0],S=t.getText(A).trim();(S.endsWith(",")||S.endsWith(";"))&&(S=S.slice(0,-1)),e.report({fix:k=>k.replaceTextRange([T.range[0],m.range[1]],`{ ${S} }`),message:"Single property nested object type should be on one line",node:x})}}}if(a.type==="TSPropertySignature"&&a.optional){let x=t.getFirstToken(a),T=t.getTokenAfter(x);T&&T.value==="?"&&t.getText().slice(x.range[1],T.range[0])!==""&&e.report({fix:E=>E.replaceTextRange([x.range[1],T.range[0]],""),message:'No space allowed before "?" in optional property',node:a})}if(!(u===r.length-1)||r.length===1){let x=t.getText(a);x.trimEnd().endsWith(";")&&e.report({fix(T){let m=x.lastIndexOf(";"),E=a.range[0]+m;return T.replaceTextRange([E,E+1],",")},message:"Interface properties must end with comma (,) not semicolon (;)",node:a})}if(r.length>1&&u>0){let x=r[u-1];a.loc.start.line===x.loc.end.line&&e.report({fix:T=>{let m=t.getTokenAfter(x);for(;m&&m.value!==","&&m.range[0]<a.range[0];)m=t.getTokenAfter(m);let E=m&&m.value===","?m.range[1]:x.range[1];return T.replaceTextRange([E,a.range[0]],`
@@ -278,4 +278,4 @@ ${h})`;e.report({fix:u=>u.replaceTextRange([g.range[0],i.range[1]],a),message:"F
278
278
  `);return T.replaceTextRange([x.range[1],a.range[0]],E)},message:"No empty lines allowed between interface properties",node:a})}}),r.length>1){let a=t.getText(c),u=a.trimEnd(),b=t.getTokenAfter(c),x=u.endsWith(",")||b&&b.value===",",T=u.endsWith(";"),m=h.loc.start.line===c.loc.end.line;if(T){let E=a.lastIndexOf(";"),A=c.range[0]+E;m?e.report({fix:S=>S.replaceTextRange([A,h.range[0]],`,
279
279
  `+o),message:"Last interface property must end with comma and closing brace must be on its own line",node:c}):e.report({fix:S=>S.replaceTextRange([A,A+1],","),message:"Interface properties must end with comma (,) not semicolon (;)",node:c})}else!x&&m?e.report({fix:E=>E.replaceTextRange([c.range[1],h.range[0]],`,
280
280
  `+o),message:"Last interface property must have trailing comma and closing brace must be on its own line",node:c}):x?m&&e.report({fix:E=>E.replaceTextRange([c.range[1],h.range[0]],`
281
- `+o),message:"Closing brace must be on its own line",node:h}):e.report({fix:E=>E.insertTextAfter(c,","),message:"Last interface property must have trailing comma",node:c})}}}},meta:{docs:{description:"Enforce interface naming (PascalCase + Interface suffix), camelCase properties, proper formatting, and trailing commas"},fixable:"code",schema:[],type:"suggestion"}},Vt={create(e){let I=(e.filename||e.getFilename()).replace(/\\/g,"/"),C=s=>new RegExp(`/${s}/[^/]+\\.(ts|tsx)$`).test(I),y=()=>/\.(ts|tsx)$/.test(I);return{TSInterfaceDeclaration(s){y()&&(C("interfaces")||e.report({message:'Interfaces must be declared in files inside the "interfaces" folder',node:s.id||s}))},TSEnumDeclaration(s){y()&&(C("enums")||e.report({message:'Enums must be declared in files inside the "enums" folder',node:s.id||s}))},TSTypeAliasDeclaration(s){y()&&(C("types")||e.report({message:'Type aliases must be declared in files inside the "types" folder',node:s.id||s}))}}},meta:{docs:{description:"Enforce that interfaces are in interfaces folder, enums in enums folder, and types in types folder"},schema:[],type:"suggestion"}};var _t={create(e){let t=e.sourceCode||e.getSourceCode(),I=/^[a-z][a-zA-Z0-9]*$/,C=/^[A-Z][a-zA-Z0-9]*$/,y=/^use[A-Z][a-zA-Z0-9]*$/,s=/^[A-Z][A-Z0-9_]*$/,g=m=>/^[A-Z][A-Z0-9_]*$/.test(m)?m.toLowerCase().replace(/_([a-z0-9])/g,(E,A)=>A.toUpperCase()):/_/.test(m)?m.toLowerCase().replace(/_([a-z0-9])/g,(E,A)=>A.toUpperCase()):/^[A-Z]/.test(m)?m[0].toLowerCase()+m.slice(1):m,i=m=>{let A=(t.getScope?t.getScope(m):e.getScope()).variables.find(S=>S.name===m.name);return A?A.references.map(S=>S.identifier):[]},r=["ArrowFunctionExpression","CallExpression","FunctionDeclaration","FunctionExpression","Property","VariableDeclarator","JSXElement","JSXOpeningElement","ReturnStatement","SwitchCase","SwitchStatement","ObjectExpression","ObjectPattern","BlockStatement","IfStatement","Identifier","RestElement","AssignmentPattern","ArrayPattern","MemberExpression","JSXText","JSXAttribute","JSXExpressionContainer","Function","Object","Array","String","Number","Boolean","Symbol","BigInt","Date","RegExp","Error","Map","Set","WeakMap","WeakSet","Promise"],l=m=>{if(!m||m.type!=="CallExpression")return!1;let{callee:E}=m;if(E.type==="CallExpression"){let A=E.callee;if(A.type==="Identifier"&&A.name==="styled"||A.type==="MemberExpression"&&A.object.name==="styled")return!0}return!1},o=m=>{if(m.type!=="CallExpression")return!1;let{callee:E}=m;return E.type==="Identifier"&&E.name==="styled"},n=m=>{if(!m)return!1;if(m.type==="ArrowFunctionExpression"||m.type==="FunctionExpression")return!0;if(m.type==="CallExpression"&&m.callee){let E=m.callee.name||m.callee.property&&m.callee.property.name;return["memo","forwardRef","lazy","createContext"].includes(E)}return!1},h=m=>{if(!m.init)return!1;let E=m.id.name;if(/^[A-Z]/.test(E)&&n(m.init)||/^[A-Z]/.test(E)&&m.init.type==="MemberExpression"&&m.init.object.type==="Identifier"&&/^[A-Z]/.test(m.init.object.name))return!0;if(/^[A-Z]/.test(E)&&m.init.type==="ConditionalExpression"){let{consequent:A,alternate:S}=m.init,k=$=>$.type==="Identifier"&&/^[A-Z]/.test($.name)||$.type==="Literal"&&typeof $.value=="string"||$.type==="MemberExpression"&&$.object.type==="Identifier"&&/^[A-Z]/.test($.object.name);if(k(A)||k(S))return!0}return!1},f=m=>{if(!m.init)return!1;let E=m.id.name;return E.startsWith("use")&&/^use[A-Z]/.test(E)&&n(m.init)},c=["Icon","Component","FormComponent","Layout","Wrapper","Container","Provider"],a=(m,E)=>{if(m.type==="Identifier"){let A=m.name;if(A.startsWith("_")||s.test(A)||r.includes(A)||c.includes(A))return;I.test(A)||e.report({message:`${E} "${A}" should be camelCase`,node:m})}else m.type==="ObjectPattern"?m.properties.forEach(A=>{A.type==="Property"?a(A.value,E):A.type==="RestElement"&&a(A.argument,E)}):m.type==="ArrayPattern"?m.elements.forEach(A=>{A&&a(A,E)}):m.type==="AssignmentPattern"?a(m.left,E):m.type==="RestElement"&&a(m.argument,E)},u=m=>{if(m.id.type!=="Identifier"){a(m.id,"Variable");return}let E=m.id.name;if(l(m.init)){C.test(E)||e.report({message:`Styled component "${E}" should be PascalCase (e.g., StyledCard instead of styledCard)`,node:m.id});return}if(E.startsWith("_")||h(m))return;let A=["Component","Icon","Layout","Wrapper","Container","Provider","View","Screen","Page"];if(C.test(E)&&A.some(k=>E.endsWith(k)))return;if(f(m)){y.test(E)||e.report({message:`Hook "${E}" should start with "use" followed by PascalCase (e.g., useEventsList)`,node:m.id});return}if(!([/^[A-Z][a-zA-Z]*Data$/,/^[A-Z][a-zA-Z]*Config$/,/^Routes$/].some(k=>k.test(E))&&m.init&&(m.init.type==="ArrayExpression"||m.init.type==="ObjectExpression"||m.init.type==="CallExpression"))&&!I.test(E)){let k=g(E),$=i(m.id);e.report({fix:v=>{let p=[];return $.forEach(d=>{p.push(v.replaceText(d,k))}),p},message:`Variable "${E}" should be camelCase (e.g., ${k} instead of ${E})`,node:m.id})}},b=m=>{if(m.computed||m.key.type!=="Identifier")return;let E=m.key.name;if(!(E.startsWith("_")||r.includes(E))){if(m.value&&m.value.type==="Identifier"){let A=m.value.name;if(C.test(A)&&C.test(E))return}if(!c.includes(E)&&!E.startsWith("Mui")&&!I.test(E)){let A=g(E);e.report({fix:S=>S.replaceText(m.key,A),message:`Property "${E}" should be camelCase (e.g., ${A} instead of ${E})`,node:m.key})}}},x=m=>{m.params.forEach(E=>a(E,"Parameter"))};return{ArrowFunctionExpression:x,CallExpression:m=>{o(m)||m.arguments.forEach(E=>{if(E.type==="Identifier"){let A=E.name;if(A.startsWith("_")||s.test(A)||r.includes(A)||c.includes(A)||C.test(A))return;if(!I.test(A)){let S=g(A);e.report({fix(k){let $=t.getScope?t.getScope(E):e.getScope(),v=$.variables.find(w=>w.name===A)||$.upper&&$.upper.variables.find(w=>w.name===A);if(!v)return k.replaceText(E,S);let p=[],d=new Set;return v.references.forEach(w=>{let L=`${w.identifier.range[0]}-${w.identifier.range[1]}`;d.has(L)||(d.add(L),p.push(k.replaceText(w.identifier,S)))}),p},message:`Argument "${A}" should be camelCase (e.g., ${S} instead of ${A})`,node:E})}}})},FunctionDeclaration:x,FunctionExpression:x,Property:b,VariableDeclarator:u}},meta:{docs:{description:"Enforce naming conventions: camelCase for variables/properties/params/arguments, PascalCase for components, useXxx for hooks"},fixable:"code",schema:[],type:"suggestion"}};var Mn={meta:{name:"eslint-plugin-code-style",version:"2.0.13"},rules:{"array-callback-destructure":Se,"array-items-per-line":Ee,"array-objects-on-new-lines":we,"arrow-function-block-body":ve,"arrow-function-simple-jsx":Ce,"arrow-function-simplify":Ae,"curried-arrow-same-line":$e,"function-arguments-format":Le,"nested-call-closing-brackets":Ie,"no-empty-lines-in-function-calls":Re,"opening-brackets-same-line":Pe,"simple-call-single-line":Fe,"single-argument-on-one-line":Be,"comment-format":Oe,"component-props-destructure":Ne,"component-props-inline-type":De,"folder-based-naming-convention":Xe,"folder-structure-consistency":ze,"no-redundant-folder-suffix":We,"svg-icon-naming-convention":Je,"react-code-order":Ht,"block-statement-newlines":Ue,"empty-line-after-block":Ge,"if-else-spacing":_e,"if-statement-format":Ve,"logical-expression-multiline":Ke,"multiline-if-conditions":qe,"no-empty-lines-in-switch-cases":Ye,"ternary-condition-multiline":Ze,"class-method-definition-format":je,"class-naming-convention":He,"function-call-spacing":Qe,"function-declaration-style":et,"function-naming-convention":tt,"function-object-destructure":st,"function-params-per-line":nt,"no-empty-lines-in-function-params":rt,"hook-callback-format":it,"hook-deps-per-line":at,"use-state-naming-convention":ot,"absolute-imports-only":lt,"export-format":ct,"import-format":pt,"import-source-spacing":ft,"index-export-style":gt,"index-exports-only":mt,"inline-export-declaration":dt,"module-index-exports":ut,"classname-dynamic-at-end":St,"classname-multiline":Ct,"classname-no-extra-spaces":wt,"classname-order":vt,"jsx-children-on-new-line":yt,"jsx-closing-bracket-spacing":ht,"jsx-element-child-new-line":xt,"jsx-logical-expression-simplify":Tt,"jsx-parentheses-position":bt,"jsx-prop-naming-convention":kt,"jsx-simple-element-one-line":Et,"jsx-string-value-trim":At,"jsx-ternary-format":$t,"no-empty-lines-in-jsx":Lt,"no-empty-lines-in-objects":It,"object-property-per-line":Rt,"object-property-value-brace":Pt,"object-property-value-format":Ft,"string-property-spacing":Bt,"assignment-value-same-line":jt,"member-expression-bracket-spacing":Ot,"enum-format":Wt,"enum-type-enforcement":Nt,"interface-format":Ut,"no-inline-type-definitions":Jt,"prop-naming-convention":Dt,"type-annotation-spacing":zt,"type-format":Xt,"typescript-definition-location":Vt,"no-hardcoded-strings":Mt,"variable-naming-convention":_t}};export{Mn as default};
281
+ `+o),message:"Closing brace must be on its own line",node:h}):e.report({fix:E=>E.insertTextAfter(c,","),message:"Last interface property must have trailing comma",node:c})}}}},meta:{docs:{description:"Enforce interface naming (PascalCase + Interface suffix), camelCase properties, proper formatting, and trailing commas"},fixable:"code",schema:[],type:"suggestion"}},Ut={create(e){let I=(e.filename||e.getFilename()).replace(/\\/g,"/"),C=s=>new RegExp(`/${s}/[^/]+\\.(ts|tsx)$`).test(I),y=()=>/\.(ts|tsx)$/.test(I);return{TSInterfaceDeclaration(s){y()&&(C("interfaces")||e.report({message:'Interfaces must be declared in files inside the "interfaces" folder',node:s.id||s}))},TSEnumDeclaration(s){y()&&(C("enums")||e.report({message:'Enums must be declared in files inside the "enums" folder',node:s.id||s}))},TSTypeAliasDeclaration(s){y()&&(C("types")||e.report({message:'Type aliases must be declared in files inside the "types" folder',node:s.id||s}))}}},meta:{docs:{description:"Enforce that interfaces are in interfaces folder, enums in enums folder, and types in types folder"},schema:[],type:"suggestion"}};var _t={create(e){let t=e.sourceCode||e.getSourceCode(),I=/^[a-z][a-zA-Z0-9]*$/,C=/^[A-Z][a-zA-Z0-9]*$/,y=/^use[A-Z][a-zA-Z0-9]*$/,s=/^[A-Z][A-Z0-9_]*$/,g=m=>/^[A-Z][A-Z0-9_]*$/.test(m)?m.toLowerCase().replace(/_([a-z0-9])/g,(E,A)=>A.toUpperCase()):/_/.test(m)?m.toLowerCase().replace(/_([a-z0-9])/g,(E,A)=>A.toUpperCase()):/^[A-Z]/.test(m)?m[0].toLowerCase()+m.slice(1):m,i=m=>{let A=(t.getScope?t.getScope(m):e.getScope()).variables.find(S=>S.name===m.name);return A?A.references.map(S=>S.identifier):[]},r=["ArrowFunctionExpression","CallExpression","FunctionDeclaration","FunctionExpression","Property","VariableDeclarator","JSXElement","JSXOpeningElement","ReturnStatement","SwitchCase","SwitchStatement","ObjectExpression","ObjectPattern","BlockStatement","IfStatement","Identifier","RestElement","AssignmentPattern","ArrayPattern","MemberExpression","JSXText","JSXAttribute","JSXExpressionContainer","Function","Object","Array","String","Number","Boolean","Symbol","BigInt","Date","RegExp","Error","Map","Set","WeakMap","WeakSet","Promise"],l=m=>{if(!m||m.type!=="CallExpression")return!1;let{callee:E}=m;if(E.type==="CallExpression"){let A=E.callee;if(A.type==="Identifier"&&A.name==="styled"||A.type==="MemberExpression"&&A.object.name==="styled")return!0}return!1},o=m=>{if(m.type!=="CallExpression")return!1;let{callee:E}=m;return E.type==="Identifier"&&E.name==="styled"},n=m=>{if(!m)return!1;if(m.type==="ArrowFunctionExpression"||m.type==="FunctionExpression")return!0;if(m.type==="CallExpression"&&m.callee){let E=m.callee.name||m.callee.property&&m.callee.property.name;return["memo","forwardRef","lazy","createContext"].includes(E)}return!1},h=m=>{if(!m.init)return!1;let E=m.id.name;if(/^[A-Z]/.test(E)&&n(m.init)||/^[A-Z]/.test(E)&&m.init.type==="MemberExpression"&&m.init.object.type==="Identifier"&&/^[A-Z]/.test(m.init.object.name))return!0;if(/^[A-Z]/.test(E)&&m.init.type==="ConditionalExpression"){let{consequent:A,alternate:S}=m.init,k=$=>$.type==="Identifier"&&/^[A-Z]/.test($.name)||$.type==="Literal"&&typeof $.value=="string"||$.type==="MemberExpression"&&$.object.type==="Identifier"&&/^[A-Z]/.test($.object.name);if(k(A)||k(S))return!0}return!1},f=m=>{if(!m.init)return!1;let E=m.id.name;return E.startsWith("use")&&/^use[A-Z]/.test(E)&&n(m.init)},c=["Icon","Component","FormComponent","Layout","Wrapper","Container","Provider"],a=(m,E)=>{if(m.type==="Identifier"){let A=m.name;if(A.startsWith("_")||s.test(A)||r.includes(A)||c.includes(A))return;I.test(A)||e.report({message:`${E} "${A}" should be camelCase`,node:m})}else m.type==="ObjectPattern"?m.properties.forEach(A=>{A.type==="Property"?a(A.value,E):A.type==="RestElement"&&a(A.argument,E)}):m.type==="ArrayPattern"?m.elements.forEach(A=>{A&&a(A,E)}):m.type==="AssignmentPattern"?a(m.left,E):m.type==="RestElement"&&a(m.argument,E)},u=m=>{if(m.id.type!=="Identifier"){a(m.id,"Variable");return}let E=m.id.name;if(l(m.init)){C.test(E)||e.report({message:`Styled component "${E}" should be PascalCase (e.g., StyledCard instead of styledCard)`,node:m.id});return}if(E.startsWith("_")||h(m))return;let A=["Component","Icon","Layout","Wrapper","Container","Provider","View","Screen","Page"];if(C.test(E)&&A.some(k=>E.endsWith(k)))return;if(f(m)){y.test(E)||e.report({message:`Hook "${E}" should start with "use" followed by PascalCase (e.g., useEventsList)`,node:m.id});return}if(!([/^[A-Z][a-zA-Z]*Data$/,/^[A-Z][a-zA-Z]*Config$/,/^Routes$/].some(k=>k.test(E))&&m.init&&(m.init.type==="ArrayExpression"||m.init.type==="ObjectExpression"||m.init.type==="CallExpression"))&&!I.test(E)){let k=g(E),$=i(m.id);e.report({fix:v=>{let p=[];return $.forEach(d=>{p.push(v.replaceText(d,k))}),p},message:`Variable "${E}" should be camelCase (e.g., ${k} instead of ${E})`,node:m.id})}},b=m=>{if(m.computed||m.key.type!=="Identifier")return;let E=m.key.name;if(!(E.startsWith("_")||r.includes(E))){if(m.value&&m.value.type==="Identifier"){let A=m.value.name;if(C.test(A)&&C.test(E))return}if(!c.includes(E)&&!E.startsWith("Mui")&&!I.test(E)){let A=g(E);e.report({fix:S=>S.replaceText(m.key,A),message:`Property "${E}" should be camelCase (e.g., ${A} instead of ${E})`,node:m.key})}}},x=m=>{m.params.forEach(E=>a(E,"Parameter"))};return{ArrowFunctionExpression:x,CallExpression:m=>{o(m)||m.arguments.forEach(E=>{if(E.type==="Identifier"){let A=E.name;if(A.startsWith("_")||s.test(A)||r.includes(A)||c.includes(A)||C.test(A))return;if(!I.test(A)){let S=g(A);e.report({fix(k){let $=t.getScope?t.getScope(E):e.getScope(),v=$.variables.find(w=>w.name===A)||$.upper&&$.upper.variables.find(w=>w.name===A);if(!v)return k.replaceText(E,S);let p=[],d=new Set;return v.references.forEach(w=>{let L=`${w.identifier.range[0]}-${w.identifier.range[1]}`;d.has(L)||(d.add(L),p.push(k.replaceText(w.identifier,S)))}),p},message:`Argument "${A}" should be camelCase (e.g., ${S} instead of ${A})`,node:E})}}})},FunctionDeclaration:x,FunctionExpression:x,Property:b,VariableDeclarator:u}},meta:{docs:{description:"Enforce naming conventions: camelCase for variables/properties/params/arguments, PascalCase for components, useXxx for hooks"},fixable:"code",schema:[],type:"suggestion"}};var Mn={meta:{name:"eslint-plugin-code-style",version:"2.0.15"},rules:{"array-callback-destructure":Se,"array-items-per-line":Ee,"array-objects-on-new-lines":we,"arrow-function-block-body":ve,"arrow-function-simple-jsx":Ce,"arrow-function-simplify":Ae,"curried-arrow-same-line":$e,"function-arguments-format":Le,"nested-call-closing-brackets":Ie,"no-empty-lines-in-function-calls":Re,"opening-brackets-same-line":Pe,"simple-call-single-line":Fe,"single-argument-on-one-line":Be,"comment-format":Oe,"component-props-destructure":Ne,"component-props-inline-type":De,"folder-based-naming-convention":Xe,"folder-structure-consistency":ze,"no-redundant-folder-suffix":We,"svg-icon-naming-convention":Je,"react-code-order":Ht,"block-statement-newlines":Ve,"empty-line-after-block":Ge,"if-else-spacing":_e,"if-statement-format":Ue,"logical-expression-multiline":Ke,"multiline-if-conditions":qe,"no-empty-lines-in-switch-cases":Ye,"ternary-condition-multiline":Ze,"class-method-definition-format":je,"class-naming-convention":He,"function-call-spacing":Qe,"function-declaration-style":et,"function-naming-convention":tt,"function-object-destructure":st,"function-params-per-line":nt,"no-empty-lines-in-function-params":rt,"hook-callback-format":it,"hook-deps-per-line":at,"use-state-naming-convention":ot,"absolute-imports-only":lt,"export-format":ct,"import-format":pt,"import-source-spacing":ft,"index-export-style":gt,"index-exports-only":mt,"inline-export-declaration":dt,"module-index-exports":ut,"classname-dynamic-at-end":St,"classname-multiline":Ct,"classname-no-extra-spaces":wt,"classname-order":vt,"jsx-children-on-new-line":yt,"jsx-closing-bracket-spacing":ht,"jsx-element-child-new-line":xt,"jsx-logical-expression-simplify":Tt,"jsx-parentheses-position":bt,"jsx-prop-naming-convention":kt,"jsx-simple-element-one-line":Et,"jsx-string-value-trim":At,"jsx-ternary-format":$t,"no-empty-lines-in-jsx":Lt,"no-empty-lines-in-objects":It,"object-property-per-line":Rt,"object-property-value-brace":Pt,"object-property-value-format":Ft,"string-property-spacing":Bt,"assignment-value-same-line":jt,"member-expression-bracket-spacing":Ot,"enum-format":Wt,"enum-type-enforcement":Nt,"interface-format":Vt,"no-inline-type-definitions":Jt,"prop-naming-convention":Dt,"type-annotation-spacing":zt,"type-format":Xt,"typescript-definition-location":Ut,"no-hardcoded-strings":Mt,"variable-naming-convention":_t}};export{Mn as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-code-style",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "description": "A custom ESLint plugin for enforcing consistent code formatting and style rules in React/JSX projects",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",