pickier 0.1.71 → 0.1.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +2 -2
- package/dist/{chunk-c82emw32.js → chunk-0rxvmb2a.js} +2 -2
- package/dist/chunk-2ja6xfzf.js +2 -0
- package/dist/chunk-3d4jgaj2.js +2 -0
- package/dist/{chunk-wx92kdf9.js → chunk-513cs23x.js} +5 -5
- package/dist/chunk-7ydmmwjq.js +2 -0
- package/dist/chunk-96vhwdwy.js +3 -0
- package/dist/chunk-d1qeak2x.js +3 -0
- package/dist/chunk-dnn0da5m.js +124 -0
- package/dist/chunk-fn87cp4c.js +2 -0
- package/dist/{chunk-5c026tb4.js → chunk-kn5s3eh8.js} +1 -1
- package/dist/{chunk-8m82hwdv.js → chunk-qq03kpe0.js} +2 -2
- package/dist/{chunk-99jrtc0c.js → chunk-ra9jn7j5.js} +2 -2
- package/dist/chunk-rx0b7k57.js +29 -0
- package/dist/{chunk-qjzzx1m2.js → chunk-t0w79bj5.js} +25 -25
- package/dist/chunk-wz6hqyhd.js +2 -0
- package/dist/native/darwin-arm64/pickier-native +0 -0
- package/dist/native/darwin-x64/pickier-native +0 -0
- package/dist/native/linux-arm64/pickier-native +0 -0
- package/dist/native/linux-x64/pickier-native +0 -0
- package/dist/native/win32-arm64/pickier-native.exe +0 -0
- package/dist/native/win32-x64/pickier-native.exe +0 -0
- package/dist/src/index.js +1 -1
- package/dist/src/lint-worker.js +1 -1
- package/dist/src/parallel.d.ts +4 -0
- package/dist/src/rules/general/prefer-template.d.ts +12 -0
- package/package.json +1 -1
- package/dist/chunk-0b2yx624.js +0 -3
- package/dist/chunk-1jtr81zg.js +0 -25
- package/dist/chunk-3h389bm4.js +0 -2
- package/dist/chunk-6vptsmta.js +0 -128
- package/dist/chunk-gpfjzx90.js +0 -2
- package/dist/chunk-jerw13hn.js +0 -2
- package/dist/chunk-m9ym248d.js +0 -2
- package/dist/chunk-vrbz87a8.js +0 -3
- package/dist/chunk-xgm5reee.js +0 -2
package/dist/bin/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
async function
|
|
4
|
-
`)}),r.version(
|
|
3
|
+
async function I(){let i=process.argv.slice(2),a=i[0]??"",h=a==="run",v=h||a==="lint"||a==="format"?1:0,c=h?"auto":a==="format"?"format":"lint",f=!1,m=!1,x=!1,w=!1,k,b,u=!1,d,p=[],y=!i.some((e)=>e==="version"||e==="help"||e==="--version"||e==="-v"||e==="--help"||e==="-h");for(let e=v;e<i.length;e++){let t=i[e];if(t==="--mode")c=i[++e]||"auto";else if(t==="--format")x=!0,c="format";else if(t==="--check")f=!0;else if(t==="--write")m=!0;else if(t==="--config")k=i[++e];else if(t==="--verbose")w=!0;else if(t==="--ext")b=i[++e];else if(t==="--ignore-path")e++;else if(t==="--cache")u=!0;else if(t==="--reporter"){let o=i[++e];d=o==="json"||o==="compact"?o:"stylish"}else if(t==="--fix"||t==="--dry-run"||t==="--max-warnings"){y=!1,p.length=0;break}else if(t.startsWith("--"));else p.push(t)}if(x&&!f)m=!0;if(y&&(c==="format"||c==="auto"||c==="lint")&&p.length>0){let{runUnified:e}=await import("../chunk-3d4jgaj2.js"),t=await e(p,{mode:c,check:f,write:m,verbose:w,config:k,ext:b,...u&&{cache:u},...d&&{reporter:d}});process.exit(t)}let{CLI:C}=await import("../chunk-p0j2ra3t.js"),{version:U}=await import("../chunk-7ydmmwjq.js"),r=new C("pickier"),l=(e)=>{let[t,o]=e;return[Array.isArray(t)?t.filter((g)=>typeof g==="string"):[],o&&typeof o==="object"?o:{}]};r.command("[...globs]","Lint files (default)").option("--fix","Auto-fix lint problems").option("--format","Format files instead of linting").option("--dry-run","Simulate fixes without writing").option("--check","Check formatting without writing (CI-friendly)").option("--max-warnings <n>","Max warnings before non-zero exit",{default:-1}).option("--reporter <name>","stylish|json|compact",{default:"stylish"}).option("--config <path>","Path to pickier config").option("--ignore-path <file>","Ignore file (like .gitignore)").option("--ext <exts>","Comma-separated extensions").option("--cache","Enable cache").option("--verbose","Verbose output").example("pickier .").example("pickier . --fix").example("pickier . --format").example("pickier src --fix --verbose").action(async(...e)=>{let[t,o]=l(e);if(t.length===0){r.outputHelp();return}let{runUnified:s}=await import("../chunk-3d4jgaj2.js"),n;if(o.format){if(n="format",!o.check)o.write=!0}else n="lint";let g=await s(t,{...o,mode:n});process.exit(g)}),r.command("lint [...globs]","[DEPRECATION] Use `pickier [...globs]` instead. Lint files").option("--fix","Auto-fix problems").option("--dry-run","Simulate fixes without writing").option("--max-warnings <n>","Max warnings before non-zero exit",{default:-1}).option("--reporter <name>","stylish|json|compact",{default:"stylish"}).option("--config <path>","Path to pickier config").option("--ignore-path <file>","Ignore file (like .gitignore)").option("--ext <exts>","Comma-separated extensions").option("--cache","Enable cache").option("--verbose","Verbose output").example("pickier lint .").example("pickier lint src --fix").example('pickier lint "src/**/*.{ts,tsx}" --reporter json').action(async(...e)=>{let[t,o]=l(e),{runUnified:s}=await import("../chunk-3d4jgaj2.js"),n=await s(t,{...o,mode:"lint"});process.exit(n)}),r.command("format [...globs]","[DEPRECATION] Use `pickier [...globs] --format` instead. Format files").option("--write","Write changes to files").option("--check","Check without writing (CI-friendly)").option("--config <path>","Path to pickier config").option("--ignore-path <file>","Ignore file").option("--ext <exts>","Comma-separated extensions").option("--verbose","Verbose output").example("pickier format . --write").example("pickier format . --check").action(async(...e)=>{let[t,o]=l(e),{runUnified:s}=await import("../chunk-3d4jgaj2.js"),n=await s(t,{...o,mode:"format"});process.exit(n)}),r.command("run [...globs]","Unified mode (auto, lint, or format)").option("--mode <mode>","auto|lint|format",{default:"auto"}).option("--fix","Auto-fix problems (lint mode)").option("--dry-run","Simulate fixes without writing (lint mode)").option("--max-warnings <n>","Max warnings before non-zero exit (lint mode)",{default:-1}).option("--reporter <name>","stylish|json|compact (lint mode)",{default:"stylish"}).option("--write","Write changes to files (format mode)").option("--check","Check without writing (format mode)").option("--config <path>","Path to pickier config").option("--ignore-path <file>","Ignore file (like .gitignore)").option("--ext <exts>","Comma-separated extensions").option("--cache","Enable cache (lint mode)").option("--verbose","Verbose output").example("pickier run . --mode lint --fix").example("pickier run . --mode format --write").action(async(...e)=>{let[t,o]=l(e),{runUnified:s}=await import("../chunk-3d4jgaj2.js"),n=await s(t,o);process.exit(n)}),r.command("version","Show the version of the CLI").action(async()=>{let{version:e}=await import("../chunk-7ydmmwjq.js");process.stdout.write(`${e}
|
|
4
|
+
`)}),r.version(U),r.help(),r.parse()}I().catch((i)=>{let a=i instanceof Error?i.message:String(i);process.stderr.write(`pickier: ${a}
|
|
5
5
|
`),process.exit(1)});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
function a(o){let c=o.length,e=Array.from({length:c},(n,s)=>o[s]),t=0;while(t<c){let n=o[t];if(n==="#"&&(t===0||/\s/.test(o[t-1]))){while(t<c)e[t]=" ",t++;break}if(n==="$"&&o[t+1]==="'"){t+=2;while(t<c){if(o[t]==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}if(o[t]==="'"){t++;break}e[t]=" ",t++}continue}if(n==="$"&&o[t+1]==='"'){t++,t=r(o,t,e);continue}if(n==="$"&&o[t+1]==="{"){t+=2;let s=1;while(t<c&&s>0){let f=o[t];if(f==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}if(f==="'"){t++;while(t<c&&o[t]!=="'")e[t]=" ",t++;if(t<c)t++;continue}if(f==='"'){t=r(o,t,e);continue}if(f==="{"){s++,t++;continue}if(f==="}"){s--,t++;continue}e[t]=" ",t++}continue}if(n==="$"&&o[t+1]==="("&&o[t+2]==="("){t+=3;let s=2;while(t<c&&s>0){let f=o[t];if(f==="("){s++,t++;continue}if(f===")"){s--,t++;continue}e[t]=" ",t++}continue}if(n==="$"&&o[t+1]==="("){t+=2;let s=1;while(t<c&&s>0){let f=o[t];if(f==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}if(f==="'"){t++;while(t<c&&o[t]!=="'")e[t]=" ",t++;if(t<c)t++;continue}if(f==='"'){t=r(o,t,e);continue}if(f==="("){s++,t++;continue}if(f===")"){s--,t++;continue}e[t]=" ",t++}continue}if(n==="'"){t++;while(t<c&&o[t]!=="'")e[t]=" ",t++;if(t<c)t++;continue}if(n==='"'){t=r(o,t,e);continue}if(n==="`"){t++;while(t<c&&o[t]!=="`"){if(o[t]==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}e[t]=" ",t++}if(t<c)t++;continue}t++}return e.join("")}function r(o,c,e){let t=o.length,n=c+1;while(n<t){let s=o[n];if(s==="\\"&&n+1<t){e[n]=" ",e[n+1]=" ",n+=2;continue}if(s==='"')return n+1;if(s==="$"&&o[n+1]==="("&&o[n+2]==="("){n+=3;let f=2;while(n<t&&f>0){let u=o[n];if(u==="("){f++,n++;continue}if(u===")"){f--,n++;continue}e[n]=" ",n++}continue}if(s==="$"&&o[n+1]==="("){n+=2;let f=1;while(n<t&&f>0){let u=o[n];if(u==="\\"&&n+1<t){e[n]=" ",e[n+1]=" ",n+=2;continue}if(u==="'"){n++;while(n<t&&o[n]!=="'")e[n]=" ",n++;if(n<t)n++;continue}if(u==='"'){n=r(o,n,e);continue}if(u==="("){f++,n++;continue}if(u===")"){f--,n++;continue}e[n]=" ",n++}continue}if(s==="$"&&o[n+1]==="{"){n+=2;let f=1;while(n<t&&f>0){let u=o[n];if(u==="{"){f++,n++;continue}if(u==="}"){f--,n++;continue}e[n]=" ",n++}continue}e[n]=" ",n++}return n}function i(o){let e=a(o).match(/<<-?/);if(!e||e.index===void 0)return null;let n=o.slice(e.index+e[0].length).match(/^\s*(['"]?)(\w+)\1/);if(!n)return null;return n[2]}class
|
|
3
|
-
export{a,i,
|
|
2
|
+
function a(o){let c=o.length,e=Array.from({length:c},(n,s)=>o[s]),t=0;while(t<c){let n=o[t];if(n==="#"&&(t===0||/\s/.test(o[t-1]))){while(t<c)e[t]=" ",t++;break}if(n==="$"&&o[t+1]==="'"){t+=2;while(t<c){if(o[t]==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}if(o[t]==="'"){t++;break}e[t]=" ",t++}continue}if(n==="$"&&o[t+1]==='"'){t++,t=r(o,t,e);continue}if(n==="$"&&o[t+1]==="{"){t+=2;let s=1;while(t<c&&s>0){let f=o[t];if(f==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}if(f==="'"){t++;while(t<c&&o[t]!=="'")e[t]=" ",t++;if(t<c)t++;continue}if(f==='"'){t=r(o,t,e);continue}if(f==="{"){s++,t++;continue}if(f==="}"){s--,t++;continue}e[t]=" ",t++}continue}if(n==="$"&&o[t+1]==="("&&o[t+2]==="("){t+=3;let s=2;while(t<c&&s>0){let f=o[t];if(f==="("){s++,t++;continue}if(f===")"){s--,t++;continue}e[t]=" ",t++}continue}if(n==="$"&&o[t+1]==="("){t+=2;let s=1;while(t<c&&s>0){let f=o[t];if(f==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}if(f==="'"){t++;while(t<c&&o[t]!=="'")e[t]=" ",t++;if(t<c)t++;continue}if(f==='"'){t=r(o,t,e);continue}if(f==="("){s++,t++;continue}if(f===")"){s--,t++;continue}e[t]=" ",t++}continue}if(n==="'"){t++;while(t<c&&o[t]!=="'")e[t]=" ",t++;if(t<c)t++;continue}if(n==='"'){t=r(o,t,e);continue}if(n==="`"){t++;while(t<c&&o[t]!=="`"){if(o[t]==="\\"&&t+1<c){e[t]=" ",e[t+1]=" ",t+=2;continue}e[t]=" ",t++}if(t<c)t++;continue}t++}return e.join("")}function r(o,c,e){let t=o.length,n=c+1;while(n<t){let s=o[n];if(s==="\\"&&n+1<t){e[n]=" ",e[n+1]=" ",n+=2;continue}if(s==='"')return n+1;if(s==="$"&&o[n+1]==="("&&o[n+2]==="("){n+=3;let f=2;while(n<t&&f>0){let u=o[n];if(u==="("){f++,n++;continue}if(u===")"){f--,n++;continue}e[n]=" ",n++}continue}if(s==="$"&&o[n+1]==="("){n+=2;let f=1;while(n<t&&f>0){let u=o[n];if(u==="\\"&&n+1<t){e[n]=" ",e[n+1]=" ",n+=2;continue}if(u==="'"){n++;while(n<t&&o[n]!=="'")e[n]=" ",n++;if(n<t)n++;continue}if(u==='"'){n=r(o,n,e);continue}if(u==="("){f++,n++;continue}if(u===")"){f--,n++;continue}e[n]=" ",n++}continue}if(s==="$"&&o[n+1]==="{"){n+=2;let f=1;while(n<t&&f>0){let u=o[n];if(u==="{"){f++,n++;continue}if(u==="}"){f--,n++;continue}e[n]=" ",n++}continue}e[n]=" ",n++}return n}function i(o){let e=a(o).match(/<<-?/);if(!e||e.index===void 0)return null;let n=o.slice(e.index+e[0].length).match(/^\s*(['"]?)(\w+)\1/);if(!n)return null;return n[2]}class b{continued=!1;header;read(o){let c=a(o).trim(),e=this.continued;if(!e)this.header=/^(?:if|elif)\b/.test(c)?"then":/^(?:while|for|until)\b/.test(c)?"do":void 0;let t=e&&this.header!==void 0&&new RegExp(`\\b${this.header}\\s*$`).test(c),n=c.match(/\\+$/)?.[0].length??0;if(this.continued=n%2===1,!this.continued)this.header=void 0;return{continuation:e,closesHeader:t}}}
|
|
3
|
+
export{a,i,b};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{n}from"./chunk-
|
|
3
|
-
`)}};var P={meta:{docs:"Require error handling after cd commands",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];let m=t.replace(/^\s+/,"");if(m.startsWith("#"))continue;let h=m.match(/^cd\s+/);if(!h)continue;let l=/\|\||&&/.test(t),p=/^\s*(?:if|elif|while|until)\s/.test(m)||/\bif\s+cd\b/.test(t),
|
|
4
|
-
`)}};function E(u,f){if(/^then\b/.test(u)||/^do\b/.test(u)||/^else\b/.test(u))return!0;if(/^if\b/.test(u)&&/\bthen\s*$/.test(u))return!0;if(/^elif\b/.test(u)&&/\bthen\s*$/.test(u))return!0;if(/^(?:while|for|until)\b/.test(u)&&/\bdo\s*$/.test(u))return!0;if(/^case\b/.test(u)&&/\bin\s*$/.test(u))return!0;if(f&&/\)\s*$/.test(u)&&!/\$\(/.test(u)&&!/^\s*\(/.test(u)&&!u.startsWith("#"))return!0;if(/\{\s*$/.test(u)&&!u.startsWith("#"))return!0;return!1}function q(u){return/^(?:fi|done|esac|elif|else)\b/.test(u)||/^\}/.test(u)||/^;[;&]\s*$/.test(u)}var O={meta:{docs:"Enforce consistent indentation in shell scripts",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=f.config.format.indent||2,r=0,e=new
|
|
5
|
-
`)}};var A={meta:{docs:"Enforce spacing around shell keywords (if, then, do, else, fi, etc.)",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=i(t);if(d)s=!0,r=d;if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=a(t),l=h.match(/;(?![;\s$])\S/);if(l)o.push({filePath:f.filePath,line:e+1,column:(l.index||0)+1,ruleId:"shell/keyword-spacing",message:"Missing space after semicolon",severity:"warning"});let p=h.match(/\w(then|do|else|elif|fi|done|esac)\b/);if(p&&!/[a-z]/.test(h[p.index])){let
|
|
2
|
+
import{n}from"./chunk-qq03kpe0.js";import{a,i,b}from"./chunk-0rxvmb2a.js";var v={meta:{docs:"Use $() instead of backticks for command substitution",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="",e=!1;for(let t=0;t<c.length;t++){let d=c[t];if(s){if(d.trim()===r)s=!1;continue}let m=d.match(/<<-?\s*['"]?(\w+)['"]?/);if(m)s=!0,r=m[1];if(d.replace(/^\s+/,"").startsWith("#"))continue;e=!1;for(let l=0;l<d.length;l++){let p=d[l];if(p==="#"&&!e)break;if(p==="\\"){l++;continue}if(p==="'"){e=!e;continue}if(e)continue;if(p==="`"){o.push({filePath:f.filePath,line:t+1,column:l+1,ruleId:"shell/command-substitution",message:"Use $(...) instead of backticks for command substitution",severity:"error",help:"Replace `cmd` with $(cmd) for better readability and nesting support"});for(l++;l<d.length&&d[l]!=="`";l++)if(d[l]==="\\")l++}}}return o},fix(u,f){let o=u.split(/\r?\n/),c=[],s=!1,r="";for(let e of o){if(s){if(c.push(e),e.trim()===r)s=!1;continue}let t=e.match(/<<-?\s*['"]?(\w+)['"]?/);if(t)s=!0,r=t[1];let d="",m=!1,h=0;while(h<e.length){let l=e[h];if(l==="#"&&!m){d+=e.slice(h);break}if(l==="\\"){d+=e.slice(h,h+2),h+=2;continue}if(l==="'"){m=!m,d+=l,h++;continue}if(m){d+=l,h++;continue}if(l==="`"){let p="";h++;while(h<e.length&&e[h]!=="`")if(e[h]==="\\")p+=e[h+1]||"",h+=2;else p+=e[h],h++;h++,d+=`$(${p})`}else d+=l,h++}c.push(d)}return c.join(`
|
|
3
|
+
`)}};var P={meta:{docs:"Require error handling after cd commands",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];let m=t.replace(/^\s+/,"");if(m.startsWith("#"))continue;let h=m.match(/^cd\s+/);if(!h)continue;let l=/\|\||&&/.test(t),p=/^\s*(?:if|elif|while|until)\s/.test(m)||/\bif\s+cd\b/.test(t),g=/\(.*\bcd\b.*\)/.test(t);if(!l&&!p&&!g)o.push({filePath:f.filePath,line:e+1,column:h.index+1,ruleId:"shell/no-cd-without-check",message:"cd without error handling \u2014 if it fails, subsequent commands run in the wrong directory",severity:"warning",help:"Use: cd dir || exit 1 (or || return 1 inside functions)"})}return o}};var S={meta:{docs:"Disallow use of eval in shell scripts",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];if(t.replace(/^\s+/,"").startsWith("#"))continue;if(t.match(/(?:^|[;&|]\s*|^\s+)eval\s/)){let l=t.indexOf("eval");o.push({filePath:f.filePath,line:e+1,column:l+1,ruleId:"shell/no-eval",message:"Avoid using eval \u2014 it re-parses arguments and can lead to code injection",severity:"error",help:"Refactor to avoid eval. Consider using arrays for dynamic commands or indirect variable references with ${!var}"})}}return o}};var D={meta:{docs:"Flag exit inside subshells where it only exits the subshell",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="",e=0;for(let t=0;t<c.length;t++){let d=c[t];if(s){if(d.trim()===r)s=!1;continue}let m=d.match(/<<-?\s*['"]?(\w+)['"]?/);if(m)s=!0,r=m[1];if(d.replace(/^\s+/,"").startsWith("#"))continue;let l=!1,p=!1;for(let g=0;g<d.length;g++){let R=d[g];if(R==="#"&&!l&&!p)break;if(R==="\\"&&!l){g++;continue}if(R==="'"&&!p){l=!l;continue}if(R==='"'&&!l){p=!p;continue}if(!l&&!p){if(R==="("&&g>0&&d[g-1]!=="$"&&d[g+1]!=="(")e++;else if(R==="("&&g===0&&d[g+1]!=="(")e++;else if(R===")"&&e>0&&(g+1>=d.length||d[g+1]!==")"))e--}}if(e>0){let g=d.match(/\bexit\b/);if(g)o.push({filePath:f.filePath,line:t+1,column:g.index+1,ruleId:"shell/no-exit-in-subshell",message:"exit inside a subshell only exits the subshell, not the script",severity:"warning",help:"Restructure to avoid subshells, or use return if inside a function"})}if(e===0){let g=d.match(/(?<!\$)\((?!\()([^)]*\bexit\b[^)]*)\)(?!\))/);if(g){let R=d.indexOf("exit",g.index);o.push({filePath:f.filePath,line:t+1,column:R+1,ruleId:"shell/no-exit-in-subshell",message:"exit inside a subshell only exits the subshell, not the script",severity:"warning",help:"Restructure to avoid subshells, or use return if inside a function"})}}}return o}};var I={meta:{docs:"Disallow parsing ls output \u2014 use globs or find instead",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];if(t.replace(/^\s+/,"").startsWith("#"))continue;if(t.match(/\bls\b[^|]*\|/)){let g=t.indexOf("ls");o.push({filePath:f.filePath,line:e+1,column:g+1,ruleId:"shell/no-ls-parsing",message:"Don't parse ls output \u2014 filenames can contain special characters",severity:"warning",help:'Use globs (for f in *.txt), find (find . -name "*.txt"), or stat instead'});continue}let l=t.match(/\$\(\s*ls\b/);if(l){let g=l.index+1;o.push({filePath:f.filePath,line:e+1,column:g,ruleId:"shell/no-ls-parsing",message:"Don't use ls in command substitution \u2014 use globs instead",severity:"warning",help:"Replace $(ls *.txt) with glob patterns: for f in *.txt; do ...; done"});continue}let p=t.match(/`\s*ls\b/);if(p){let g=p.index+1;o.push({filePath:f.filePath,line:e+1,column:g,ruleId:"shell/no-ls-parsing",message:"Don't use ls in command substitution \u2014 use globs instead",severity:"warning",help:"Replace `ls` with glob patterns"})}}return o}};var T={meta:{docs:"Detect useless use of cat (UUOC)",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=t.match(/\bcat\s+(["']?[\w.\/~${}*?-]+["']?)\s*\|/);if(h){let l=t.indexOf("cat");o.push({filePath:f.filePath,line:e+1,column:l+1,ruleId:"shell/no-useless-cat",message:`Useless use of cat \u2014 pipe the file directly instead of \`cat ${h[1]} | ...\``,severity:"warning",help:`Use \`cmd < ${h[1]}\` or pass the file as an argument to the command`})}}return o}};var W={meta:{docs:"Flag variables inside single quotes where they won't expand",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=!1,l=!1,p=-1;for(let g=0;g<t.length;g++){let R=t[g];if(R==="#"&&!h&&!l)break;if(R==="\\"&&!h){g++;continue}if(R==='"'&&!h){l=!l;continue}if(R==="'"&&!l)if(!h)h=!0,p=g;else{let M=t.slice(p+1,g).match(/\$(?:[A-Za-z_]\w*|\{[^}]+\}|\([^)]*\))/),w=/(?:^|[;&|])\s*(?:(?:then|do)\s+)?(?:(?:builtin|command)\s+)?trap\s+(?:--\s+)?$/.test(t.slice(0,p));if(M&&!w)o.push({filePath:f.filePath,line:e+1,column:p+1+M.index+1,ruleId:"shell/no-variable-in-single-quotes",message:`Variable ${M[0]} is inside single quotes and won't be expanded`,severity:"warning",help:`Use double quotes if you want variable expansion: "..." instead of '...'`});h=!1}}}return o}};var G=[/^\s*(?:local|export|declare|typeset|readonly)\s+/,/\[\[.*\]\]/,/\(\(.*\)\)/],k=/^\$(?:\{[A-Za-z_]\w*(?:[:#%\/][^}]*)?\}|[A-Za-z_]\w*)/,H={meta:{docs:"Quote variable expansions to prevent word splitting and globbing",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=i(t);if(d){if(s=!0,r=d,new RegExp(`<<-?\\s*['"]${d}['"]`).test(t))continue}if(t.replace(/^\s+/,"").startsWith("#"))continue;if(G.some((p)=>p.test(t)))continue;let h=[],l=0;while(l<t.length){let p=h[h.length-1];if(p==="squote"){if(t[l]==="'")h.pop();l++;continue}if(t[l]==="\\"&&l+1<t.length){l+=2;continue}if(p==="dquote"){let R=t[l];if(R==='"'){h.pop(),l++;continue}if(R==="$"&&t[l+1]==="("&&t[l+2]==="("){h.push("arith"),l+=3;continue}if(R==="$"&&t[l+1]==="("){h.push("subshell"),l+=2;continue}if(R==="$"){let y=t.slice(l).match(k);if(y){l+=y[0].length;continue}}l++;continue}if(p==="arith"){let R=t[l];if(R===")"&&t[l+1]===")"){h.pop(),l+=2;continue}if(R==="$"){let y=t.slice(l).match(k);if(y){l+=y[0].length;continue}}l++;continue}let g=t[l];if(g==="#"&&(l===0||/\s/.test(t[l-1])))break;if(g==="'"){h.push("squote"),l++;continue}if(g==='"'){h.push("dquote"),l++;continue}if(g==="$"&&t[l+1]==="("&&t[l+2]==="("){h.push("arith"),l+=3;continue}if(g==="$"&&t[l+1]==="("){h.push("subshell"),l+=2;continue}if(g===")"&&p==="subshell"){h.pop(),l++;continue}if(g==="$"){let R=t.slice(l).match(k);if(R){let y=R[0];if(!/^\$[?!#@*0-9-]/.test(y))o.push({filePath:f.filePath,line:e+1,column:l+1,ruleId:"shell/quote-variables",message:`Unquoted variable ${y} \u2014 use "${y}" to prevent word splitting`,severity:"warning",help:`Wrap in double quotes: "${y}"`});l+=y.length;continue}}l++}}return o}};var C={meta:{docs:"Enforce consistent function declaration style",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];let m=t.replace(/^\s+/,"");if(m.startsWith("#"))continue;let h=m.match(/^function\s+(\w+)\s*(?:\(\s*\))?\s*\{?\s*$/);if(h){let l=h[1],p=t.indexOf("function");o.push({filePath:f.filePath,line:e+1,column:p+1,ruleId:"shell/function-style",message:`Use \`${l}() {\` instead of \`function ${l}\` \u2014 POSIX-compatible style`,severity:"warning",help:`Replace with: ${l}() {`})}}return o},fix(u){let f=u.split(/\r?\n/),o=[];for(let c of f){let s=c.match(/^(\s*)function\s+(\w+)\s*(?:\(\s*\))?\s*(\{?\s*)$/);if(s){let[,r,e,t]=s;o.push(`${r}${e}() ${t||"{"}`)}else o.push(c)}return o.join(`
|
|
4
|
+
`)}};function E(u,f){if(/^then\b/.test(u)||/^do\b/.test(u)||/^else\b/.test(u))return!0;if(/^if\b/.test(u)&&/\bthen\s*$/.test(u))return!0;if(/^elif\b/.test(u)&&/\bthen\s*$/.test(u))return!0;if(/^(?:while|for|until)\b/.test(u)&&/\bdo\s*$/.test(u))return!0;if(/^case\b/.test(u)&&/\bin\s*$/.test(u))return!0;if(f&&/\)\s*$/.test(u)&&!/\$\(/.test(u)&&!/^\s*\(/.test(u)&&!u.startsWith("#"))return!0;if(/\{\s*$/.test(u)&&!u.startsWith("#"))return!0;return!1}function q(u){return/^(?:fi|done|esac|elif|else)\b/.test(u)||/^\}/.test(u)||/^;[;&]\s*$/.test(u)}var O={meta:{docs:"Enforce consistent indentation in shell scripts",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=f.config.format.indent||2,r=0,e=new b,t=!1,d="",m=!1,h=0;for(let l=0;l<c.length;l++){let p=c[l];if(/^\s*$/.test(p))continue;if(t){if(p.trim()===d)t=!1;continue}let g=p.match(/<<-?\s*['"]?(\w+)['"]?/);if(g)t=!0,d=g[1];let R=p.replace(/^\s+/,""),y=e.read(R);if(l===0&&R.startsWith("#!"))continue;if(/^case\b/.test(R)&&/\bin\s*$/.test(R))h++,m=!0;if(/^esac\b/.test(R)){if(h=Math.max(0,h-1),h===0)m=!1}if(!y.continuation&&q(R))r=Math.max(0,r-1);let M=0;for(let x=0;x<p.length;x++)if(p[x]===" ")M++;else if(p[x]==="\t")M+=s;else break;let w=(r+Number(y.continuation))*s;if(M!==w&&!R.startsWith("#"))o.push({filePath:f.filePath,line:l+1,column:1,ruleId:"shell/indent",message:`Expected ${w} spaces of indentation, found ${M}`,severity:"warning"});if(y.closesHeader||!y.continuation&&E(R,m))r++}return o},fix(u,f){let o=u.split(/\r?\n/),c=f.config.format.indent||2,s=f.config.format.indentStyle==="tabs",r=[],e=0,t=new b,d=!1,m="",h=!1,l=0;for(let p=0;p<o.length;p++){let g=o[p];if(/^\s*$/.test(g)){r.push("");continue}if(d){if(r.push(g),g.trim()===m)d=!1;continue}let R=g.match(/<<-?\s*['"]?(\w+)['"]?/);if(R)d=!0,m=R[1];let y=g.replace(/^\s+/,"").trimEnd(),M=t.read(y);if(p===0&&y.startsWith("#!")){r.push(y);continue}if(/^case\b/.test(y)&&/\bin\s*$/.test(y))l++,h=!0;if(/^esac\b/.test(y)){if(l=Math.max(0,l-1),l===0)h=!1}if(!M.continuation&&q(y))e=Math.max(0,e-1);let w=e+Number(M.continuation),x=s?"\t".repeat(w):" ".repeat(w*c);if(r.push(x+y),M.closesHeader||!M.continuation&&E(y,h))e++}return r.join(`
|
|
5
|
+
`)}};var A={meta:{docs:"Enforce spacing around shell keywords (if, then, do, else, fi, etc.)",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=i(t);if(d)s=!0,r=d;if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=a(t),l=h.match(/;(?![;\s$])\S/);if(l)o.push({filePath:f.filePath,line:e+1,column:(l.index||0)+1,ruleId:"shell/keyword-spacing",message:"Missing space after semicolon",severity:"warning"});let p=h.match(/\w(then|do|else|elif|fi|done|esac)\b/);if(p&&!/[a-z]/.test(h[p.index])){let g=p[1],R=h[p.index];if(R!==" "&&R!=="\t"&&R!==";")o.push({filePath:f.filePath,line:e+1,column:(p.index||0)+2,ruleId:"shell/keyword-spacing",message:`Missing space before keyword '${g}'`,severity:"warning"})}}return o}};var U={meta:{docs:"Disallow unnecessary trailing semicolons",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];let m=t.replace(/^\s+/,"").trimEnd();if(m.startsWith("#"))continue;if(/;;\s*$/.test(m))continue;if(/\bfor\b/.test(m)||/\bwhile\b/.test(m)||/\buntil\b/.test(m))continue;if(/;\s*(?:then|do|else|elif|fi|done|esac)\s*$/.test(m))continue;if(/;\s*$/.test(m)){let h=t.lastIndexOf(";");o.push({filePath:f.filePath,line:e+1,column:h+1,ruleId:"shell/no-trailing-semicolons",message:"Unnecessary trailing semicolon",severity:"warning"})}}return o},fix(u){let f=u.split(/\r?\n/),o=[],c=!1,s="";for(let r of f){if(c){if(o.push(r),r.trim()===s)c=!1;continue}let e=r.match(/<<-?\s*['"]?(\w+)['"]?/);if(e)c=!0,s=e[1];let t=r.replace(/^\s+/,"").trimEnd();if(t.startsWith("#")||/;;\s*$/.test(t)||/\bfor\b/.test(t)||/\bwhile\b/.test(t)||/\buntil\b/.test(t)||/;\s*(?:then|do|else|elif|fi|done|esac)\s*$/.test(t)){o.push(r);continue}o.push(r.replace(/;\s*$/,""))}return o.join(`
|
|
6
6
|
`)}};var j={meta:{docs:"Disallow trailing whitespace",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=i(t);if(d)s=!0,r=d;if(/[ \t]+$/.test(t)){let m=t.match(/[ \t]+$/);o.push({filePath:f.filePath,line:e+1,column:m.index+1,ruleId:"shell/no-trailing-whitespace",message:"Trailing whitespace",severity:"error"})}}return o},fix(u){let f=u.split(/\r?\n/),o=!1,c="";return f.map((r)=>{if(o){if(r.trim()===c)o=!1;return r}let e=i(r);if(e)o=!0,c=e;return r.replace(/[ \t]+$/,"")}).join(`
|
|
7
7
|
`)}};var B={meta:{docs:"Enforce spaces inside [ ] and [[ ]] test expressions",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=i(t);if(d)s=!0,r=d;if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=a(t);for(let l of K(h,e+1,f.filePath))o.push(l)}return o},fix(u){let f=u.split(/\r?\n/),o=[],c=!1,s="";for(let r of f){if(c){if(r.trim()===s)c=!1;o.push(r);continue}let e=i(r);if(e){c=!0,s=e,o.push(r);continue}if(r.replace(/^\s+/,"").startsWith("#")){o.push(r);continue}o.push(J(r))}return o.join(`
|
|
8
|
-
`)}};function K(u,f,o){let c=[],s=/\[\[(?!\s|\]|$)/g;for(let e of u.matchAll(s))c.push({filePath:o,line:f,column:(e.index??0)+1,ruleId:"shell/operator-spacing",message:"Missing space after [[",severity:"warning"});let r=/(?<!\s|\[)\]\]/g;for(let e of u.matchAll(r))c.push({filePath:o,line:f,column:(e.index??0)+1,ruleId:"shell/operator-spacing",message:"Missing space before ]]",severity:"warning"});for(let e=0;e<u.length;e++){if(u[e]!=="[")continue;if(u[e+1]==="[")continue;if(e>0&&u[e-1]==="[")continue;if(!z(u,e))continue;let t=u[e+1];if(t!==void 0&&t!==" "&&t!=="\t")c.push({filePath:o,line:f,column:e+1,ruleId:"shell/operator-spacing",message:"Missing space after [",severity:"warning"})}for(let e=0;e<u.length;e++){if(u[e]!=="]")continue;if(u[e+1]==="]")continue;if(e>0&&u[e-1]==="]")continue;if(!L(u,e))continue;let t=u[e-1];if(t!==void 0&&t!==" "&&t!=="\t")c.push({filePath:o,line:f,column:e+1,ruleId:"shell/operator-spacing",message:"Missing space before ]",severity:"warning"})}return c}function J(u){let f=a(u),o=[];for(let s of f.matchAll(/\[\[(?!\s|\]|$)/g)){let r=(s.index??0)+2;o.push({pos:r,text:" "})}for(let s of f.matchAll(/(?<!\s|\[)\]\]/g)){let r=s.index??0;o.push({pos:r,text:" "})}for(let s=0;s<f.length;s++){if(f[s]!=="[")continue;if(f[s+1]==="[")continue;if(s>0&&f[s-1]==="[")continue;if(!z(f,s))continue;let r=f[s+1];if(r!==void 0&&r!==" "&&r!=="\t")o.push({pos:s+1,text:" "})}for(let s=0;s<f.length;s++){if(f[s]!=="]")continue;if(f[s+1]==="]")continue;if(s>0&&f[s-1]==="]")continue;if(!L(f,s))continue;let r=f[s-1];if(r!==void 0&&r!==" "&&r!=="\t")o.push({pos:s,text:" "})}if(o.length===0)return u;o.sort((s,r)=>r.pos-s.pos);let c=u;for(let{pos:s,text:r}of o)c=`${c.slice(0,s)}${r}${c.slice(s)}`;return c}function z(u,f){let o=f-1;while(o>=0&&(u[o]===" "||u[o]==="\t"))o--;if(o<0)return!0;let c=u[o];if(c===";"||c==="|"||c==="&"||c==="!"||c==="(")return!0;let s=u.slice(0,o+1);if(/(?:^|\s)(?:if|while|until|elif|then|else|do)\s*$/.test(s))return!0;return!1}function L(u,f){let o=u[f+1];if(o===void 0)return!0;return o===" "||o==="\t"||o===";"||o==="|"||o==="&"||o===")"}var Y=/^#!\s*(?:\/usr\/bin\/env\s+(?:ba|z|k|da)?sh|\/bin\/(?:ba|z|k|da)?sh|\/usr\/bin\/(?:ba|z|k|da)?sh)\b/,Q={meta:{docs:"Ensure shell scripts have a proper shebang line",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/);if(c.length===0)return o;let s=c[0];if(c.every((r)=>r.trim()===""))return o;if(!s.startsWith("#!"))return o.push({filePath:f.filePath,line:1,column:1,ruleId:"shell/shebang",message:"Missing shebang line \u2014 shell scripts should start with #!/usr/bin/env bash (or similar)",severity:"warning",help:"Add #!/usr/bin/env bash as the first line"}),o;if(!Y.test(s))o.push({filePath:f.filePath,line:1,column:1,ruleId:"shell/shebang",message:`Invalid shebang: ${s} \u2014 use #!/usr/bin/env bash or #!/bin/sh`,severity:"warning",help:"Use #!/usr/bin/env bash for portability or #!/bin/sh for POSIX scripts"});return o}};var V={meta:{docs:"Enforce consistent case statement terminator placement",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="",e=[];for(let t of c){if(s){if(t.trim()===r)s=!1;e.push("");continue}let d=i(t);if(d)s=!0,r=d;if(t.replace(/^\s+/,"").startsWith("#")){e.push("");continue}e.push(a(t))}for(let t=0;t<e.length;t++){if(!/\bcase\b[\s\S]*\bin\s*$/.test(e[t].trimEnd()))continue;let d=1,m=-1;for(let
|
|
8
|
+
`)}};function K(u,f,o){let c=[],s=/\[\[(?!\s|\]|$)/g;for(let e of u.matchAll(s))c.push({filePath:o,line:f,column:(e.index??0)+1,ruleId:"shell/operator-spacing",message:"Missing space after [[",severity:"warning"});let r=/(?<!\s|\[)\]\]/g;for(let e of u.matchAll(r))c.push({filePath:o,line:f,column:(e.index??0)+1,ruleId:"shell/operator-spacing",message:"Missing space before ]]",severity:"warning"});for(let e=0;e<u.length;e++){if(u[e]!=="[")continue;if(u[e+1]==="[")continue;if(e>0&&u[e-1]==="[")continue;if(!z(u,e))continue;let t=u[e+1];if(t!==void 0&&t!==" "&&t!=="\t")c.push({filePath:o,line:f,column:e+1,ruleId:"shell/operator-spacing",message:"Missing space after [",severity:"warning"})}for(let e=0;e<u.length;e++){if(u[e]!=="]")continue;if(u[e+1]==="]")continue;if(e>0&&u[e-1]==="]")continue;if(!L(u,e))continue;let t=u[e-1];if(t!==void 0&&t!==" "&&t!=="\t")c.push({filePath:o,line:f,column:e+1,ruleId:"shell/operator-spacing",message:"Missing space before ]",severity:"warning"})}return c}function J(u){let f=a(u),o=[];for(let s of f.matchAll(/\[\[(?!\s|\]|$)/g)){let r=(s.index??0)+2;o.push({pos:r,text:" "})}for(let s of f.matchAll(/(?<!\s|\[)\]\]/g)){let r=s.index??0;o.push({pos:r,text:" "})}for(let s=0;s<f.length;s++){if(f[s]!=="[")continue;if(f[s+1]==="[")continue;if(s>0&&f[s-1]==="[")continue;if(!z(f,s))continue;let r=f[s+1];if(r!==void 0&&r!==" "&&r!=="\t")o.push({pos:s+1,text:" "})}for(let s=0;s<f.length;s++){if(f[s]!=="]")continue;if(f[s+1]==="]")continue;if(s>0&&f[s-1]==="]")continue;if(!L(f,s))continue;let r=f[s-1];if(r!==void 0&&r!==" "&&r!=="\t")o.push({pos:s,text:" "})}if(o.length===0)return u;o.sort((s,r)=>r.pos-s.pos);let c=u;for(let{pos:s,text:r}of o)c=`${c.slice(0,s)}${r}${c.slice(s)}`;return c}function z(u,f){let o=f-1;while(o>=0&&(u[o]===" "||u[o]==="\t"))o--;if(o<0)return!0;let c=u[o];if(c===";"||c==="|"||c==="&"||c==="!"||c==="(")return!0;let s=u.slice(0,o+1);if(/(?:^|\s)(?:if|while|until|elif|then|else|do)\s*$/.test(s))return!0;return!1}function L(u,f){let o=u[f+1];if(o===void 0)return!0;return o===" "||o==="\t"||o===";"||o==="|"||o==="&"||o===")"}var Y=/^#!\s*(?:\/usr\/bin\/env\s+(?:ba|z|k|da)?sh|\/bin\/(?:ba|z|k|da)?sh|\/usr\/bin\/(?:ba|z|k|da)?sh)\b/,Q={meta:{docs:"Ensure shell scripts have a proper shebang line",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/);if(c.length===0)return o;let s=c[0];if(c.every((r)=>r.trim()===""))return o;if(!s.startsWith("#!"))return o.push({filePath:f.filePath,line:1,column:1,ruleId:"shell/shebang",message:"Missing shebang line \u2014 shell scripts should start with #!/usr/bin/env bash (or similar)",severity:"warning",help:"Add #!/usr/bin/env bash as the first line"}),o;if(!Y.test(s))o.push({filePath:f.filePath,line:1,column:1,ruleId:"shell/shebang",message:`Invalid shebang: ${s} \u2014 use #!/usr/bin/env bash or #!/bin/sh`,severity:"warning",help:"Use #!/usr/bin/env bash for portability or #!/bin/sh for POSIX scripts"});return o}};var V={meta:{docs:"Enforce consistent case statement terminator placement",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="",e=[];for(let t of c){if(s){if(t.trim()===r)s=!1;e.push("");continue}let d=i(t);if(d)s=!0,r=d;if(t.replace(/^\s+/,"").startsWith("#")){e.push("");continue}e.push(a(t))}for(let t=0;t<e.length;t++){if(!/\bcase\b[\s\S]*\bin\s*$/.test(e[t].trimEnd()))continue;let d=1,m=-1;for(let g=t+1;g<e.length;g++){let R=e[g].trimEnd();if(/^\s*esac\b/.test(R)){if(d--,d===0){m=g;break}continue}if(/\bcase\b[\s\S]*\bin\s*$/.test(R))d++}if(m===-1)continue;let h=0,l=!1,p=!1;for(let g=t+1;g<m;g++){let R=e[g],y=R.trim();if(y==="")continue;if(h===0){let M=ee(R);if(M!==-1){if(l&&p)o.push({filePath:f.filePath,line:g+1,column:1,ruleId:"shell/consistent-case-terminators",message:"Missing ;; terminator for previous case branch",severity:"warning",help:"Add ;; at the end of the case branch before the next pattern"});l=!0,p=!0;let w=R.slice(M+1).trimEnd();if(/;;\s*$/.test(w))l=!1;continue}}if(h+=te(R),h<0)h=0;if(l&&h===0&&/;;\s*$/.test(y))l=!1}}return o}};function ee(u){let f=u.replace(/^\s+/,"");if(f==="")return-1;if(/^(?:for|while|until|if|case|do|then|else|elif|fi|done|esac)\b/.test(f))return-1;let o=u.length-f.length,c=0;if(f[c]==="(")c++;let s=0;while(c<f.length){let r=f[c];if(r==="(")s++;else if(r===")"){if(s===0)return o+c;s--}else if(r===";"||r==="&"||r==="<"||r===">"||r==="=")return-1;c++}return-1}function te(u){let f=u.trim();if(f==="")return 0;let o=f.split(/[\s;]+/),c=0;for(let s of o)if(s==="if"||s==="for"||s==="while"||s==="until")c++;else if(s==="fi"||s==="done")c--;return c}var _={meta:{docs:"Recommend <<- for heredocs inside indented blocks"},check(u,f){let o=[],c=u.split(/\r?\n/);for(let s=0;s<c.length;s++){let r=c[s];if(r.replace(/^\s+/,"").startsWith("#"))continue;if(!r.match(/^\s+/))continue;let m=a(r).match(/(?<!<)<<(?![<-])/);if(!m||m.index===void 0)continue;let l=r.slice(m.index+2).match(/^\s*(['"]?)(\w+)\1\s*$/);if(l){let p=l[2];o.push({filePath:f.filePath,line:s+1,column:m.index+1,ruleId:"shell/heredoc-indent",message:`Use <<- instead of << for indented heredoc (delimiter '${p}' must be at column 0 otherwise)`,severity:"warning",help:"Use <<- to strip leading tabs from heredoc content, allowing proper indentation"})}}return o}};var Z={meta:{docs:"Detect incorrect redirect ordering (2>&1 before > file)",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=i(t);if(d)s=!0,r=d;if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=a(t);if(h.match(/2>&1\s+>(?!&)\s*\S/)){let p=h.indexOf("2>&1");o.push({filePath:f.filePath,line:e+1,column:p+1,ruleId:"shell/no-broken-redirect",message:"Broken redirect: 2>&1 before > file \u2014 stderr goes to terminal, not the file",severity:"error",help:"Swap the order: cmd > file 2>&1 (or use &> file in bash)"})}}return o}};var F={meta:{docs:"Prefer [[ ]] over [ ] for test expressions in bash/zsh",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/)[0]||"",s=/bash|zsh/.test(c);if(/^#!.*\bsh\b/.test(c)&&!s||!s)return o;let e=u.split(/\r?\n/),t=!1,d="";for(let m=0;m<e.length;m++){let h=e[m];if(t){if(h.trim()===d)t=!1;continue}let l=h.match(/<<-?\s*['"]?(\w+)['"]?/);if(l)t=!0,d=l[1];if(h.replace(/^\s+/,"").startsWith("#"))continue;if(h.match(/(?:^|\s|;)\[\s(?!\[)/)){if(/(?<!\])\](?!\])/.test(h)){let R=h.indexOf("[");o.push({filePath:f.filePath,line:m+1,column:R+1,ruleId:"shell/prefer-double-brackets",message:"Use [[ ]] instead of [ ] for test expressions in bash/zsh",severity:"warning",help:"[[ ]] prevents word splitting and supports && || regex; [ ] is only needed for POSIX sh"})}}}return o},fix(u){let f=u.split(/\r?\n/)[0]||"";if(!/bash|zsh/.test(f))return u;let c=u.split(/\r?\n/),s=[];for(let r of c){let e=r;e=e.replace(/(?:^|(?<=\s|;))\[(\s(?!\[).*?(?<!\]))\](?!\])/g,"[[$1]]"),s.push(e)}return s.join(`
|
|
9
9
|
`)}};var X={meta:{docs:"Prefer printf over echo -e and echo -n",recommended:!0},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r="";for(let e=0;e<c.length;e++){let t=c[e];if(s){if(t.trim()===r)s=!1;continue}let d=t.match(/<<-?\s*['"]?(\w+)['"]?/);if(d)s=!0,r=d[1];if(t.replace(/^\s+/,"").startsWith("#"))continue;let h=t.match(/\becho\s+-[en]+\b/);if(h){let l=t.indexOf("echo"),p=h[0].replace("echo ","");o.push({filePath:f.filePath,line:e+1,column:l+1,ruleId:"shell/prefer-printf",message:`Use printf instead of echo ${p} \u2014 echo behavior varies across platforms`,severity:"warning",help:'printf is portable: printf "format\\n" args... (use \\n for newline)'})}}return o}};var N={meta:{docs:"Recommend set -euo pipefail for safer script execution"},check(u,f){let o=[],c=u.split(/\r?\n/),s=!1,r=!1,e=!1,t=-1,d=!1;for(let h=0;h<c.length;h++){let l=c[h].replace(/^\s+/,"");if(h===0&&l.startsWith("#!")){t=h;continue}if(l.startsWith("#"))continue;if(l==="")continue;if(d=!0,/\bset\s+-\w*e/.test(l))s=!0;if(/\bset\s+-\w*u/.test(l))r=!0;if(/\bset\s+.*-o\s+pipefail/.test(l))e=!0;if(/\bset\s+-euo\s+pipefail/.test(l))s=!0,r=!0,e=!0}if(!d)return o;let m=[];if(!s)m.push("-e");if(!r)m.push("-u");if(!e)m.push("-o pipefail");if(m.length>0)o.push({filePath:f.filePath,line:t>=0?t+2:1,column:1,ruleId:"shell/set-options",message:`Missing shell safety options: set ${m.join(" ")}`,severity:"warning",help:"Add `set -euo pipefail` near the top of the script for safer execution"});return o}};var Ye={name:"shell",rules:{"command-substitution":n(v),"quote-variables":n(H),"no-cd-without-check":n(P),"no-eval":n(S),"no-useless-cat":n(T),"no-ls-parsing":n(I),"no-variable-in-single-quotes":n(W),"no-exit-in-subshell":n(D),shebang:n(Q),indent:n(O),"function-style":n(C),"operator-spacing":n(B),"keyword-spacing":n(A),"no-trailing-semicolons":n(U),"no-trailing-whitespace":n(j),"prefer-double-brackets":n(F),"set-options":n(N),"prefer-printf":n(X),"consistent-case-terminators":n(V),"no-broken-redirect":n(Z),"heredoc-indent":n(_)}};export{Ye as shellPlugin};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{oe,ae,F,le,ce,ue,fe,me,he,de,pe,ge,ye,be,we,xe,ke,Re,$e,ve}from"./chunk-ra9jn7j5.js";export{ce as author,be as bin,he as bugs,ve as default,ke as dependencies,le as description,$e as devDependencies,pe as exports,we as files,fe as homepage,de as keywords,ue as license,ge as module,oe as name,Re as optionalDependencies,me as repository,xe as scripts,ae as type,ye as types,F as version};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var{defineProperty:e,getOwnPropertyNames:g,getOwnPropertyDescriptor:h}=Object,i=Object.prototype.hasOwnProperty;function k(a){return this[a]}var P=(a)=>{var b=(f??=new WeakMap).get(a),c;if(b)return b;if(b=e({},"__esModule",{value:!0}),a&&typeof a==="object"||typeof a==="function"){for(var d of g(a))if(!i.call(b,d))e(b,d,{get:k.bind(a,d),enumerable:!(c=h(a,d))||c.enumerable})}return f.set(a,b),b},f;var l=(a)=>a;function m(a,b){this[a]=l.bind(null,b)}var D=(a,b)=>{for(var c in b)e(a,c,{get:b[c],enumerable:!0,configurable:!0,set:m.bind(b,c)})};var j=(a,b,c)=>()=>{if(a)try{b=a(a=0)}catch(d){c=[d]}if(c)throw c[0];return b};var te=import.meta.require;
|
|
3
|
+
export{P,D,j,te};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{p,u}from"./chunk-rx0b7k57.js";import{readFileSync as O,statSync as y,writeFileSync as x}from"fs";import{isAbsolute as d,resolve as l}from"path";function o(r){return r.write===!0||r.fix===!0}async function B(r,t){let a=t.mode||"auto";if(a==="format"&&r.length===1&&!/[*?[\]{}()!]/.test(r[0]))try{let n=r[0],i=d(n)?n:l(process.cwd(),n);if(y(i).isFile()){let m=await u(t.config),f=O(i,"utf8"),c=p(f,m,i);if(c===f)return 0;if(o(t))return x(i,c,"utf8"),0}}catch{}let{runLint:e}=await import("./chunk-2ja6xfzf.js");if(a==="lint")return e(r,t);if(a==="format"){let n={...t,fix:!0,dryRun:!o(t),ext:t.ext,_formatOnly:!0};return e(r,n)}if(!(t.fix===!0||t.write===!0||t.check===!0))return e(r,t);let s={...t,fix:!0,dryRun:!!t.check,ext:t.ext};return e(r,s)}
|
|
3
|
+
export{B};
|