yummaui 0.2.0 → 0.2.1

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/cli.mjs +6 -6
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import e from"picocolors";import{spawnSync as t}from"node:child_process";import{existsSync as n,mkdirSync as r,readFileSync as i,readdirSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,relative as u,resolve as d,sep as f}from"node:path";import*as p from"@clack/prompts";var m=`0.2.0`;const h=`https://yummacss.com/ui/r`;var g=class extends Error{};async function _(e){let t;try{t=await fetch(e,{headers:{accept:`application/json`}})}catch(t){throw new g(`Could not reach the registry at ${e}. Are you online?`,{cause:t})}if(t.status===404)throw new g(`Not found: ${e}`);if(!t.ok)throw new g(`Registry returned ${t.status} for ${e}`);try{return await t.json()}catch(t){throw new g(`Registry sent invalid JSON from ${e}`,{cause:t})}}function v(e){return _(`${e}/index.json`)}function y(e,t){return _(`${e}/${t}.json`)}const b=`yummaui.json`,x={"pnpm-lock.yaml":`pnpm`,"bun.lockb":`bun`,"bun.lock":`bun`,"yarn.lock":`yarn`,"package-lock.json":`npm`};function S(e=process.cwd()){let t=d(e);for(;;){if(n(l(t,`package.json`)))return t;let e=c(t);if(e===t)return null;t=e}}function C(e){try{return JSON.parse(i(l(e,`package.json`),`utf8`))}catch{return{}}}function w(e){for(let[t,r]of Object.entries(x))if(n(l(e,t)))return r;let t=C(e).packageManager;if(typeof t==`string`){let e=t.split(`@`)[0];if(e===`pnpm`||e===`npm`||e===`yarn`||e===`bun`)return e}return`npm`}function T(e){let t=C(e),r={...t.dependencies,...t.devDependencies};return r.next?[`app`,`src/app`].some(t=>n(l(e,t)))?`Next.js (App Router)`:`Next.js (Pages Router)`:r.astro?`Astro`:r[`react-router`]||r[`@remix-run/react`]?`React Router`:r.vite?`Vite`:null}function E(e){for(let t of[`tsconfig.json`,`jsconfig.json`]){let r=l(e,t);if(n(r))try{let e=i(r,`utf8`).replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|\s)\/\/.*$/gm,`$1`);if(JSON.parse(e)?.compilerOptions?.paths?.[`@/*`])return`@`}catch{}}return null}function D(e){return l(e,b)}function O(e){let t=D(e);if(!n(t))return null;try{let e=JSON.parse(i(t,`utf8`));return{componentsDir:e.componentsDir??`components/ui`,alias:e.alias??null,registry:e.registry??h}}catch{return null}}function k(e,t){s(D(e),`${JSON.stringify(t,null,` `)}\n`)}function A(e,t){let n=C(e),r=new Set([...Object.keys(n.dependencies??{}),...Object.keys(n.devDependencies??{}),...Object.keys(n.peerDependencies??{})]);return t.filter(e=>!r.has(e.name))}function j(e,t){return{command:e,args:e===`npm`?[`install`,...t]:[`add`,...t]}}function M(e=S()){switch(e?w(e):`npm`){case`pnpm`:return`pnpm dlx yummaui`;case`yarn`:return`yarn dlx yummaui`;case`bun`:return`bunx yummaui`;default:return`npx yummaui`}}function N(e){let t=[],n={all:!1,overwrite:!1,yes:!1};for(let r=0;r<e.length;r++){let i=e[r];i===`--all`||i===`-a`?n.all=!0:i===`--overwrite`?n.overwrite=!0:i===`--yes`||i===`-y`?n.yes=!0:i.startsWith(`-`)||t.push(i)}return{names:t,options:n}}function ee(e,t,n){return n===`base`?`${t}.tsx`:`${e}.tsx`}function P(e,t,n={}){let r=[];n.all&&r.push(...e.components.map(e=>e.base));for(let n of t){let t=e.components.find(e=>e.component===n);if(t){r.push(t.base);continue}let i=e.blocks.find(e=>e.id===n);if(i){r.push(i.id);continue}return{unknown:n}}return{ids:[...new Set(r)]}}async function F(i){let{names:a,options:o}=N(i),d=S();if(!d)return p.log.error(`No package.json found. Run this inside a project.`),1;let f=d,m=O(f);if(!m)return p.log.error(`No ${b} found. Run ${e.cyan(`${M(f)} init`)} first.`),1;let{registry:h,componentsDir:_}=m;if(a.length===0&&!o.all)return p.log.error(`Nothing to add. Try: ${M(f)} add button`),1;p.intro(e.bgCyan(e.black(` Yumma UI `)));let x,C=p.spinner();C.start(`Fetching registry`);try{x=await v(m.registry)}catch(e){return C.stop(`Registry unavailable`,1),p.log.error(e instanceof g?e.message:String(e)),1}C.stop(`${x.components.length} components, ${x.blocks.length} blocks available`);let T=P(x,a,{all:o.all});if(`unknown`in T)return p.log.error(`Unknown component or block ${e.bold(T.unknown)}.`),T.unknown===`all`?p.log.info(`Every component is ${e.cyan(`--all`)}.`):L(x,T.unknown),1;let E=T.ids,D=[],k=new Map,F=new Set;async function I(e,t){if(F.has(e))return!0;F.add(e);let i;try{i=await y(h,e)}catch(e){return p.log.error(e instanceof g?e.message:String(e)),!1}for(let e of i.registryDependencies)if(!await I(e,!1))return!1;let a=l(f,_,ee(i.id,i.component,i.variant)),d=u(f,a).replace(/\\/g,`/`);if(n(a)&&!o.overwrite){if(!t||o.yes)return p.log.warn(`Skipped ${d} (already exists)`),!0;let e=await p.confirm({message:`${d} already exists. Overwrite?`,initialValue:!1});if(p.isCancel(e))return p.cancel(`Cancelled.`),!1;if(!e)return p.log.warn(`Skipped ${d}`),!0}let m=i.files[0];if(!m)return p.log.error(`${e} has no files.`),!1;r(c(a),{recursive:!0}),s(a,m.content),D.push(d);for(let e of i.dependencies)k.set(e.name,e.version);return!0}for(let e of E)if(!await I(e,!0))return 1;if(D.length===0)return p.outro(`Nothing written.`),0;p.log.success(`Added\n${D.map(e=>` ${e}`).join(`
3
- `)}`);let R=A(f,[...k].map(([e,t])=>({name:e,version:t}))),z=[...k.keys()].filter(e=>!R.some(t=>t.name===e));if(k.size>0){let t=[...z.map(t=>` ${e.green(`✔`)} ${t} ${e.dim(`already installed`)}`),...R.map(t=>` ${e.yellow(`+`)} ${t.name}@${t.version}`)];p.log.info(`Dependencies\n${t.join(`
4
- `)}`)}if(R.length>0){let n=w(f),r=R.map(e=>`${e.name}@${e.version}`),i=o.yes;if(!i){let t=await p.confirm({message:`Install ${R.length} missing package${R.length>1?`s`:``} with ${e.bold(n)}?`});if(p.isCancel(t))return p.cancel(`Cancelled.`),1;i=t}if(i){let{command:e,args:i}=j(n,r),a=t(e,i,{cwd:f,stdio:`inherit`,shell:process.platform===`win32`});if(a.status!==0)return p.log.error(`${e} exited with ${a.status??`an error`}.`),1}else p.log.info(`Install manually:\n ${w(f)} add ${r.join(` `)}`)}return p.outro(`Done.`),0}function I(e,t){let n=Array.from({length:t.length+1},(e,t)=>t);for(let r=1;r<=e.length;r++){let i=[r];for(let a=1;a<=t.length;a++){let o=e[r-1]===t[a-1]?0:1;i[a]=Math.min(i[a-1]+1,n[a]+1,n[a-1]+o)}n=i}return n[t.length]}function L(e,t){let n=[...e.components.map(e=>e.component),...e.blocks.map(e=>e.id)].map(e=>({name:e,score:e.includes(t)||t.includes(e)?0:I(e,t)})).filter(e=>e.score<=2).sort((e,t)=>e.score-t.score).slice(0,5).map(e=>e.name);n.length?p.log.info(`Did you mean: ${n.join(`, `)}`):p.log.info(`Run ${M()} list to see everything.`)}async function R(t){let n=t.includes(`--force`),r=S();if(!r)return p.log.error(`No package.json found. Run this inside a project.`),1;if(p.intro(e.bgCyan(e.black(` Yumma UI `))),O(r)&&!n)return p.log.warn(`${b} already exists. Use --force to overwrite.`),p.outro(`Nothing to do.`),0;let i=T(r),a=w(r),o=E(r);p.log.step([i?`Detected ${e.bold(i)}`:`No framework detected`,`Detected ${e.bold(a)}`].join(`
5
- `));let s=await p.text({message:`Where should components go?`,placeholder:`components/ui`,defaultValue:`components/ui`});if(p.isCancel(s))return z();let c=!1;if(o){let t=await p.confirm({message:`Use the ${e.bold(`"${o}/"`)} import alias?`});if(p.isCancel(t))return z();c=t}return k(r,{componentsDir:String(s),alias:c&&o?`${o}/${s}`:null,registry:h}),p.log.success(`Wrote ${e.bold(D(r))}`),p.outro(`Next: ${e.cyan(`${M(r)} add button`)}`),0}function z(){return p.cancel(`Cancelled.`),1}async function B(t){let n=t.find(e=>!e.startsWith(`-`)),r=S(),i=r&&O(r)?.registry||h,a;try{a=await v(i)}catch(t){return console.error(e.red(t instanceof g?t.message:String(t))),1}if(n){let t=a.components.find(e=>e.component===n);if(!t)return console.error(e.red(`Unknown component ${n}.`)),1;let i=a.blocks.filter(e=>e.component===n);if(console.log(`\n${e.bold(t.title)} ${e.dim(t.component)}\n`),console.log(` ${e.dim(`${M(r)} add ${t.component}`)}\n`),console.log(` ${e.dim(`Every variation is a prop. Read its API at`)} ${e.cyan(`https://yummacss.com/ui/components/${t.component}`)}\n`),i.length){console.log(` ${e.bold(`${i.length} block${i.length>1?`s`:``} built on it`)}`);for(let t of i)console.log(` ${t.id.padEnd(26)}${e.dim(`add ${t.id}`)}`);console.log()}return 0}console.log(`\n${e.bold(`${a.components.length} components`)}\n`);let o=a.components.map(e=>e.component);for(let e=0;e<o.length;e+=2)console.log(` ${(o[e]??``).padEnd(24)}${o[e+1]??``}`);console.log(`\n${e.bold(`${a.blocks.length} blocks`)}\n`);let s=a.blocks.map(e=>e.id);for(let e=0;e<s.length;e+=2)console.log(` ${(s[e]??``).padEnd(30)}${s[e+1]??``}`);return console.log(`\n ${e.dim(`${M(r)} list <component>`)} to see its blocks\n`),0}const V=new Set([`.astro`,`.cjs`,`.cts`,`.js`,`.jsx`,`.md`,`.mdx`,`.mjs`,`.mts`,`.svelte`,`.ts`,`.tsx`,`.vue`]),H=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mjs`,`.cjs`,`.mts`,`.cts`],U=new Set([`.cache`,`.git`,`.next`,`.output`,`.svelte-kit`,`.turbo`,`.vercel`,`build`,`coverage`,`dist`,`node_modules`,`out`]),W=[/\bfrom\s*["']([^"'\n]+)["']/g,/\bimport\s*\(\s*["']([^"'\n]+)["']/g,/\brequire\s*\(\s*["']([^"'\n]+)["']/g,/\bimport\s+["']([^"'\n]+)["']/g];function G(e){let t=new Set;for(let n of W){n.lastIndex=0;for(let r of e.matchAll(n))r[1]&&t.add(r[1])}return[...t]}const K=/\b(?:from|import\s*\(|require\s*\()\s*`/;function q(e){return K.test(e)}function J(e){let t=e.split(f).join(`/`).replace(/^\.\//,``);for(let e of H)if(t.endsWith(e))return t.slice(0,-e.length);return t}function Y(e,t,n){let r=d(n.root,n.componentsDir);if(n.alias){let t=`${n.alias}/`;if(e===n.alias)return`index`;if(e.startsWith(t)){let n=e.slice(t.length);return n?J(n):`index`}}if(!e.startsWith(`.`))return null;let i=u(r,d(c(t),e));return i?i===`..`||i.startsWith(`..${f}`)?null:J(i):`index`}function X(e,t){return J(u(d(t.root,t.componentsDir),e))}function Z(e,t,n=[]){let r;try{r=a(e,{withFileTypes:!0})}catch{return n}for(let i of r){let r=l(e,i.name);if(i.isDirectory()){if(U.has(i.name)||r===t)continue;Z(r,t,n)}else if(i.isFile()){let e=i.name.lastIndexOf(`.`);e>0&&V.has(i.name.slice(e))&&n.push(r)}}return n}function Q(e){let t=new Set;for(let n of e.components)t.add(`${n.component}.tsx`);for(let n of e.blocks)t.add(`${n.id}.tsx`);return t}function te(e,t){let n=d(e.root,e.componentsDir),r=Z(n,``),a=Z(e.root,n),o=new Map,s=new Set,c=new Map,l=[];for(let n of r){let r=X(n,e);n.endsWith(`.tsx`)&&!r.includes(`/`)&&t.has(`${r}.tsx`)?o.set(r,n):s.add(r);let a=i(n,`utf8`);q(a)&&l.push(n);let u=new Set;for(let t of G(a)){let r=Y(t,n,e);r&&u.add(r)}c.set(r,u)}for(let t of a){let n=i(t,`utf8`);q(n)&&l.push(t);for(let r of G(n)){let n=Y(r,t,e);n&&s.add(n)}}let u=new Set,f=[...s];for(;f.length>0;){let e=f.pop();if(!u.has(e)){u.add(e);for(let t of c.get(e)??[])u.has(t)||f.push(t)}}let p=[];for(let[e,t]of o)u.has(e)||p.push(t);return{unused:p.sort(),kept:o.size-p.length,foreign:r.length-o.size,scanned:r.length+a.length,computed:l}}function ne(e){return{write:e.includes(`--write`),yes:e.includes(`--yes`)||e.includes(`-y`)}}async function re(t){let n=ne(t),r=S();if(!r)return p.log.error(`No package.json found. Run this inside a project.`),1;let i=O(r);if(!i)return p.log.error(`No ${b} found. Run ${e.cyan(`${M(r)} init`)} first.`),1;p.intro(e.bgCyan(e.black(` Yumma UI `)));let a,s=p.spinner();s.start(`Fetching registry`);try{a=await v(i.registry)}catch(e){return s.stop(`Registry unavailable`,1),p.log.error(e instanceof g?e.message:String(e)),1}s.stop(`Reading the project`);let c=te({root:r,componentsDir:i.componentsDir,alias:i.alias},Q(a)),l=e=>u(r,e).replace(/\\/g,`/`);if(c.computed.length>0&&p.log.warn(`Imports built at runtime in ${c.computed.length} file${c.computed.length>1?`s`:``}; anything they name is invisible here:\n${c.computed.slice(0,5).map(e=>` ${l(e)}`).join(`
2
+ import e from"picocolors";import{spawnSync as t}from"node:child_process";import{existsSync as n,mkdirSync as r,readFileSync as i,readdirSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,relative as u,resolve as d,sep as f}from"node:path";import*as p from"@clack/prompts";var m=`0.2.1`;const h=`https://yummacss.com/ui/r`;var g=class extends Error{};async function _(e){let t;try{t=await fetch(e,{headers:{accept:`application/json`}})}catch(t){throw new g(`Could not reach the registry at ${e}. Are you online?`,{cause:t})}if(t.status===404)throw new g(`Not found: ${e}`);if(!t.ok)throw new g(`Registry returned ${t.status} for ${e}`);try{return await t.json()}catch(t){throw new g(`Registry sent invalid JSON from ${e}`,{cause:t})}}function v(e){return _(`${e}/index.json`)}function ee(e,t){return _(`${e}/${t}.json`)}const y=`yummaui.json`,b={"pnpm-lock.yaml":`pnpm`,"bun.lockb":`bun`,"bun.lock":`bun`,"yarn.lock":`yarn`,"package-lock.json":`npm`};function x(e=process.cwd()){let t=d(e);for(;;){if(n(l(t,`package.json`)))return t;let e=c(t);if(e===t)return null;t=e}}function S(e){try{return JSON.parse(i(l(e,`package.json`),`utf8`))}catch{return{}}}function C(e){for(let[t,r]of Object.entries(b))if(n(l(e,t)))return r;let t=S(e).packageManager;if(typeof t==`string`){let e=t.split(`@`)[0];if(e===`pnpm`||e===`npm`||e===`yarn`||e===`bun`)return e}return`npm`}function w(e){let t=S(e),r={...t.dependencies,...t.devDependencies};return r.next?[`app`,`src/app`].some(t=>n(l(e,t)))?`Next.js (App Router)`:`Next.js (Pages Router)`:r.astro?`Astro`:r[`react-router`]||r[`@remix-run/react`]?`React Router`:r.vite?`Vite`:null}function T(e){for(let t of[`tsconfig.json`,`jsconfig.json`]){let r=l(e,t);if(n(r))try{let e=i(r,`utf8`).replace(/\/\*[\s\S]*?\*\//g,``).replace(/(^|\s)\/\/.*$/gm,`$1`);if(JSON.parse(e)?.compilerOptions?.paths?.[`@/*`])return`@`}catch{}}return null}function E(e){return l(e,y)}function D(e){let t=E(e);if(!n(t))return null;try{let e=JSON.parse(i(t,`utf8`));return{componentsDir:e.componentsDir??`components/ui`,alias:e.alias??null,registry:e.registry??h}}catch{return null}}function O(e,t){s(E(e),`${JSON.stringify(t,null,` `)}\n`)}function k(e,t){let n=S(e),r=new Set([...Object.keys(n.dependencies??{}),...Object.keys(n.devDependencies??{}),...Object.keys(n.peerDependencies??{})]);return t.filter(e=>!r.has(e.name))}function A(e,t){return{command:e,args:e===`npm`?[`install`,...t]:[`add`,...t]}}function j(e=x()){switch(e?C(e):`npm`){case`pnpm`:return`pnpm dlx yummaui`;case`yarn`:return`yarn dlx yummaui`;case`bun`:return`bunx yummaui`;default:return`npx yummaui`}}function M(e){let t=[],n={all:!1,overwrite:!1,yes:!1};for(let r=0;r<e.length;r++){let i=e[r];i===`--all`||i===`-a`?n.all=!0:i===`--overwrite`?n.overwrite=!0:i===`--yes`||i===`-y`?n.yes=!0:i.startsWith(`-`)||t.push(i)}return{names:t,options:n}}function N(e,t,n){return n===`base`?`${t}.tsx`:`${e}.tsx`}function P(e,t,n={}){let r=[];n.all&&r.push(...e.components.map(e=>e.base));for(let n of t){let t=e.components.find(e=>e.component===n);if(t){r.push(t.base);continue}let i=e.blocks.find(e=>e.id===n);if(i){r.push(i.id);continue}return{unknown:n}}return{ids:[...new Set(r)]}}async function F(i){let{names:a,options:o}=M(i),d=x();if(!d)return p.log.error(`No package.json found. Run this inside a project.`),1;let f=d,m=D(f);if(!m)return p.log.error(`No ${y} found. Run ${e.cyan(`${j(f)} init`)} first.`),1;let{registry:h,componentsDir:_}=m;if(a.length===0&&!o.all)return p.log.error(`Nothing to add. Try: ${j(f)} add button`),1;p.intro(e.bgCyan(e.black(` Yumma UI `)));let b,S=p.spinner();S.start(`Fetching registry`);try{b=await v(m.registry)}catch(e){return S.stop(`Registry unavailable`,1),p.log.error(e instanceof g?e.message:String(e)),1}S.stop(`${b.components.length} components, ${b.blocks.length} blocks available`);let w=P(b,a,{all:o.all});if(`unknown`in w)return p.log.error(`Unknown component or block ${e.bold(w.unknown)}.`),w.unknown===`all`?p.log.info(`Every component is ${e.cyan(`--all`)}.`):L(b,w.unknown),1;let T=w.ids,E=[],O=new Map,F=new Set;async function I(e,t){if(F.has(e))return!0;F.add(e);let i;try{i=await ee(h,e)}catch(e){return p.log.error(e instanceof g?e.message:String(e)),!1}for(let e of i.registryDependencies)if(!await I(e,!1))return!1;let a=l(f,_,N(i.id,i.component,i.variant)),d=u(f,a).replace(/\\/g,`/`);if(n(a)&&!o.overwrite){if(!t||o.yes)return p.log.warn(`Skipped ${d} (already exists)`),!0;let e=await p.confirm({message:`${d} already exists. Overwrite?`,initialValue:!1});if(p.isCancel(e))return p.cancel(`Cancelled.`),!1;if(!e)return p.log.warn(`Skipped ${d}`),!0}let m=i.files[0];if(!m)return p.log.error(`${e} has no files.`),!1;r(c(a),{recursive:!0}),s(a,m.content),E.push(d);for(let e of i.dependencies)O.set(e.name,e.version);return!0}for(let e of T)if(!await I(e,!0))return 1;if(E.length===0)return p.outro(`Nothing written.`),0;p.log.success(`Added\n${E.map(e=>` ${e}`).join(`
3
+ `)}`);let R=k(f,[...O].map(([e,t])=>({name:e,version:t}))),z=[...O.keys()].filter(e=>!R.some(t=>t.name===e));if(O.size>0){let t=[...z.map(t=>` ${e.green(`✔`)} ${t} ${e.dim(`already installed`)}`),...R.map(t=>` ${e.yellow(`+`)} ${t.name}@${t.version}`)];p.log.info(`Dependencies\n${t.join(`
4
+ `)}`)}if(R.length>0){let n=C(f),r=R.map(e=>`${e.name}@${e.version}`),i=o.yes;if(!i){let t=await p.confirm({message:`Install ${R.length} missing package${R.length>1?`s`:``} with ${e.bold(n)}?`});if(p.isCancel(t))return p.cancel(`Cancelled.`),1;i=t}if(i){let{command:e,args:i}=A(n,r),a=t(e,i,{cwd:f,stdio:`inherit`,shell:process.platform===`win32`});if(a.status!==0)return p.log.error(`${e} exited with ${a.status??`an error`}.`),1}else p.log.info(`Install manually:\n ${C(f)} add ${r.join(` `)}`)}return p.outro(`Done.`),0}function I(e,t){let n=Array.from({length:t.length+1},(e,t)=>t);for(let r=1;r<=e.length;r++){let i=[r];for(let a=1;a<=t.length;a++){let o=e[r-1]===t[a-1]?0:1;i[a]=Math.min(i[a-1]+1,n[a]+1,n[a-1]+o)}n=i}return n[t.length]}function L(e,t){let n=[...e.components.map(e=>e.component),...e.blocks.map(e=>e.id)].map(e=>({name:e,score:e.includes(t)||t.includes(e)?0:I(e,t)})).filter(e=>e.score<=2).sort((e,t)=>e.score-t.score).slice(0,5).map(e=>e.name);n.length?p.log.info(`Did you mean: ${n.join(`, `)}`):p.log.info(`Run ${j()} list to see everything.`)}async function R(t){let n=t.includes(`--force`),r=x();if(!r)return p.log.error(`No package.json found. Run this inside a project.`),1;if(p.intro(e.bgCyan(e.black(` Yumma UI `))),D(r)&&!n)return p.log.warn(`${y} already exists. Use --force to overwrite.`),p.outro(`Nothing to do.`),0;let i=w(r),a=C(r),o=T(r);p.log.step([i?`Detected ${e.bold(i)}`:`No framework detected`,`Detected ${e.bold(a)}`].join(`
5
+ `));let s=await p.text({message:`Where should components go?`,placeholder:`components/ui`,defaultValue:`components/ui`});if(p.isCancel(s))return z();let c=!1;if(o){let t=await p.confirm({message:`Use the ${e.bold(`"${o}/"`)} import alias?`});if(p.isCancel(t))return z();c=t}return O(r,{componentsDir:String(s),alias:c&&o?`${o}/${s}`:null,registry:h}),p.log.success(`Wrote ${e.bold(E(r))}`),p.outro(`Next: ${e.cyan(`${j(r)} add button`)}`),0}function z(){return p.cancel(`Cancelled.`),1}async function B(t){let n=t.find(e=>!e.startsWith(`-`)),r=x(),i=r&&D(r)?.registry||h,a;try{a=await v(i)}catch(t){return console.error(e.red(t instanceof g?t.message:String(t))),1}if(n){let t=a.components.find(e=>e.component===n);if(!t)return console.error(e.red(`Unknown component ${n}.`)),1;let i=a.blocks.filter(e=>e.component===n);if(console.log(`\n${e.bold(t.title)} ${e.dim(t.component)}\n`),console.log(` ${e.dim(`${j(r)} add ${t.component}`)}\n`),console.log(` ${e.dim(`Every variation is a prop. Read its API at`)} ${e.cyan(`https://yummacss.com/ui/components/${t.component}`)}\n`),i.length){console.log(` ${e.bold(`${i.length} block${i.length>1?`s`:``} built on it`)}`);for(let t of i)console.log(` ${t.id.padEnd(26)}${e.dim(`add ${t.id}`)}`);console.log()}return 0}console.log(`\n${e.bold(`${a.components.length} components`)}\n`);let o=a.components.map(e=>e.component);for(let e=0;e<o.length;e+=2)console.log(` ${(o[e]??``).padEnd(24)}${o[e+1]??``}`);console.log(`\n${e.bold(`${a.blocks.length} blocks`)}\n`);let s=a.blocks.map(e=>e.id);for(let e=0;e<s.length;e+=2)console.log(` ${(s[e]??``).padEnd(30)}${s[e+1]??``}`);return console.log(`\n ${e.dim(`${j(r)} list <component>`)} to see its blocks\n`),0}const V=[`.astro`,`.cjs`,`.cts`,`.js`,`.jsx`,`.md`,`.mdx`,`.mjs`,`.mts`,`.svelte`,`.ts`,`.tsx`,`.vue`],H=new Set([`node_modules`,`.git`]),U=[/\bfrom\s*["']([^"'\n]+)["']/g,/\bimport\s*\(\s*["']([^"'\n]+)["']/g,/\brequire\s*\(\s*["']([^"'\n]+)["']/g,/\bimport\s+["']([^"'\n]+)["']/g];function W(e){let t=new Set;for(let n of U){n.lastIndex=0;for(let r of e.matchAll(n))r[1]&&t.add(r[1])}return[...t]}const G=/\b(?:from|import\s*\(|require\s*\()\s*`/;function K(e){return G.test(e)}function q(e){let t=e.split(f).join(`/`).replace(/^\.\//,``);for(let e of V)if(t.endsWith(e))return t.slice(0,-e.length);return t}function J(e,t,n){let r=d(n.root,n.componentsDir);if(n.alias){let t=`${n.alias}/`;if(e===n.alias)return`index`;if(e.startsWith(t)){let n=e.slice(t.length);return n?q(n):`index`}}if(!e.startsWith(`.`))return null;let i=u(r,d(c(t),e));return i?i===`..`||i.startsWith(`..${f}`)?null:q(i):`index`}function Y(e,t){return q(u(d(t.root,t.componentsDir),e))}function X(e,t,n=[]){let r;try{r=a(e,{withFileTypes:!0})}catch{return n}for(let i of r){let r=l(e,i.name);if(i.isDirectory()){if(H.has(i.name)||r===t)continue;X(r,t,n)}else if(i.isFile()){let e=i.name.lastIndexOf(`.`);e>0&&V.includes(i.name.slice(e))&&n.push(r)}}return n}function Z(e){let t=new Set;for(let n of e.components)t.add(`${n.component}.tsx`);for(let n of e.blocks)t.add(`${n.id}.tsx`);return t}function Q(e,t){let n=d(e.root,e.componentsDir),r=X(n,``),a=X(e.root,n),o=new Map,s=new Set,c=new Map,l=[];for(let n of r){let r=Y(n,e);n.endsWith(`.tsx`)&&!r.includes(`/`)&&t.has(`${r}.tsx`)?o.set(r,n):s.add(r);let a=i(n,`utf8`);K(a)&&l.push(n);let u=new Set;for(let t of W(a)){let r=J(t,n,e);r&&u.add(r)}c.set(r,u)}for(let t of a){let n=i(t,`utf8`);K(n)&&l.push(t);for(let r of W(n)){let n=J(r,t,e);n&&s.add(n)}}let u=new Set,f=[...s];for(;f.length>0;){let e=f.pop();if(!u.has(e)){u.add(e);for(let t of c.get(e)??[])u.has(t)||f.push(t)}}let p=[];for(let[e,t]of o)u.has(e)||p.push(t);return{unused:p.sort(),kept:o.size-p.length,foreign:r.length-o.size,scanned:r.length+a.length,computed:l}}function te(e){return{write:e.includes(`--write`),yes:e.includes(`--yes`)||e.includes(`-y`)}}async function ne(t){let n=te(t),r=x();if(!r)return p.log.error(`No package.json found. Run this inside a project.`),1;let i=D(r);if(!i)return p.log.error(`No ${y} found. Run ${e.cyan(`${j(r)} init`)} first.`),1;p.intro(e.bgCyan(e.black(` Yumma UI `)));let a,s=p.spinner();s.start(`Fetching registry`);try{a=await v(i.registry)}catch(e){return s.stop(`Registry unavailable`,1),p.log.error(e instanceof g?e.message:String(e)),1}s.stop(`Reading the project`);let c=Q({root:r,componentsDir:i.componentsDir,alias:i.alias},Z(a)),l=e=>u(r,e).replace(/\\/g,`/`);if(c.computed.length>0&&p.log.warn(`Imports built at runtime in ${c.computed.length} file${c.computed.length>1?`s`:``}; anything they name is invisible here:\n${c.computed.slice(0,5).map(e=>` ${l(e)}`).join(`
6
6
  `)}`),c.unused.length===0)return p.log.info(`${c.kept} installed, all reachable. ${c.scanned} files scanned.`),p.outro(`Nothing to prune.`),0;if(p.log.info(`Unreachable from outside ${e.bold(i.componentsDir)}\n${c.unused.map(t=>` ${e.yellow(l(t))}`).join(`
7
- `)}`),p.log.step(`${c.unused.length} unused, ${c.kept} in use`+(c.foreign>0?`, ${c.foreign} not ours`:``)),!n.write)return p.outro(`Delete them with ${e.cyan(`${M(r)} prune --write`)}`),0;if(!n.yes){let e=await p.confirm({message:`Delete ${c.unused.length} file${c.unused.length>1?`s`:``}?`,initialValue:!1});if(p.isCancel(e))return p.cancel(`Cancelled.`),1;if(!e)return p.outro(`Nothing deleted.`),0}for(let e of c.unused)o(e,{force:!0});return p.log.success(`Deleted ${c.unused.length}`),p.outro(`Done.`),0}const $=`
7
+ `)}`),p.log.step(`${c.unused.length} unused, ${c.kept} in use`+(c.foreign>0?`, ${c.foreign} not ours`:``)),!n.write)return p.outro(`Delete them with ${e.cyan(`${j(r)} prune --write`)}`),0;if(!n.yes){let e=await p.confirm({message:`Delete ${c.unused.length} file${c.unused.length>1?`s`:``}?`,initialValue:!1});if(p.isCancel(e))return p.cancel(`Cancelled.`),1;if(!e)return p.outro(`Nothing deleted.`),0}for(let e of c.unused)o(e,{force:!0});return p.log.success(`Deleted ${c.unused.length}`),p.outro(`Done.`),0}const $=`
8
8
  ${e.bold(`yummaui`)} ${e.dim(`v${m}`)}
9
9
 
10
10
  Copies Yumma UI components into your project. Never a dependency.
@@ -32,4 +32,4 @@ ${e.bold(`Examples`)}
32
32
  npx yummaui add --all
33
33
  npx yummaui list button
34
34
  npx yummaui prune
35
- `;async function ie(){let t=process.argv.slice(2),n=t[0];if(!n||n===`-h`||n===`--help`)return console.log($),0;if(n===`--version`||n===`-V`)return console.log(m),0;let r=t.slice(1);switch(n){case`init`:return R(r);case`add`:return F(r);case`list`:case`ls`:return B(r);case`prune`:return re(r);default:return console.error(e.red(`Unknown command "${n}".`)),console.log($),1}}ie().then(e=>{process.exitCode=e}).catch(t=>{console.error(e.red(t instanceof Error?t.message:String(t))),process.exitCode=1});export{};
35
+ `;async function re(){let t=process.argv.slice(2),n=t[0];if(!n||n===`-h`||n===`--help`)return console.log($),0;if(n===`--version`||n===`-V`)return console.log(m),0;let r=t.slice(1);switch(n){case`init`:return R(r);case`add`:return F(r);case`list`:case`ls`:return B(r);case`prune`:return ne(r);default:return console.error(e.red(`Unknown command "${n}".`)),console.log($),1}}re().then(e=>{process.exitCode=e}).catch(t=>{console.error(e.red(t instanceof Error?t.message:String(t))),process.exitCode=1});export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yummaui",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Add Yumma UI components to your project.",
5
5
  "keywords": [
6
6
  "yummacss",