@kitschpatrol/stylelint-config 8.1.0 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import{cosmiconfig as e}from"cosmiconfig";import{TypeScriptLoader as t}from"cosmiconfig-typescript-loader";import{execa as n}from"execa";import r from"fs-extra";import i from"node:fs";import a from"node:path";import{PassThrough as o,Transform as s}from"node:stream";import{fileURLToPath as c}from"node:url";import{packageUp as l,packageUpSync as u}from"package-up";import d from"picocolors";import f from"yargs";import{hideBin as p}from"yargs/helpers";import m from"@pinojs/json-colorizer";import h from"decircular";import g from"deepmerge";import _ from"json-stringify-pretty-compact";import{findWorkspacesRoot as v}from"find-workspaces";import y from"node:fs/promises";import{stripVTControlCharacters as b}from"node:util";import x from"stylelint";var S=`8.1.0`;function C(e){return e instanceof Error&&`exitCode`in e&&typeof e.exitCode==`number`}function w(e){return m(_(h(e),{indent:2,replacer(e,t){return typeof t==`function`?t.name:t}}),{colors:{BRACKET:`gray`}})}const T=(e,t,n)=>{let r=[...e];for(let[i,a]of t.entries())r[i]===void 0?r[i]=n.cloneUnlessOtherwiseSpecified(a,n):n.isMergeableObject(a)?r[i]=E(e[i],a,n):e.includes(a)||r.push(a);return r};function E(e,t,n={arrayMerge:T}){return g(e,t,n)}function D(){let e=u();if(e===void 0)throw Error(`No package.json found.`);return a.dirname(e)}function O(){let e=v();return e===null?D():a.resolve(e.location)}function k(e){let t=a.join(O(),e);if(r.existsSync(t))return t}function A(e){if(e===`workspace-root`)return O();if(e===`package-dir`)return D();if(typeof e==`string`){if(!r.pathExistsSync(e))throw Error(`Custom cwd directory does not exist: ${e}`);return e}return process.cwd()}async function j(e,t){try{let{default:n}=await import(`prettier`),r=await n.resolveConfig(e),i=await n.format(t,{filepath:e,...r});await y.writeFile(e,i,`utf8`)}catch{console.warn(`Skipped formatting ${e} since Prettier is not installed.`)}}async function M(e){try{await j(e,await y.readFile(e,`utf8`))}catch{}}const N=/\r?\n/v;function P(e){return new s({transform(t,n,r){r(void 0,t.toString().split(N).filter(t=>t.trim()!==``&&!e(b(t))).join(`
3
- `)+`
4
- `)}})}function F(e,t){let n=e===void 0||e===``?``:t===void 0?e:d[t](e);return new s({transform(e,t,r){r(void 0,e.toString().split(N).filter(e=>e.trim().length>0).map(e=>`${n} ${e}\n`).join(``))}})}async function I(e){let t=[];return new Promise((n,r)=>{e.on(`data`,e=>{t.push(e)}),e.on(`error`,e=>{r(e)}),e.on(`end`,()=>{n(Buffer.concat(t).toString(`utf8`))})})}function L(e,t){return t===1?e:e+`s`}async function R(e,t,n,r,i){let a;if(r.logPrefix===void 0)a=e;else{let t=F(r.logPrefix,r.logColor);t.pipe(e),a=t}i&&a.write(d.bold(`Running: "${r.name}() with Positional arguments: ${String(t)} and Option flags: ${String(n)}"`));try{return await r.execute(a,t,n)}catch(e){return console.error(String(e)),1}}async function z(e,t,r,i,a){let s=1,c;if(i.logPrefix===void 0)c=e;else{let t=F(i.logPrefix,i.logColor);t.pipe(e),c=t}let l=i.subcommands??[],u=[...i.receivePositionalArguments?t:[],...i.positionalArguments??[]],d=[...i.receiveOptionFlags?r:[],...i.optionFlags??[]],f=[...l,...d,...u],p=A(i.cwdOverride);a&&c.write(`Running: "${i.name} ${f.join(` `)}"`);let m=i.prettyJsonOutput?new o:c;try{let e=n(i.name,f,{cwd:p,env:{...process.env.NO_COLOR===void 0&&{FORCE_COLOR:`true`}},preferLocal:!0,reject:!1,stdin:`inherit`});if(i.outputFilter){let t=P(i.outputFilter),n=P(i.outputFilter);e.stdout.pipe(t).pipe(m,{end:!1}),e.stderr.pipe(n).pipe(m,{end:!1})}else e.stdout.pipe(m,{end:!1}),e.stderr.pipe(m,{end:!1});if(await e,i.prettyJsonOutput){m.end();let e=await I(m),t=w(JSON.parse(e)).split(`
5
- `);for(let e of t)c.write(`${e}\n`)}s=e.exitCode??1}catch(e){console.error(`${i.name} failed with error:`),console.error(e),C(e)&&(s=typeof e.exitCode==`number`?e.exitCode:1)}return s}function B(e){return`execute`in e}const V=/^ksc-/v;function H(e){return e.replace(V,``)}function U(e){return e===void 0||e.length===0?[]:e.flatMap(e=>e.split(`,`)).map(e=>H(e.trim()))}function W(e){return e.option(`skip`,{array:!0,describe:`Tool names to skip (with or without "ksc-" prefix).`,type:`string`})}async function G(e,t,n,r,i,a,o){let s=o??[],c=[],l=[];for(let e of r)s.length>0&&s.includes(H(e.name))?l.push(e):c.push(e);if(s.length>0){let t=new Set(l.map(e=>H(e.name))),n=s.filter(e=>!t.has(e));if(n.length>0){let t=r.map(e=>H(e.name)).join(`, `);e.write(`⚠️ ${d.yellow(`Unrecognized --skip ${L(`value`,n.length)}: ${n.join(`, `)}. Available: ${t}`)}\n`)}}let u=[];for(let r of c){let a=await(B(r)?R(e,t,n,r,i):z(e,t,n,r,i));u.push({exitCode:a,name:r.name})}let f=r.length;if(l.length>0){let t=l.map(({name:e})=>e),n=d.bold(`${t.length} / ${f} ${L(`Command`,t.length)} Skipped:`);e.write(`⏭️ ${d.dim(n)} ${d.dim(t.join(`, `))}\n`)}if(a){let t=u.filter(({exitCode:e})=>e===0).map(({name:e})=>e),n=u.filter(({exitCode:e})=>e!==0).map(({name:e})=>e);if(t.length>0){let n=d.bold(`${t.length} / ${f} ${L(`Command`,t.length)} Succeeded:`);e.write(`✅ ${d.green(n)} ${d.green(t.join(`, `))}\n`)}if(n.length>0){let t=d.bold(`${n.length} / ${f} ${L(`Command`,n.length)} Failed:`);e.write(`❌ ${d.red(t)} ${d.red(n.join(`, `))}\n`)}}return+!u.every(({exitCode:e})=>e===0)}async function K(e,t,n,o){let s=await l();if(s===void 0)throw Error("The `init` command must be used in a directory with a package.json file");let u=await l({cwd:c(import.meta.url)});if(u===void 0)return e.write(`Error: The script being called was not in a package, weird.
6
- `),1;let d=a.join(a.dirname(u),`init`),f=a.dirname(s),p=(t===`file`||t===`package`)&&n!==void 0&&o!==void 0;try{if(p){let n=Object.keys(o)[0],i=r.readJsonSync(s);if(t===`package`){e.write(`Merging: \nPackage config key "${n}" "${f}" (Because --location is set to "package")\n`);let t=E(i,o);r.writeJSONSync(s,t,{spaces:` `}),await M(s)}else n!==void 0&&Object.keys(i).includes(n)&&(e.write(`Deleting: \nPackage config key "${n}" in "${f}" (Because --location is set to "file")\n`),delete i[n],r.writeJSONSync(s,i,{spaces:` `}),await M(s))}if(!await r.pathExists(d))return 0;if((await r.readdir(d)).length===0)return e.write(`Source directory "${d}" is empty.\n`),0;e.write(`Adding initial configuration files from:\n"${d}" → "${f}"\n`),await r.copy(d,f,{async filter(o,s){let c=i.statSync(o).isFile(),l=i.existsSync(s);if(c){if(p&&t===`package`&&o.includes(n))return l?(e.write(`Deleting: \n"${o}" → "${s}" (Because --location is set to "package")\n`),r.removeSync(s)):e.write(`Skipping: \n"${o}" → "${s}" (Because --location is set to "package")\n`),!1;if(l&&(s.includes(`.vscode/`)||s.includes(`package.json`))&&a.extname(s)===`.json`){e.write(`Merging: \n"${o}" → "${s}"\n`);let t=r.readJSONSync(o),n=E(r.readJSONSync(s),t);return r.writeJSONSync(s,n,{spaces:` `}),await M(s),!1}return l?(e.write(`Overwriting: \n"${o}" "${s}"\n`),await M(s),!0):(e.write(`Copying: \n"${o}" → "${s}"\n`),await M(s),!0)}return!0},overwrite:!0})}catch(e){return console.error(String(e)),1}return 0}async function q(e){let{commands:{fix:t,init:n,lint:r,printConfig:i},description:a,logColor:o,logPrefix:s,name:c,showSummary:l,verbose:u}=e,d=F(s,o);d.pipe(process.stdout);let m=f(p(process.argv)).scriptName(c).usage(`$0 <command>`,a);n!==void 0&&m.command({builder(e){let t=n.locationOptionFlag?e.option(`location`,{choices:[`file`,`package`],default:`file`,describe:`Where to store the configuration.`,type:`string`}):e;return l?W(t):t},command:`init`,describe:n.description??`Initialize by copying starter config files to your project root${n.locationOptionFlag?` or to your package.json file.`:`.`}`,async handler(e){let t=n.locationOptionFlag?e.location:void 0,r=U(e.skip),i=await G(d,[],t===void 0?[]:[`--location`,t],[{async execute(e,t,r){return K(e,r.at(1),n.configFile,n.configPackageJson)},name:`copyAndMergeInitFiles`},...n.commands??[]],void 0,void 0,r);process.exitCode=i}}),r!==void 0&&m.command({builder(e){let t=r.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...r.positionalArgumentDefault!==void 0&&{default:r.positionalArgumentDefault},describe:`Files or glob pattern to lint.`,type:`string`});return l?W(t):t},command:r.positionalArgumentMode===`none`?`lint`:r.positionalArgumentMode===`optional`?`lint [files..]`:`lint <files..>`,describe:r.description,async handler(e){let t=e.files??[],n=U(e.skip),i=await G(d,t,[],r.commands,u,l,n);process.exitCode=i}}),t!==void 0&&m.command({builder(e){let n=t.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...t.positionalArgumentDefault!==void 0&&{default:t.positionalArgumentDefault},describe:`Files or glob pattern to fix.`,type:`string`});return l?W(n):n},command:t.positionalArgumentMode===`none`?`fix`:t.positionalArgumentMode===`optional`?`fix [files..]`:`fix <files..>`,describe:t.description,async handler(e){let n=e.files??[],r=U(e.skip),i=await G(d,n,[],t.commands,void 0,void 0,r);process.exitCode=i}}),i!==void 0&&m.command({builder(e){let t=i.positionalArgumentMode===`none`?e:e.positional(`file`,{...i.positionalArgumentDefault!==void 0&&{default:i.positionalArgumentDefault},describe:`File or glob pattern to print configuration for.`,type:`string`});return l?W(t):t},command:i.positionalArgumentMode===`none`?`print-config`:i.positionalArgumentMode===`optional`?`print-config [file]`:`print-config <file>`,describe:i.description,async handler(e){let t=e.file??void 0,n=t===void 0?[]:[t],r=U(e.skip),a=await G(d,n,[],i.commands,u,l,r);process.exitCode=a}}),m.alias(`h`,`help`),m.version(S),m.alias(`v`,`version`),m.help(),m.wrap(process.stdout.isTTY?Math.min(120,m.terminalWidth()):0),await m.parseAsync()}async function J(n){let r=e(n,{loaders:{".ts":t()},searchStrategy:`project`});try{let e=await r.search();if(e===null){console.error(`No ${n} configuration found.`);return}return e}catch(e){console.error(`Error while searching for ${n} configuration:`,e);return}}const Y={fileRun:`Matches files below the current working directory by default.`,monorepoRun:`In a monorepo, it will also run in all packages below the current working directory.`,monorepoSearch:`Searches up to the root of a monorepo if necessary.`,multiArgumentCaveat:`Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package scope.`,multiOptionCaveat:`Will use option flags where possible if provided, but some of the invoked tools will ignore them.`,optionalFileRun:`Package-scoped by default, file-scoped if a file argument is provided.`,packageRun:`Package-scoped.`,packageSearch:`Package-scoped.`},X=[`--ignore-path`,k(`.gitignore`)??`.gitignore`,`--allow-empty-input`],Z=`**/*.{${[`css`,`scss`,`sass`,`svelte`,`html`,`astro`,`tsx`,`jsx`,`php`,`vue`].join(`,`)}}`;async function Q(e,t){let n=`stylelint`,r=await J(n);if(r===void 0)return 1;let{filepath:i,isEmpty:o}=r;if(o)return e.write(`Configuration is empty.
7
- `),0;e.write(`Found ${n} configuration at "${i}"\n`);let s,[c]=t;c===void 0?s=A(`package-dir`):(s=a.join(process.cwd(),c),e.write(`Showing config for file at "${s}"\n`));let l=w(await x.resolveConfig(s)).split(`
8
- `);for(let t of l)e.write(`${t}\n`);return 0}await q({commands:{fix:{commands:[{name:`stylelint`,optionFlags:[...X,`--fix`],receivePositionalArguments:!0}],description:`Fix your project with Stylelint. ${Y.fileRun}`,positionalArgumentDefault:Z,positionalArgumentMode:`optional`},init:{configFile:`stylelint.config.js`,configPackageJson:{stylelint:{extends:`@kitschpatrol/stylelint-config`}},locationOptionFlag:!0},lint:{commands:[{name:`stylelint`,optionFlags:X,receivePositionalArguments:!0}],description:`Lint your project with Stylelint. ${Y.fileRun}`,positionalArgumentDefault:Z,positionalArgumentMode:`optional`},printConfig:{commands:[{execute:Q,name:Q.name}],description:`Print the effective Stylelint configuration. ${Y.optionalFileRun}.`,positionalArgumentMode:`optional`}},description:`Kitschpatrol's Stylelint shared configuration tools.`,logColor:`greenBright`,logPrefix:`[Stylelint]`,name:`ksc-stylelint`,order:5});export{};
2
+ import{cosmiconfig as e}from"cosmiconfig";import{TypeScriptLoader as t}from"cosmiconfig-typescript-loader";import{execa as n}from"execa";import r from"fs-extra";import i from"node:fs";import a from"node:path";import{PassThrough as o,Transform as s}from"node:stream";import{fileURLToPath as c}from"node:url";import{packageUp as l,packageUpSync as u}from"package-up";import d from"picocolors";import f from"yargs";import{hideBin as p}from"yargs/helpers";import{stripVTControlCharacters as m}from"node:util";import h from"@pinojs/json-colorizer";import g from"decircular";import _ from"deepmerge";import v from"json-stringify-pretty-compact";import{findWorkspacesRoot as y}from"find-workspaces";import b from"node:fs/promises";import ee from"stylelint";var te=`8.2.0`;function ne(e,t){let n=a.isAbsolute(e)?e:a.resolve(t,e),r=a.relative(process.cwd(),n);return r===``?`.`:r}const re=/\s*\n\s*/gv,ie=/\r?\n/v;function ae(e){let t=e.message.replaceAll(re,` `),n=e.rule===void 0?e.tool:`${e.tool}/${e.rule}`;return e.file===void 0?`${e.severity}: ${t} [${n}]`:`${e.file}:${e.line??1}:${e.column??1}: ${e.severity}: ${t} [${n}]`}function oe(e,t){let n=(e.file??`￿`).localeCompare(t.file??`￿`);if(n!==0)return n;let r=(e.line??0)-(t.line??0);return r===0?(e.column??0)-(t.column??0):r}function se(e,t){let n=t.toSorted(oe);return{cwd:process.cwd(),diagnostics:n,success:e.every(e=>e.exitCode===0),summary:{errors:n.filter(e=>e.severity===`error`).length,infos:n.filter(e=>e.severity===`info`).length,warnings:n.filter(e=>e.severity===`warning`).length},tools:e,version:1}}function x(e){return m(e).split(ie).map(e=>e.trimEnd()).filter(e=>e.trim().length>0)}function S(e){return e instanceof Error&&`exitCode`in e&&typeof e.exitCode==`number`}function C(e){return h(v(g(e),{indent:2,replacer(e,t){return typeof t==`function`?t.name:t}}),{colors:{BRACKET:`gray`}})}const w=(e,t,n)=>{let r=[...e];for(let[i,a]of t.entries())r[i]===void 0?r[i]=n.cloneUnlessOtherwiseSpecified(a,n):n.isMergeableObject(a)?r[i]=T(e[i],a,n):e.includes(a)||r.push(a);return r};function T(e,t,n={arrayMerge:w}){return _(e,t,n)}function E(e){let{tasks:t}=e;return Array.isArray(t)?t:[]}function ce(e,t){let n=[...E(e)];for(let e of E(t)){let t=n.findIndex(t=>t.label!==void 0&&t.label===e.label);t===-1?n.push(e):n[t]=e}return{...e,...t,tasks:n}}const D=[`json`,`machine`,`native`],le=D;function O(e){return typeof e==`string`&&D.includes(e)}function k(){let e=process.env.KSC_FORMAT;return O(e)?e:`native`}function ue(){let{argv:e}=process;for(let[t,n]of e.entries()){let r;n===`--format`?r=e[t+1]:n.startsWith(`--format=`)&&(r=n.slice(9)),O(r)&&(process.env.KSC_FORMAT=r)}}function A(){let e=u();if(e===void 0)throw Error(`No package.json found.`);return a.dirname(e)}function j(){let e=y();return e===null?A():a.resolve(e.location)}function de(e){let t=a.join(j(),e);if(r.existsSync(t))return t}function M(e){if(e===`workspace-root`)return j();if(e===`package-dir`)return A();if(typeof e==`string`){if(!r.pathExistsSync(e))throw Error(`Custom cwd directory does not exist: ${e}`);return e}return process.cwd()}async function fe(e,t){try{let{default:n}=await import(`prettier`),r=await n.resolveConfig(e),i=await n.format(t,{filepath:e,...r});await b.writeFile(e,i,`utf8`)}catch{console.warn(`Skipped formatting ${e} since Prettier is not installed.`)}}async function N(e){try{await fe(e,await b.readFile(e,`utf8`))}catch{}}const P=/\r?\n/v;function F(e){let t=``,n=t=>t.filter(t=>t.trim()!==``&&!e(m(t))).map(e=>`${e}\n`).join(``);return new s({flush(e){e(void 0,n([t]))},transform(e,r,i){let a=(t+e.toString()).split(P);t=a.pop()??``,i(void 0,n(a))}})}function I(e,t){let n=k()===`native`?e:void 0,r=n===void 0||n===``?``:t===void 0?n:d[t](n),i=``,a=e=>e.filter(e=>e.trim().length>0).map(e=>r===``?`${e}\n`:`${r} ${e}\n`).join(``);return new s({flush(e){e(void 0,a([i]))},transform(e,t,n){let r=(i+e.toString()).split(P);i=r.pop()??``,n(void 0,a(r))}})}async function L(e){let t=[];return new Promise((n,r)=>{e.on(`data`,e=>{t.push(e)}),e.on(`error`,e=>{r(e)}),e.on(`end`,()=>{n(Buffer.concat(t).toString(`utf8`))})})}function R(e,t){return t===1?e:e+`s`}async function z(e){return typeof e==`function`?e():e}async function B(e,t,n,r,i){let a;if(r.logPrefix===void 0)a=e;else{let t=I(r.logPrefix,r.logColor);t.pipe(e),a=t}i&&a.write(d.bold(`Running: "${r.name}() with Positional arguments: ${String(t)} and Option flags: ${String(n)}"`)+`
3
+ `);try{return await r.execute(a,t,n)}catch(e){return console.error(String(e)),1}}function V(e,t,n,r){return[...e.subcommands??[],...e.receiveOptionFlags?n:[],...r??[],...e.receivePositionalArguments?t:[],...e.positionalArguments??[]]}async function pe(e,t,r,i,a){let s=1,c;if(i.logPrefix===void 0)c=e;else{let t=I(i.logPrefix,i.logColor);t.pipe(e),c=t}let l=V(i,t,r,i.optionFlags),u=M(i.cwdOverride);a&&c.write(`Running: "${i.name} ${l.join(` `)}"\n`);let d=i.prettyJsonOutput?new o:c,f=k()===`native`?process.env.NO_COLOR===void 0?{FORCE_COLOR:`true`}:{}:{NO_COLOR:`1`};try{let e=n(i.name,l,{cwd:u,env:{...f},preferLocal:!0,reject:!1,stdin:`inherit`});if(i.outputFilter){let t=F(i.outputFilter),n=F(i.outputFilter);e.stdout.pipe(t).pipe(d,{end:!1}),e.stderr.pipe(n).pipe(d,{end:!1})}else e.stdout.pipe(d,{end:!1}),e.stderr.pipe(d,{end:!1});if(await e,i.prettyJsonOutput){d.end();let e=await L(d),t=C(JSON.parse(e)).split(`
4
+ `);for(let e of t)c.write(`${e}\n`)}s=e.exitCode??1}catch(e){console.error(`${i.name} failed with error:`),console.error(e),S(e)&&(s=typeof e.exitCode==`number`?e.exitCode:1)}return s}function H(e){return`execute`in e}async function U(e,t,r,i){let a=V(r,e,t,r.collect?.optionFlags??r.optionFlags),o=M(r.cwdOverride);try{let e=n(r.name,a,{cwd:o,env:{NO_COLOR:`1`},preferLocal:!0,reject:!1,stdin:`inherit`});i!==void 0&&e.stderr.pipe(i,{end:!1});let t=await e;return{cwd:o,exitCode:t.exitCode??1,stderr:t.stderr,stdout:t.stdout}}catch(e){return console.error(`${r.name} failed with error:`),console.error(e),{cwd:o,exitCode:S(e)&&typeof e.exitCode==`number`?e.exitCode:1,stderr:``,stdout:``}}}function me(e){return typeof e==`object`&&!!e&&`version`in e&&e.version===1&&`diagnostics`in e&&Array.isArray(e.diagnostics)&&`tools`in e&&Array.isArray(e.tools)}async function he(e,t,n,r){let i=Date.now(),a=()=>Date.now()-i;if(H(r)){if(r.collect!==void 0)try{let{diagnostics:e,exitCode:i,unparsed:o}=await r.collect(t,n);return{diagnostics:e,exitCode:i,tools:[{durationMs:a(),exitCode:i,name:r.name,unparsed:o}]}}catch(e){return{diagnostics:[],exitCode:1,tools:[{durationMs:a(),exitCode:1,name:r.name,unparsed:[String(e)]}]}}let e=``,i=new o;i.on(`data`,t=>{e+=t.toString()});let s;try{s=await r.execute(i,t,n)}catch(t){e+=`\n${String(t)}`,s=1}return{diagnostics:[],exitCode:s,tools:[{durationMs:a(),exitCode:s,name:r.name,unparsed:x(e)}]}}if(r.outputFormatAware){let i=await U(t,n,r,e);try{let e=JSON.parse(i.stdout);if(!me(e))throw Error(`Child output is not a lint report`);return{diagnostics:e.diagnostics,exitCode:i.exitCode,tools:e.tools}}catch{return{diagnostics:[],exitCode:i.exitCode,tools:[{durationMs:a(),exitCode:i.exitCode,name:r.name,unparsed:x(i.stdout)}]}}}let s=await U(t,n,r);if(r.collect!==void 0)try{let{diagnostics:e,unparsed:t}=r.collect.parse(s);return{diagnostics:e,exitCode:s.exitCode,tools:[{durationMs:a(),exitCode:s.exitCode,name:r.name,unparsed:t}]}}catch(e){return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:a(),exitCode:s.exitCode,name:r.name,unparsed:[...x(s.stdout),...x(s.stderr),String(e)]}]}}return{diagnostics:[],exitCode:s.exitCode,tools:[{durationMs:a(),exitCode:s.exitCode,name:r.name,unparsed:[...x(s.stdout),...x(s.stderr)]}]}}const ge=/^ksc-/v;function W(e){return e.replace(ge,``)}function G(e){return e===void 0||e.length===0?[]:e.flatMap(e=>e.split(`,`)).map(e=>W(e.trim()))}function K(e){return e.option(`skip`,{array:!0,describe:`Tool names to skip (with or without "ksc-" prefix).`,type:`string`})}function q(e){return e.option(`format`,{choices:le,default:`native`,describe:`Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report.`})}function _e(e,t){return t===`native`||t===`machine`&&!H(e)&&e.outputFormatAware===!0}function ve(e,t){for(let n of t.diagnostics)e.write(`${ae(n)}\n`);for(let n of t.tools)for(let t of n.unparsed)e.write(`${t}\n`)}function ye(e,t,n){let r=[],i=[];for(let e of t)n.length>0&&n.includes(W(e.name))?i.push(e):r.push(e);if(n.length>0){let r=new Set(i.map(e=>W(e.name))),a=n.filter(e=>!r.has(e));if(a.length>0){let n=t.map(e=>W(e.name)).join(`, `);e.write(`⚠️ ${d.yellow(`Unrecognized --skip ${R(`value`,a.length)}: ${a.join(`, `)}. Available: ${n}`)}\n`)}}return{commandsToRun:r,skippedCommands:i}}async function J(e,t,n,r,i,a,o,s=`native`){let{commandsToRun:c,skippedCommands:l}=ye(e,r,o??[]),u=[],f=[],p=[],m=s===`native`&&i;for(let r of c){if(_e(r,s)){let i=await(H(r)?B(e,t,n,r,m):pe(e,t,n,r,m));u.push({exitCode:i,name:r.name});continue}let i=await he(e,t,n,r);u.push({exitCode:i.exitCode,name:r.name}),f.push(...i.tools),p.push(...i.diagnostics),s===`machine`&&ve(e,i)}let h=r.length;if(s===`native`&&l.length>0){let t=l.map(({name:e})=>e),n=d.bold(`${t.length} / ${h} ${R(`Command`,t.length)} Skipped:`);e.write(`⏭️ ${d.dim(n)} ${d.dim(t.join(`, `))}\n`)}if(s===`native`&&a){let t=u.filter(({exitCode:e})=>e===0).map(({name:e})=>e),n=u.filter(({exitCode:e})=>e!==0).map(({name:e})=>e);if(t.length>0){let n=d.bold(`${t.length} / ${h} ${R(`Command`,t.length)} Succeeded:`);e.write(`✅ ${d.green(n)} ${d.green(t.join(`, `))}\n`)}if(n.length>0){let t=d.bold(`${n.length} / ${h} ${R(`Command`,n.length)} Failed:`);e.write(`❌ ${d.red(t)} ${d.red(n.join(`, `))}\n`)}}return{exitCode:+!u.every(({exitCode:e})=>e===0),report:s===`json`?se(f,p):void 0}}async function be(e,t,n,o){let s=await l();if(s===void 0)throw Error("The `init` command must be used in a directory with a package.json file");let u=await l({cwd:c(import.meta.url)});if(u===void 0)return e.write(`Error: The script being called was not in a package, weird.
5
+ `),1;let d=a.join(a.dirname(u),`init`),f=a.dirname(s),p=(t===`file`||t===`package`)&&n!==void 0&&o!==void 0;try{if(p){let n=Object.keys(o)[0],i=r.readJsonSync(s);if(t===`package`){e.write(`Merging: \nPackage config key "${n}" → "${f}" (Because --location is set to "package")\n`);let t=T(i,o);r.writeJSONSync(s,t,{spaces:` `}),await N(s)}else n!==void 0&&Object.keys(i).includes(n)&&(e.write(`Deleting: \nPackage config key "${n}" in "${f}" (Because --location is set to "file")\n`),delete i[n],r.writeJSONSync(s,i,{spaces:` `}),await N(s))}if(!await r.pathExists(d))return 0;if((await r.readdir(d)).length===0)return e.write(`Source directory "${d}" is empty.\n`),0;e.write(`Adding initial configuration files from:\n"${d}" → "${f}"\n`),await r.copy(d,f,{async filter(o,s){let c=i.statSync(o).isFile(),l=i.existsSync(s);if(c){if(p&&t===`package`&&o.includes(n))return l?(e.write(`Deleting: \n"${o}" "${s}" (Because --location is set to "package")\n`),r.removeSync(s)):e.write(`Skipping: \n"${o}" → "${s}" (Because --location is set to "package")\n`),!1;if(l&&(s.includes(`.vscode/`)||s.includes(`package.json`))&&a.extname(s)===`.json`){e.write(`Merging: \n"${o}" → "${s}"\n`);let t=r.readJSONSync(o),n=r.readJSONSync(s),i=s.endsWith(`.vscode/tasks.json`)?ce(n,t):T(n,t);return r.writeJSONSync(s,i,{spaces:` `}),await N(s),!1}return l?(e.write(`Overwriting: \n"${o}" "${s}"\n`),await N(s),!0):(e.write(`Copying: \n"${o}" "${s}"\n`),await N(s),!0)}return!0},overwrite:!0})}catch(e){return console.error(String(e)),1}return 0}async function Y(e){let{commands:{fix:t,init:n,lint:r,printConfig:i},description:a,logColor:o,logPrefix:s,name:c,showSummary:l,verbose:u}=e;ue();let d=I(s,o);d.pipe(k()===`json`?process.stderr:process.stdout);let m=f(p(process.argv)).scriptName(c).usage(`$0 <command>`,a);n!==void 0&&m.command({builder(e){let t=n.locationOptionFlag?e.option(`location`,{choices:[`file`,`package`],default:`file`,describe:`Where to store the configuration.`,type:`string`}):e;return l?K(t):t},command:`init`,describe:n.description??`Initialize by copying starter config files to your project root${n.locationOptionFlag?` or to your package.json file.`:`.`}`,async handler(e){let t=n.locationOptionFlag?e.location:void 0,r=G(e.skip),{exitCode:i}=await J(d,[],t===void 0?[]:[`--location`,t],[{async execute(e,t,r){return be(e,r.at(1),n.configFile,n.configPackageJson)},name:`copyAndMergeInitFiles`},...n.commands??[]],void 0,void 0,r);process.exitCode=i}}),r!==void 0&&m.command({builder(e){let t=q(r.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...r.positionalArgumentDefault!==void 0&&{default:r.positionalArgumentDefault},describe:`Files or glob pattern to lint.`,type:`string`}));return l?K(t):t},command:r.positionalArgumentMode===`none`?`lint`:r.positionalArgumentMode===`optional`?`lint [files..]`:`lint <files..>`,describe:r.description,async handler(e){let t=e.files??[],n=G(e.skip),i=k(),{exitCode:a,report:o}=await J(d,t,[],await z(r.commands),u,l,n,i);o!==void 0&&process.stdout.write(`${JSON.stringify(o,void 0,` `)}\n`),process.exitCode=a}}),t!==void 0&&m.command({builder(e){let n=q(t.positionalArgumentMode===`none`?e:e.positional(`files`,{array:!0,...t.positionalArgumentDefault!==void 0&&{default:t.positionalArgumentDefault},describe:`Files or glob pattern to fix.`,type:`string`}));return l?K(n):n},command:t.positionalArgumentMode===`none`?`fix`:t.positionalArgumentMode===`optional`?`fix [files..]`:`fix <files..>`,describe:t.description,async handler(e){let n=e.files??[],r=G(e.skip),i=k(),{exitCode:a,report:o}=await J(d,n,[],await z(t.commands),void 0,void 0,r,i);o!==void 0&&process.stdout.write(`${JSON.stringify(o,void 0,` `)}\n`),process.exitCode=a}}),i!==void 0&&m.command({builder(e){let t=i.positionalArgumentMode===`none`?e:e.positional(`file`,{...i.positionalArgumentDefault!==void 0&&{default:i.positionalArgumentDefault},describe:`File or glob pattern to print configuration for.`,type:`string`});return l?K(t):t},command:i.positionalArgumentMode===`none`?`print-config`:i.positionalArgumentMode===`optional`?`print-config [file]`:`print-config <file>`,describe:i.description,async handler(e){let t=e.file??void 0,n=t===void 0?[]:[t],r=G(e.skip),{exitCode:a}=await J(d,n,[],await z(i.commands),u,l,r);process.exitCode=a}}),m.alias(`h`,`help`),m.version(te),m.alias(`v`,`version`),m.help(),m.wrap(process.stdout.isTTY?Math.min(120,m.terminalWidth()):0),await m.parseAsync()}async function xe(n){let r=e(n,{loaders:{".ts":t()},searchStrategy:`project`});try{let e=await r.search();if(e===null){console.error(`No ${n} configuration found.`);return}return e}catch(e){console.error(`Error while searching for ${n} configuration:`,e);return}}const X={fileRun:`Matches files below the current working directory by default.`,monorepoRun:`In a monorepo, it will also run in all packages below the current working directory.`,monorepoSearch:`Searches up to the root of a monorepo if necessary.`,multiArgumentCaveat:`Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package scope.`,multiOptionCaveat:`Will use option flags where possible if provided, but some of the invoked tools will ignore them.`,optionalFileRun:`Package-scoped by default, file-scoped if a file argument is provided.`,packageRun:`Package-scoped.`,packageSearch:`Package-scoped.`},Z=[`--ignore-path`,de(`.gitignore`)??`.gitignore`,`--allow-empty-input`],Q=`**/*.{${[`css`,`scss`,`sass`,`svelte`,`html`,`astro`,`tsx`,`jsx`,`php`,`vue`].join(`,`)}}`;function $(e){let t;try{t=JSON.parse(e.stderr)}catch{return{diagnostics:[],unparsed:[...x(e.stdout),...x(e.stderr)]}}let n=[];for(let r of t){let t=ne(r.source,e.cwd);for(let e of r.warnings){let r=e.rule===void 0?void 0:` (${e.rule})`,i=r!==void 0&&e.text.endsWith(r)?e.text.slice(0,-r.length):e.text;n.push({column:e.column,endColumn:e.endColumn,endLine:e.endLine,file:t,line:e.line,message:i,rule:e.rule,severity:e.severity===`warning`?`warning`:`error`,tool:`stylelint`})}let i=r.parseErrors??[];for(let e of i)n.push({column:e.column,file:t,line:e.line,message:e.text,rule:`parse-error`,severity:`error`,tool:`stylelint`})}return{diagnostics:n,unparsed:x(e.stdout)}}async function Se(e,t){let n=`stylelint`,r=await xe(n);if(r===void 0)return 1;let{filepath:i,isEmpty:o}=r;if(o)return e.write(`Configuration is empty.
6
+ `),0;e.write(`Found ${n} configuration at "${i}"\n`);let s,[c]=t;c===void 0?s=M(`package-dir`):(s=a.join(process.cwd(),c),e.write(`Showing config for file at "${s}"\n`));let l=C(await ee.resolveConfig(s)).split(`
7
+ `);for(let t of l)e.write(`${t}\n`);return 0}await Y({commands:{fix:{commands:[{collect:{optionFlags:[...Z,`--fix`,`--formatter`,`json`],parse:$},name:`stylelint`,optionFlags:[...Z,`--fix`],receivePositionalArguments:!0}],description:`Fix your project with Stylelint. ${X.fileRun}`,positionalArgumentDefault:Q,positionalArgumentMode:`optional`},init:{configFile:`stylelint.config.js`,configPackageJson:{stylelint:{extends:`@kitschpatrol/stylelint-config`}},locationOptionFlag:!0},lint:{commands:[{collect:{optionFlags:[...Z,`--formatter`,`json`],parse:$},name:`stylelint`,optionFlags:Z,receivePositionalArguments:!0}],description:`Lint your project with Stylelint. ${X.fileRun}`,positionalArgumentDefault:Q,positionalArgumentMode:`optional`},printConfig:{commands:[{execute:Se,name:`stylelint-config`}],description:`Print the effective Stylelint configuration. ${X.optionalFileRun}.`,positionalArgumentMode:`optional`}},description:`Kitschpatrol's Stylelint shared configuration tools.`,logColor:`greenBright`,logPrefix:`[Stylelint]`,name:`ksc-stylelint`,order:5});export{};
@@ -0,0 +1,73 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "label": "ksc-stylelint lint",
6
+ "detail": "Lint your project with Stylelint.",
7
+ "type": "shell",
8
+ "command": "pnpm exec ksc-stylelint lint --format machine",
9
+ "options": {
10
+ "cwd": "${workspaceFolder}"
11
+ },
12
+ "presentation": {
13
+ "clear": true,
14
+ "echo": true,
15
+ "focus": false,
16
+ "panel": "dedicated",
17
+ "reveal": "silent",
18
+ "revealProblems": "onProblem",
19
+ "showReuseMessage": false
20
+ },
21
+ "problemMatcher": [
22
+ {
23
+ "owner": "ksc",
24
+ "source": "ksc",
25
+ "fileLocation": ["relative", "${workspaceFolder}"],
26
+ "pattern": {
27
+ "regexp": "^(.+?):(\\d+):(\\d+): (error|warning|info): (.+) \\[([^\\]]+)\\]$",
28
+ "file": 1,
29
+ "line": 2,
30
+ "column": 3,
31
+ "severity": 4,
32
+ "message": 5,
33
+ "code": 6
34
+ }
35
+ }
36
+ ]
37
+ },
38
+ {
39
+ "label": "ksc-stylelint fix",
40
+ "detail": "Fix your project with Stylelint.",
41
+ "type": "shell",
42
+ "command": "pnpm exec ksc-stylelint fix --format machine",
43
+ "options": {
44
+ "cwd": "${workspaceFolder}"
45
+ },
46
+ "presentation": {
47
+ "clear": true,
48
+ "echo": true,
49
+ "focus": false,
50
+ "panel": "dedicated",
51
+ "reveal": "silent",
52
+ "revealProblems": "onProblem",
53
+ "showReuseMessage": false
54
+ },
55
+ "problemMatcher": [
56
+ {
57
+ "owner": "ksc",
58
+ "source": "ksc",
59
+ "fileLocation": ["relative", "${workspaceFolder}"],
60
+ "pattern": {
61
+ "regexp": "^(.+?):(\\d+):(\\d+): (error|warning|info): (.+) \\[([^\\]]+)\\]$",
62
+ "file": 1,
63
+ "line": 2,
64
+ "column": 3,
65
+ "severity": 4,
66
+ "message": 5,
67
+ "code": 6
68
+ }
69
+ }
70
+ ]
71
+ }
72
+ ]
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitschpatrol/stylelint-config",
3
- "version": "8.1.0",
3
+ "version": "8.2.0",
4
4
  "description": "Stylelint configuration for @kitschpatrol/shared-config.",
5
5
  "keywords": [
6
6
  "stylelint-config",
package/readme.md CHANGED
@@ -181,10 +181,11 @@ ksc-stylelint lint [files..]
181
181
  | ------------------- | ------------------------------ | ------- | ---------------------------------------------------------- |
182
182
  | `files` | Files or glob pattern to lint. | `array` | `"**/*.{css,scss,sass,svelte,html,astro,tsx,jsx,php,vue}"` |
183
183
 
184
- | Option | Description | Type |
185
- | ------------------- | ------------------- | --------- |
186
- | `--help`<br>`-h` | Show help | `boolean` |
187
- | `--version`<br>`-v` | Show version number | `boolean` |
184
+ | Option | Description | Type | Default |
185
+ | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ---------- |
186
+ | `--format` | Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report. | `"json"` `"machine"` `"native"` | `"native"` |
187
+ | `--help`<br>`-h` | Show help | `boolean` | |
188
+ | `--version`<br>`-v` | Show version number | `boolean` | |
188
189
 
189
190
  #### Subcommand: `ksc-stylelint fix`
190
191
 
@@ -200,10 +201,11 @@ ksc-stylelint fix [files..]
200
201
  | ------------------- | ----------------------------- | ------- | ---------------------------------------------------------- |
201
202
  | `files` | Files or glob pattern to fix. | `array` | `"**/*.{css,scss,sass,svelte,html,astro,tsx,jsx,php,vue}"` |
202
203
 
203
- | Option | Description | Type |
204
- | ------------------- | ------------------- | --------- |
205
- | `--help`<br>`-h` | Show help | `boolean` |
206
- | `--version`<br>`-v` | Show version number | `boolean` |
204
+ | Option | Description | Type | Default |
205
+ | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ---------- |
206
+ | `--format` | Output format: "native" streams each tool's own output, "machine" prints one parseable line per issue for editor problem matchers, "json" prints an aggregate report. | `"json"` `"machine"` `"native"` | `"native"` |
207
+ | `--help`<br>`-h` | Show help | `boolean` | |
208
+ | `--version`<br>`-v` | Show version number | `boolean` | |
207
209
 
208
210
  #### Subcommand: `ksc-stylelint print-config`
209
211
 
@@ -226,6 +228,26 @@ ksc-stylelint print-config [file]
226
228
 
227
229
  <!-- /cli-help -->
228
230
 
231
+ ### VS Code tasks
232
+
233
+ `ksc-stylelint init` adds a `.vscode/tasks.json` with two tasks:
234
+
235
+ - **`ksc-stylelint lint`** runs `ksc-stylelint lint --format machine` across the whole project
236
+ - **`ksc-stylelint fix`** runs `ksc-stylelint fix --format machine`, applying auto-fixes and reporting whatever couldn't be fixed
237
+
238
+ If you're using the complete [@kitschpatrol/shared-config](https://github.com/kitschpatrol/shared-config) package, you'd more likely want to run:
239
+
240
+ - **`ksc lint`** runs `ksc lint --format machine`, which runs all `ksc lint` tools across the whole project
241
+ - **`ksc fix`** runs `ksc fix --format machine`, which applies all `ksc fix` auto-fixes and reports anything unfixable
242
+
243
+ Run them via the _Tasks: Run Task_ command (or the _Terminal → Run Task…_ menu item).
244
+
245
+ Each task's problem matcher parses the machine-format output and populates VS Code's [Problems panel](https://code.visualstudio.com/docs/debugtest/debugging#_errors-and-warnings) with every reported issue, pointing to the offending file, line, and column.
246
+
247
+ The tasks share a problem matcher owner with the other `@kitschpatrol/shared-config` tasks, so the panel reflects the most recent run rather than stacking duplicates.
248
+
249
+ If your project already has a `.vscode/tasks.json`, `init` merges by task label: your own tasks are left alone, and same-label tasks are replaced with the latest definitions.
250
+
229
251
  ### API
230
252
 
231
253
  The package also exports `fix`, `fixFile` functions for linting and fixing CSS programmatically, pre-configured with the shared Stylelint configuration.