@sugarcube-sh/cli 0.0.1 → 0.0.3
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/README.md +5 -5
- package/dist/index.mjs +48 -45
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -10,11 +10,11 @@ CLI for [sugarcube](https://sugarcube.sh).
|
|
|
10
10
|
|
|
11
11
|
## Commands
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
13
|
+
- `@sugarcube-sh/cli init` - Set up sugarcube in your project
|
|
14
|
+
- `@sugarcube-sh/cli generate` - Generate CSS from your design tokens
|
|
15
|
+
- `@sugarcube-sh/cli validate` - Validate your token files
|
|
16
|
+
- `@sugarcube-sh/cli components` - Add components to your project
|
|
17
|
+
- `@sugarcube-sh/cli cube` - Add CUBE CSS
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
2
|
+
var st=Object.defineProperty;var i=(e,t)=>st(e,"name",{value:t,configurable:!0});import{Command as U}from"commander";import{relative as N,join as _,basename as Ie,resolve as j,dirname as it,isAbsolute as rt}from"pathe";import c from"picocolors";import{existsSync as D,readFileSync as be}from"node:fs";import{z as y}from"zod";import re,{mkdir as W,writeFile as X,readFile as Ee}from"node:fs/promises";import{execa as ot}from"execa";import{loadAndResolveTokens as at,findResolverDocument as oe,loadInternalConfig as ee,isNoConfigError as ve,configFileExists as ke,processAndConvertTokens as ae,generateCSSVariables as _e,writeCSSVariablesToDisk as $e,writeCSSUtilitiesToDisk as Re,fillDefaults as Ce,convertConfigToUnoRules as ct,DEFAULT_CONFIG as ce}from"@sugarcube-sh/core";import{select as lt,isCancel as le,log as ut,multiselect as dt,confirm as ft,cancel as Fe}from"@clack/prompts";import{getColumns as pt}from"@clack/core";import{wrapAnsi as mt}from"fast-wrap-ansi";import gt from"is-unicode-supported";import*as Ne from"node:readline";import De from"node:readline";import{createLogUpdate as Oe}from"log-update";import ue,{resolve as ht}from"node:path";import{detect as wt}from"@antfu/ni";import{createGenerator as yt}from"@unocss/core";import{glob as de}from"tinyglobby";import{getTsconfig as St}from"get-tsconfig";var Tt="0.0.3",Ae={version:Tt};const fe="fluid",It="**/*.json",Le="@sugarcube-sh/vite",bt="@sugarcube-sh/cli",Et=20,O={INIT:"@sugarcube-sh/cli init",COMPONENTS:"@sugarcube-sh/cli components",CUBE:"@sugarcube-sh/cli cube"},$={INITIALIZATION:"https://sugarcube.sh/docs/getting-started",CONFIGURATION:"https://sugarcube.sh/docs/configuration",ISSUES:"https://github.com/sugarcube-sh/sugarcube/issues",RESOLVER:"https://sugarcube.sh/docs/resolver",DESIGN_TOKENS:"https://sugarcube.sh/docs/tokens",COMPONENTS_CLI:"https://sugarcube.sh/docs/reference/cli-commands/#components",HOMEPAGE:"https://sugarcube.sh"},h={PROJECT_REQUIRED:`No sugarcube project detected. Please run ${c.cyan(O.INIT)} first.
|
|
3
3
|
|
|
4
|
-
For more information, visit: ${c.cyan(
|
|
4
|
+
For more information, visit: ${c.cyan($.INITIALIZATION)}`,CONFIG_EXISTS:i(()=>`A sugarcube config file already exists in this project.
|
|
5
5
|
|
|
6
6
|
To start over, remove it and run ${c.cyan(O.INIT)} again.`,"CONFIG_EXISTS"),PLUGIN_INSTALL_FAILED:i(e=>{const t=e.packageManager==="npm"?"install":"add";return`Failed to install ${e.pluginToInstall} plugin.
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ This is usually a temporary issue. Try these steps:
|
|
|
12
12
|
3. Install manually: ${e.packageManager} ${t} ${e.pluginToInstall}
|
|
13
13
|
|
|
14
14
|
If the problem continues, please open an issue at:
|
|
15
|
-
${
|
|
15
|
+
${$.ISSUES}`},"PLUGIN_INSTALL_FAILED"),CLI_INSTALL_FAILED:i(e=>{const t=e.packageManager==="npm"?"install":"add";return`Failed to install @sugarcube-sh/cli.
|
|
16
16
|
|
|
17
17
|
This is usually a temporary issue. Try these steps:
|
|
18
18
|
|
|
@@ -21,15 +21,12 @@ This is usually a temporary issue. Try these steps:
|
|
|
21
21
|
3. Install manually: ${e.packageManager} ${t} -D @sugarcube-sh/cli
|
|
22
22
|
|
|
23
23
|
If the problem continues, please open an issue at:
|
|
24
|
-
${
|
|
24
|
+
${$.ISSUES}`},"CLI_INSTALL_FAILED"),INITIALIZATION_INCOMPLETE:i(()=>`The initialization process was not completed properly.
|
|
25
25
|
This is an internal error that should not occur.
|
|
26
26
|
Try running the \`init\` command again.
|
|
27
27
|
|
|
28
28
|
If the problem persists, please report this issue at
|
|
29
|
-
${
|
|
30
|
-
Value: "${t}"
|
|
31
|
-
|
|
32
|
-
${e} cannot be in a reserved directory`,"DIRECTORY_PATH_RESERVED"),KIT_INCOMPLETE:i(()=>`The starter kit appears to be incomplete or corrupted.
|
|
29
|
+
${$.ISSUES}`,"INITIALIZATION_INCOMPLETE"),CONFIG_WRITE_FAILED:i(()=>"Failed to write configuration file. Check permissions and try again.","CONFIG_WRITE_FAILED"),KIT_INCOMPLETE:i(()=>`The starter kit appears to be incomplete or corrupted.
|
|
33
30
|
|
|
34
31
|
This is likely a temporary issue. Please try running the command again or choose a different starter kit.`,"KIT_INCOMPLETE"),REGISTRY_AUTH_REQUIRED:i(e=>`Registry access denied: Authentication required
|
|
35
32
|
URL: ${c.cyan(e)}`,"REGISTRY_AUTH_REQUIRED"),REGISTRY_AUTH_INVALID:i(e=>`Registry access denied: Invalid or missing token
|
|
@@ -53,11 +50,11 @@ ${c.cyan(`export default {
|
|
|
53
50
|
// ...
|
|
54
51
|
}`)}
|
|
55
52
|
|
|
56
|
-
See ${c.cyan(
|
|
53
|
+
See ${c.cyan($.RESOLVER)} for more information.`,"RESOLVER_NOT_CONFIGURED"),RESOLVER_NOT_FOUND:i(e=>`No resolver document found in ${c.cyan(e)}.
|
|
57
54
|
|
|
58
55
|
A resolver document (*.resolver.json) is required to define how your tokens are loaded.
|
|
59
56
|
|
|
60
|
-
See ${c.cyan(
|
|
57
|
+
See ${c.cyan($.RESOLVER)} to learn how to create one.`,"RESOLVER_NOT_FOUND"),RESOLVER_MULTIPLE_FOUND:i(e=>`Multiple resolver documents found:
|
|
61
58
|
${e.map(t=>` - ${c.cyan(t)}`).join(`
|
|
62
59
|
`)}
|
|
63
60
|
|
|
@@ -71,7 +68,7 @@ Please check your token files and try again.`,"TOKEN_LOAD_FAILED"),TOKEN_VALIDAT
|
|
|
71
68
|
`;for(const[n,s]of e){t+=`Error(s) in ${c.cyan(n)}:
|
|
72
69
|
`;for(const r of s)t+=` - ${r}
|
|
73
70
|
`;t+=`
|
|
74
|
-
`}return t+=`See ${c.cyan(
|
|
71
|
+
`}return t+=`See ${c.cyan($.DESIGN_TOKENS)} for valid token formats`,t},"TOKEN_VALIDATION_FAILED"),TOKEN_FILE_INVALID_JSON:i(e=>`File ${e}: Invalid JSON syntax`,"TOKEN_FILE_INVALID_JSON"),TOKEN_FILE_INCOMPLETE_JSON:i(e=>`File ${e}: Incomplete JSON file`,"TOKEN_FILE_INCOMPLETE_JSON"),TOKEN_FILE_GENERIC_ERROR:i((e,t)=>`File ${e}: ${t}`,"TOKEN_FILE_GENERIC_ERROR"),DEPENDENCY_INSTALL_FAILED:i(e=>`Failed to install dependencies using ${e}.
|
|
75
72
|
Please check your package manager configuration and try again.`,"DEPENDENCY_INSTALL_FAILED"),VALIDATE_NO_PATH_SPECIFIED:i(()=>`No path specified.
|
|
76
73
|
|
|
77
74
|
Run ${c.cyan("sugarcube validate --help")} for more information.`,"VALIDATE_NO_PATH_SPECIFIED"),VALIDATE_PATH_NOT_FOUND:i(e=>`Path not found: ${e}
|
|
@@ -80,7 +77,7 @@ Please check that the specified path exists`,"VALIDATE_PATH_NOT_FOUND"),VALIDATE
|
|
|
80
77
|
|
|
81
78
|
Please ensure the path contains .json token files`,"VALIDATE_NO_TOKEN_FILES"),COMPONENTS_FRAMEWORK_REQUIRED:i(()=>`Framework is required when specifying components. Use --framework to specify a framework (react, css-only) or run without arguments for interactive mode.
|
|
82
79
|
|
|
83
|
-
See ${c.cyan(
|
|
80
|
+
See ${c.cyan($.COMPONENTS_CLI)} for more information.`,"COMPONENTS_FRAMEWORK_REQUIRED"),COMPONENTS_INVALID_FRAMEWORK:i(()=>"Invalid framework. Must be one of: react, css-only.","COMPONENTS_INVALID_FRAMEWORK"),COMPONENTS_DIRECTORY_NOT_CONFIGURED:i(()=>"Components directory must be configured in non-interactive mode. Please run the 'components' command without arguments first.","COMPONENTS_DIRECTORY_NOT_CONFIGURED"),PLUGIN_DETECTED:i(e=>`Plugin detected: ${e}
|
|
84
81
|
|
|
85
82
|
The 'generate' command is for manual generation without plugins. Since you have a plugin installed, use your development server instead:
|
|
86
83
|
|
|
@@ -90,14 +87,16 @@ The plugin will automatically generate CSS with hot module replacement.`,"PLUGIN
|
|
|
90
87
|
|
|
91
88
|
Run ${c.cyan(O.INIT)} to set up your design tokens.
|
|
92
89
|
|
|
93
|
-
Stuck? ${c.cyan(
|
|
90
|
+
Stuck? ${c.cyan($.HOMEPAGE)}`,"GENERATE_NO_CONFIG_OR_RESOLVER"),GENERATE_MULTIPLE_RESOLVERS_NO_CONFIG:i(e=>`No config file found, but multiple resolver files detected:
|
|
94
91
|
${e.map(t=>` - ${t}`).join(`
|
|
95
92
|
`)}
|
|
96
93
|
|
|
97
94
|
Please either:
|
|
98
95
|
- Create a config file with ${c.cyan(O.INIT)}
|
|
99
|
-
- Use --resolver flag to specify which resolver to use`,"GENERATE_MULTIPLE_RESOLVERS_NO_CONFIG")
|
|
100
|
-
|
|
96
|
+
- Use --resolver flag to specify which resolver to use`,"GENERATE_MULTIPLE_RESOLVERS_NO_CONFIG"),FILENAME_CONTAINS_PATH:i((e,t)=>`Invalid ${e} value: "${t}". Must be a filename, not a path.
|
|
97
|
+
|
|
98
|
+
Use --variables-dir or --utilities-dir to specify the directory.`,"FILENAME_CONTAINS_PATH")};class p extends Error{static{i(this,"CLIError")}constructor(t,n){super(t),this.name="CLIError",this.cause=n}}const pe=y.enum(["react","web-components","css-only"]),Pe=y.object({path:y.string(),type:y.string()}),vt=Pe.extend({framework:pe}),kt=y.object({name:y.string(),type:y.string(),description:y.string().optional(),frameworks:y.array(y.string()).optional(),files:y.array(y.union([vt,Pe])),tokens:y.record(y.object({type:y.string(),mapping:y.string()})).optional(),dependencies:y.record(pe,y.array(y.string())).optional(),registryDependencies:y.record(pe,y.array(y.string())).optional(),tokenDependencies:y.array(y.string()).optional()}),_t=y.array(kt),$t=y.object({content:y.string()}),Me=process.env.REGISTRY_URL??"https://sugarcube.sh/r";async function Ue(e){try{const t=await fetch(e);if(!t.ok){if(t.status===401)throw new p(h.REGISTRY_AUTH_REQUIRED(e));if(t.status===403)throw new p(h.REGISTRY_AUTH_INVALID(e));if(t.status===404)throw new p(h.REGISTRY_NOT_FOUND(e));const n=await t.json().catch(()=>null),s=n&&typeof n=="object"&&"error"in n?String(n.error):t.statusText;throw new p(h.REGISTRY_REQUEST_FAILED(s,e))}return t.json()}catch(t){throw t instanceof p?t:new p(h.REGISTRY_NETWORK_ERROR(e))}}i(Ue,"fetchRegistry");async function G(){const e=`${Me}/index.json`,t=await Ue(e);try{return _t.parse(t)}catch{throw new p(h.REGISTRY_INVALID_DATA(e))}}i(G,"getRegistryIndex");async function me({type:e,name:t,framework:n}){const s=await G(),r=s.find(l=>l.type===e&&l.name===t);if(!r){const l=s.filter(f=>f.type===e).map(f=>f.name);throw new p(h.REGISTRY_ITEM_NOT_FOUND(e,t,l))}let o=r.files;e==="component"&&n&&(o=r.files.filter(l=>"framework"in l&&l.framework===n));const a=await Promise.all(o.map(async l=>{const f=`${Me}/${l.path}.json`,d=await Ue(f);try{const u=$t.parse(d);return{path:l.path,type:l.type,framework:"framework"in l?l.framework:void 0,content:u.content}}catch{throw new p(h.REGISTRY_FILE_INVALID(l.path))}}));return{item:r,files:a}}i(me,"getRegistryFiles");async function Rt(e){const t=await me({type:"tokens",name:e});if(!t.files[0])throw new p(h.STARTER_KIT_UNAVAILABLE(e));return t}i(Rt,"fetchStarterKit");async function ge(e,t,n){const s=[],r=new Set;async function o(a){if(r.has(a))return;r.add(a);const l=e.find(d=>d.name===a);if(!l){const d=e.filter(u=>u.type==="component").map(u=>u.name).join(", ");throw new p(`Component '${a}' not found in registry
|
|
99
|
+
Available components: ${d}`)}const f=l.registryDependencies?.[n]||[];for(const d of f)await o(d);s.push(l)}i(o,"resolveComponent");for(const a of t)await o(a);return s}i(ge,"resolveTree");async function Ct({selectedComponents:e,componentType:t,componentsOutputDirectory:n}){const s={variableCSS:[],utilityCSS:[],componentFiles:[],componentCSS:[],cubeCSS:[],indexFiles:[]},r=await G(),a=(await ge(r,e,t)).map(u=>u.name),l=r.filter(u=>u.type==="component").filter(u=>a.includes(u.name)),f=l.flatMap(u=>u.files.filter(m=>(m.type==="tsx"||m.type==="astro"||m.type==="njk")&&"framework"in m&&m.framework===t).map(m=>N(process.cwd(),_(n,u.name,`${u.name}.${m.type}`))));s.componentFiles=f.filter(u=>D(_(process.cwd(),u)));const d=l.map(u=>{const m=u.name;return N(process.cwd(),_(n,u.name,`${m}.css`))});return s.componentCSS=d.filter(u=>D(_(process.cwd(),u))),s}i(Ct,"collectComponentOverwriteWarnings");async function Ft({cubeDirectory:e}){const t={variableCSS:[],utilityCSS:[],componentFiles:[],componentCSS:[],cubeCSS:[],indexFiles:[]},s=(await G()).filter(r=>r.type==="cube").flatMap(r=>r.files).map(r=>{const o=r.path.replace(/^styles\//,"");return N(process.cwd(),_(e,o))});return t.cubeCSS=s.filter(r=>D(_(process.cwd(),r))),t}i(Ft,"collectCubeOverwriteWarnings");function je(e){const t=[];if(e.variableCSS.length>0&&t.push(`CSS variables files:
|
|
101
100
|
${e.variableCSS.map(s=>` - ${s}`).join(`
|
|
102
101
|
`)}`),e.utilityCSS.length>0&&t.push(`CSS utility files:
|
|
103
102
|
${e.utilityCSS.map(s=>` - ${s}`).join(`
|
|
@@ -111,47 +110,51 @@ ${e.indexFiles.map(s=>` - ${s}`).join(`
|
|
|
111
110
|
|
|
112
111
|
${t.join(`
|
|
113
112
|
|
|
114
|
-
`)}`}i(
|
|
113
|
+
`)}`}i(je,"formatOverwriteWarnings");async function te(e,t,n,s={}){if(e.length===0)return;const{devDependency:r=!1}=s,o=n==="npm"?"install":"add",a=(()=>{if(!r)return[];switch(n){case"npm":return["--save-dev"];case"pnpm":return["-D"];case"yarn":return["-D"];case"bun":return["-d"]}})();try{await ot(n,[o,...a,...e],{cwd:t})}catch{throw new p(h.DEPENDENCY_INSTALL_FAILED(n))}}i(te,"installDependencies");async function Nt(e,t,n){const s=_(n,t.name);if(await W(s,{recursive:!0}),e.path.endsWith(".css")){const o=_(s,`${t.name}.css`);return await X(o,e.content),o}const r=_(s,Ie(e.path));return await X(r,e.content),r}i(Nt,"writeComponentFile");async function Dt({registryIndex:e,selectedComponents:t,componentType:n,componentsOutputDirectory:s,packageManager:r}){const o=[],a=new Set;await W(s,{recursive:!0});const l=await ge(e,t,n);for(const f of l){const d=await me({type:"component",name:f.name,framework:n});for(const m of d.files)if(m)try{const g=await Nt(m,f,s);g&&o.push(g)}catch(g){const I=g instanceof Error?`: ${g.message}`:"";throw new p(`Failed to write component file for "${f.name}"${I}`)}const u=f.dependencies?.[n]||[];for(const m of u)a.add(m)}if(a.size>0)try{await te(Array.from(a),process.cwd(),r)}catch(f){const d=f instanceof Error?`: ${f.message}`:"";throw new p(`Failed to install component dependencies${d}`)}return{createdFiles:o,npmDependencies:a}}i(Dt,"installComponents");function Ot(e,t){const n=j(e),s=j(t),r=N(s,n);return!r.startsWith("..")&&!rt(r)}i(Ot,"isWithinDirectory");async function At(e){const t=[],n=j(process.cwd(),e);await W(n,{recursive:!0});const r=(await G()).filter(o=>o.type==="cube").map(o=>o.name);for(const o of r){const a=await me({type:"cube",name:o});for(const l of a.files){if(!l)continue;const f=l.path.replace(/^styles\//,""),d=j(n,f);if(!Ot(d,n))throw new p(`Invalid file path detected in CUBE module "${o}": path escapes target directory`);const u=it(d);try{await W(u,{recursive:!0}),await X(d,l.content),t.push(d)}catch(m){const g=m instanceof Error?`: ${m.message}`:"";throw new p(`Failed to write CUBE module "${o}"${g}`)}}}return t}i(At,"installCUBE");async function Lt(e,t){await re.mkdir(t,{recursive:!0});const n=[];for(const s of e)await re.writeFile(s.path,s.content),n.push(s.path);return n}i(Lt,"writeTokenFiles");async function K(e,t){let n;if(t)n={type:"memory",data:t,config:e};else{if(!e.resolver)throw new p(h.RESOLVER_NOT_CONFIGURED());n={type:"resolver",resolverPath:e.resolver,config:e}}const{trees:s,resolved:r,modifiers:o,errors:a}=await at(n);if(a.load.length>0){const l=a.load.map(f=>{const d=f.file.split("/").pop()||"unknown file";let u=`File ${d}: `;return f.message.includes("Unexpected token")?u=h.TOKEN_FILE_INVALID_JSON(d):f.message.includes("Unexpected end")?u=h.TOKEN_FILE_INCOMPLETE_JSON(d):u=h.TOKEN_FILE_GENERIC_ERROR(d,f.message),u});throw new p(h.TOKEN_LOAD_FAILED(l))}if(a.validation.length>0||a.flatten.length>0||a.resolution.length>0){const l=[...a.flatten,...a.validation,...a.resolution],f=new Map;for(const d of l)if(d.source?.sourcePath){const u=f.get(d.source.sourcePath)||[];u.push(d.message),f.set(d.source.sourcePath,u)}throw new p(h.TOKEN_VALIDATION_FAILED(f))}return{trees:s,resolved:r,modifiers:o}}i(K,"loadAndResolveTokensForCLI");const Pt=i(async(e,t,n)=>{const s=await Rt(e),r=j(process.cwd(),t),o=s.files.map(a=>({path:_(r,Ie(a.path)),content:a.content}));return{config:n,tokenFiles:o,tokensDir:r,createdTokenPaths:o.map(a=>N(process.cwd(),a.path))}},"prepareStarterKitForInstall");async function Mt(e){const t=await Pt(e.starterKit??"",e.tokensDir,e.config),n=await Lt(t.tokenFiles,e.tokensDir),s=await oe(e.tokensDir);if(s.found==="none")throw new p(h.RESOLVER_NOT_FOUND(e.tokensDir));if(s.found==="multiple")throw new p(h.RESOLVER_MULTIPLE_FOUND(s.paths));const r={...e.config,resolver:s.path},{trees:o,resolved:a}=await K(r);e.setupResult={config:r,createdTokenPaths:t.createdTokenPaths,trees:o,resolved:a,tokenFiles:t.tokenFiles,tokensDir:t.tokensDir},e.createdFiles.push(...n),e.config=r,e.sugarcubeConfig={...e.sugarcubeConfig,resolver:s.path}}i(Mt,"installFromStarterKit");async function Ge(e=!0){const t=[{label:"React",value:"react",hint:".tsx"},{label:"CSS Only",value:"css-only",hint:".css"},{label:c.dim("Web components"),value:"web-components",hint:"Coming soon!"}];e&&t.push({label:"Skip",value:"skip",hint:"continue without components"});const n=await lt({message:"Build with",options:t});return le(n)&&process.exit(0),n==="web-components"?(ut.info(c.blue("Web components are coming soon! Please choose React or CSS Only for now.")),Ge(e)):n}i(Ge,"promptComponentFramework");async function Ut(e,t){const n=e.filter(r=>r.type==="component"&&r.frameworks?.includes(t)),s=await dt({message:"Select components to add",options:n.map(r=>({label:r.name,value:r.name,hint:r.description})),required:!0});return le(s)&&process.exit(0),s}i(Ut,"promptComponentSelectionFiltered");async function Be(e,t=!1){const n=await ft({message:e,initialValue:t});return(!n||le(n))&&(Fe(),process.exit(0)),!0}i(Be,"confirmOverwrite");function B(e){return{absolute:j(process.cwd(),e)}}i(B,"resolveDirectoryFromFlag");async function jt(e){if(e){const{absolute:t}=B(e);return{directory:t}}try{const{config:t}=await ee(),n=t.output.cube||t.output.cssRoot,{absolute:s}=B(n);return{directory:s}}catch(t){if(ve(t)){const{absolute:n}=B("src/styles");return{directory:n}}throw t}}i(jt,"getCubeDir");async function Gt(e){if(e){const{absolute:t}=B(e);return{directory:t}}try{const{config:t}=await ee(),n=t.output.components??"src/components/ui",{absolute:s}=B(n);return{directory:s}}catch(t){if(ve(t)){const{absolute:n}=B("src/components/ui");return{directory:n}}throw t}}i(Gt,"getComponentsDir");const Bt=gt(),b=i((e,t)=>Bt?e:t,"unicodeOr"),Vt=b("\u25C7","o"),Ve=b("\u250C","T"),A=b("\u2502","|"),he=b("\u2514","\u2014"),xt=b("\u2510","T"),Wt=b("\u2518","\u2014"),ne=b("\u2500","-"),Kt=b("\u256E","+"),Yt=b("\u256F","+"),Ht=b("\u2570","+"),zt=b("\u256D","+"),Jt=b("\u25CF","\u2022"),qt=b("\u25C6","*"),Zt=b("\u25B2","!"),Qt=b("\u25A0","x"),Y=i((e,t=c.bgGreen,n=c.black)=>t(` ${n(e)} `),"label"),H=i(e=>{const t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"].join("|"),n=new RegExp(t,"g");return typeof e=="string"?e.replace(n,""):e},"strip"),z=i((e="",t)=>{process.stdout.write(`
|
|
115
114
|
|
|
116
|
-
${c.gray(
|
|
115
|
+
${c.gray(Ve)}${c.gray(ne)} ${e}
|
|
117
116
|
`)},"intro"),se=i((e="",t)=>{process.stdout.write(`${c.gray(A)}
|
|
118
|
-
${c.gray(
|
|
117
|
+
${c.gray(he)}${c.gray(ne)} ${e}
|
|
119
118
|
|
|
120
|
-
`)},"outro");function
|
|
121
|
-
`);let
|
|
119
|
+
`)},"outro");function V(e){return new Promise(t=>setTimeout(t,e))}i(V,"sleep");const Xt=[zt,Kt,Ht,Yt],en=[Ve,xt,he,Wt];function xe(e,t,n,s){let r=n,o=n;return s==="center"?r=Math.floor((t-e)/2):s==="right"&&(r=t-e-n),o=t-r-e,[r,o]}i(xe,"getPaddingForLine");const tn=i(e=>e,"defaultFormatBorder"),we=i((e="",t="",n)=>{const s=n?.output??process.stdout,r=pt(s),a=1*2,l=n?.titlePadding??1,f=n?.contentPadding??2,d=n?.width===void 0||n.width==="auto"?1:Math.min(1,n.width),u=n?.includePrefix?`${A} `:"",m=n?.formatBorder??tn,g=(n?.rounded?Xt:en).map(m),I=m(ne),w=m(A),k=r-u.length;let v=Math.floor(r*d)-u.length;if(n?.width==="auto"){const Z=e.split(`
|
|
120
|
+
`);let x=H(t).length+l*2;for(const nt of Z){const Te=H(nt).length+f*2;Te>x&&(x=Te)}const Q=x+a;Q<v&&(v=Q)}v%2!==0&&(v<k?v++:v--);const E=v-a,F=E-l*2,S=H(t).length>F?`${t.slice(0,F-3)}...`:t,[R,C]=xe(H(S).length,E,l,n?.titleAlign),L=mt(e,E-f*2,{hard:!0,trim:!1});s.write(`${u}${g[0]}${I.repeat(R)}${S}${I.repeat(C)}${g[1]}
|
|
122
121
|
`);const q=L.split(`
|
|
123
|
-
`);for(const Z of q){const[
|
|
124
|
-
`)}s.write(`${u}${
|
|
125
|
-
`)},"box");function
|
|
126
|
-
${e}`;
|
|
127
|
-
${e}`;
|
|
128
|
-
${e}`;
|
|
129
|
-
`),"renderContent");
|
|
130
|
-
`))}else{const
|
|
131
|
-
`))}else
|
|
132
|
-
`));await
|
|
133
|
-
`),"rawLog"),
|
|
122
|
+
`);for(const Z of q){const[x,Q]=xe(H(Z).length,E,f,n?.contentAlign);s.write(`${u}${w}${" ".repeat(x)}${Z}${" ".repeat(Q)}${w}
|
|
123
|
+
`)}s.write(`${u}${g[2]}${I.repeat(E)}${g[3]}
|
|
124
|
+
`)},"box");function ye(e,t={}){const n=`
|
|
125
|
+
${e}`;we(n,c.black(c.bgRed(" ERROR ")),{width:"auto",titlePadding:2,formatBorder:c.red,...t})}i(ye,"errorBoxWithBadge");function We(e,t={}){const n=`
|
|
126
|
+
${e}`;we(n,c.black(c.bgYellow(" WARNING ")),{width:"auto",titlePadding:2,formatBorder:c.yellow,...t})}i(We,"warningBoxWithBadge");function nn(e,t={}){const n=`
|
|
127
|
+
${e}`;we(n,c.black(c.bgCyan(" INFO ")),{width:"auto",titlePadding:2,formatBorder:c.cyan,...t})}i(nn,"infoBoxWithBadge");const sn=i((e,t)=>{if(!(e.meta&&e.name!=="escape")){if(e.ctrl){if(e.name==="a")return"first";if(e.name==="c"||e.name==="d")return"abort";if(e.name==="e")return"last";if(e.name==="g")return"reset"}return e.name==="return"||e.name==="enter"?"submit":e.name==="backspace"?"delete":e.name==="delete"?"deleteForward":e.name==="abort"?"abort":e.name==="escape"?"exit":e.name==="tab"?"next":e.name==="pagedown"?"nextPage":e.name==="pageup"?"prevPage":e.name==="home"?"home":e.name==="end"?"end":e.name==="up"?"up":e.name==="down"?"down":e.name==="right"?"right":e.name==="left"?"left":!1}},"action"),rn=i(async(e,t={})=>{const{sidebarSymbol:n=c.gray("\u2502"),clear:s=!1,stdin:r=process.stdin,stdout:o=process.stdout}=t,a=De.createInterface({input:r,escapeCodeTimeout:50}),l=Oe(o,{showCursor:!1});De.emitKeypressEvents(r,a);let f=0,d=!1;const u=i(async()=>{r.off("keypress",m),r.isTTY&&r.setRawMode(!1),a.close(),d=!0,f<e.length-1||s?l.clear():l.done()},"done"),m=i((g,I)=>{r.isTTY&&r.setRawMode(!0);const w=sn(I);if(w==="abort")return u(),process.exit(0);["up","down","left","right"].includes(w)||u()},"handleKeyPress");r.isTTY&&r.setRawMode(!0),r.on("keypress",m);for(const g of e){const I=Array.isArray(g)?g:g.split(" "),w=[];for(const E of[""].concat(I)){E&&w.push(E);const F=w.join(" ").replace(/sugarcube/g,c.cyan("sugarcube")),S=`${n} ${F}`;l(S),d||await new Promise(R=>setTimeout(R,Math.floor(Math.random()*126)+75))}d||await new Promise(E=>setTimeout(E,100));const v=(await Promise.all(I).then(E=>E.join(" "))).replace(/sugarcube/g,c.cyan("sugarcube"));l(`${n} ${v}`),d||await new Promise(E=>setTimeout(E,Math.floor(Math.random()*201)+1200)),f++}r.off("keypress",m),await new Promise(g=>setTimeout(g,100)),u(),r.isTTY&&r.setRawMode(!1),r.removeAllListeners("keypress")},"sayAnimatedInSidebar");function on(){return Math.floor(Math.random()*551)+200}i(on,"getRandomTaskDuration");async function an(e,{sidebarSymbol:t="\u2502",spacing:n=1,stdin:s=process.stdin,stdout:r=process.stdout,initialDelayMs:o=200,minDurationMs:a,successPauseMs:l=300,successMessage:f,successAsOutro:d=!1}={}){const u=i((S,R)=>{let C="";switch(R){case"start":C=`${c.cyan(`\u25B6 ${S.start}`)}`;break;case"pending":C=`${c.dim(`\u25A1 ${S.pending}`)}`;break;case"success":C=`${c.green(`\u2714 ${S.end}`)}`;break;case"end":C=`${c.dim(`\u25A0 ${S.end}`)}`;break}return`${t} ${C}`},"formatWithSidebar"),m=Array.from({length:e.length},()=>"");e.forEach((S,R)=>{m[R]=u(S,"pending")});const g=Oe(r),I=Ne.createInterface({input:s,escapeCodeTimeout:50});Ne.emitKeypressEvents(s,I);const w=i(S=>{S===""&&(g.clear(),I.close(),s.isTTY&&s.setRawMode(!1),process.exit(0)),s.isTTY&&s.setRawMode(!0)},"keypress");s.isTTY&&s.setRawMode(!0),s.on("keypress",w);const k=Array.from({length:Math.max(n,0)},()=>`${t}`),v=i(()=>[...k,...m].join(`
|
|
128
|
+
`),"renderContent");g(v()),await V(o);let E=0;for(const S of e){m[E]=u(S,"start"),g(v());const R=Date.now(),C=S.while();try{await C;const L=Date.now()-R,q=typeof a=="number"?a:on();L<q&&await V(q-L),m[E]=u(S,"success"),g(v()),await V(l)}catch(L){throw m[E]=`${t} ${c.red(`\u2717 ${S.end} (failed)`)}`,g(v()),S.onError?.(L),s.removeListener("keypress",w),I.close(),s.isTTY&&s.setRawMode(!1),L}E++}const F=e.map(S=>u(S,"end"));if(f)if(d){const S=`${c.gray(he)}${c.gray(ne)} ${c.green(f)}`;g([...k,...F,`${t}`,S].join(`
|
|
129
|
+
`))}else{const S=`${t} ${c.green(f)}`;g([...k,...F,`${t}`,S].join(`
|
|
130
|
+
`))}else g([...k,...F].join(`
|
|
131
|
+
`));await V(1e3),s.removeListener("keypress",w),s.isTTY&&s.setRawMode(!1),I.close(),g.done()}i(an,"executeTasksInSidebar");const cn=i(e=>process.stdout.write(`${e}
|
|
132
|
+
`),"rawLog"),T={message:i((e=[],{symbol:t=c.gray(A),secondarySymbol:n=c.gray(A),output:s=process.stdout,spacing:r=1}={})=>{const o=[];for(let l=0;l<r;l++)o.push(`${n}`);const a=Array.isArray(e)?e:e.split(`
|
|
134
133
|
`);if(a.length>0){const[l,...f]=a;l&&l.length>0?o.push(`${t} ${l}`):o.push(t);for(const d of f)d.length>0?o.push(`${n} ${d}`):o.push(n)}s.write(`${o.join(`
|
|
135
134
|
`)}
|
|
136
|
-
`)},"message"),info:i((e,t)=>{
|
|
135
|
+
`)},"message"),info:i((e,t)=>{T.message(e,{...t,symbol:c.blue(Jt)})},"info"),success:i((e,t)=>{T.message(e,{...t,symbol:c.green(qt)})},"success"),step:i((e,t)=>{T.message(e,{...t,symbol:c.green(Vt)})},"step"),warn:i((e,t)=>{T.message(e,{...t,symbol:c.yellow(Zt)})},"warn"),error:i((e,t)=>{T.message(e,{...t,symbol:c.red(Qt)})},"error"),animated:i(async(e,{secondarySymbol:t=c.gray(A),output:n=process.stdout,clear:s=!1,...r}={})=>rn(e,{sidebarSymbol:t,stdout:n,clear:s,...r}),"animated"),tasks:i(async(e,{spacing:t=1,secondarySymbol:n=c.gray(A),output:s=process.stdout,...r}={})=>an(e,{sidebarSymbol:n,spacing:t,stdout:s,...r}),"tasks"),space:i((e=1)=>{for(let t=0;t<e;t++)process.stdout.write(`${c.gray(A)}
|
|
137
136
|
`)},"space"),break:i((e=1)=>{for(let t=0;t<e;t++)process.stdout.write(`
|
|
138
|
-
`)},"break")};function J(e){if(e instanceof p)
|
|
137
|
+
`)},"break")};function J(e){if(e instanceof p)T.space(1),ye(e.message,{});else{const t=`An unexpected error occurred: ${e instanceof Error?e.message:String(e)}
|
|
139
138
|
|
|
140
|
-
If this issue persists, please report it: ${c.cyan("https://github.com/sugarcube-sh/sugarcube/issues")}`;
|
|
139
|
+
If this issue persists, please report it: ${c.cyan("https://github.com/sugarcube-sh/sugarcube/issues")}`;T.space(1),ye(t,{})}process.exit(1)}i(J,"handleError");function P(e,t=process.cwd()){try{const n=ht(t,"package.json");if(!D(n))return!1;const s=be(n,"utf-8"),r=JSON.parse(s),o={...r.dependencies,...r.devDependencies,...r.peerDependencies};return e in o}catch{return!1}}i(P,"isPackageInstalled");async function Ke(e,{withFallback:t=!1}={}){const n=await wt({programmatic:!0,cwd:e});if(n?.includes("yarn"))return"yarn";if(n?.includes("pnpm"))return"pnpm";if(n?.includes("bun"))return"bun";if(n?.includes("npm"))return"npm";if(t){const s=process.env.npm_config_user_agent||"";if(s.includes("yarn"))return"yarn";if(s.includes("pnpm"))return"pnpm";if(s.includes("bun"))return"bun"}return"npm"}i(Ke,"getPackageManager");const ln=new U().name("components").description("Add components to your project").argument("[components...]","Components to add (e.g., button card)").option("-f, --framework <type>","Framework to use (react, css-only)").option("--components-dir <dir>","Components output directory (e.g., 'src/components')").option("-s, --silent","Suppress logs and prompts").option("-o, --overwrite","Overwrite existing files").action(async(e,t)=>{try{t.silent||z(Y(c.bgGreen(c.black("Components"))));const{directory:n}=await Gt(t.componentsDir);let s=[],r;if(e.length>0||t.framework){if(!t.framework)throw new p(h.COMPONENTS_FRAMEWORK_REQUIRED());if(!["react","css-only"].includes(t.framework))throw new p(h.COMPONENTS_INVALID_FRAMEWORK());r=t.framework,s=e}else{r=await Ge(!1);const w=await G();w||(Fe("Failed to fetch component list"),process.exit(1)),s=await Ut(w,r)}const o=await Ke(process.cwd(),{withFallback:!0}),a=await G(),l=await ge(a,s,r),f=await Ct({selectedComponents:s,componentType:r,componentsOutputDirectory:n}),d=je(f);if(d&&!t.force&&!t.silent){const w=We(d,{});T.space(1),await Be("Continue?",!1)}const u=[],m=[],g=new Set;for(const w of l){const k=w.dependencies?.[r]||[];for(const v of k)g.add(v)}const I=Array.from(g).filter(w=>!P(w,process.cwd()));I.length>0&&u.push({pending:`Install ${I.length} dependencies`,start:`Installing ${I.join(", ")}...`,end:`Installed ${I.join(", ")}`,while:i(async()=>{await te(I,process.cwd(),o)},"while")});for(const w of l)u.push({pending:`Write component files for ${w.name}`,start:`Writing component files for ${w.name}...`,end:`Wrote component files for ${w.name}`,while:i(async()=>{const k=await Dt({registryIndex:a,selectedComponents:[w.name],componentType:r,componentsOutputDirectory:n,overwrite:t.overwrite||!1,packageManager:o});m.push(...k.createdFiles)},"while")});await T.tasks(u,{successMessage:"Components added successfully! \u{1F389} ",minDurationMs:0,successAsOutro:!0}),cn("")}catch(n){J(n)}}),un=new U().name("cube").description("Add CUBE CSS to your project").option("-s, --silent","Suppress logs and prompts").option("-f, --force","Skip overwrite confirmation").option("--cube-dir <dir>","CUBE CSS output directory (defaults to cssRoot)").action(async e=>{try{e.silent||z(Y("CUBE CSS"));const{directory:t}=await jt(e.cubeDir);try{await W(t,{recursive:!0})}catch(o){const a=o instanceof Error?`: ${o.message}`:"";throw new p(`Failed to create output directory${a}`)}const n=await Ft({cubeDirectory:t}),s=je(n);if(s&&!e.force&&!e.silent){T.space(1);const o=We(s,{});await Be("Continue?",!1)}const r=await At(t);if(!e.silent){T.space(1);const o=r,f=[...new Set(o)].map(d=>N(process.cwd(),d)).map(d=>({pending:`Write ${d}`,start:`Writing ${d}`,end:`Wrote ${d}`,while:i(async()=>{},"while")}));await T.tasks(f,{spacing:0,minDurationMs:0,successPauseMs:100,successMessage:"\u{1F389} Files written!"}),se(c.green("CUBE added successfully."))}}catch(t){J(t)}});function ie(e,t){if(e&&(e.includes("/")||e.includes("\\")))throw new p(h.FILENAME_CONTAINS_PATH(t,e))}i(ie,"validateFilename");const dn=`/* Generated by @sugarcube-sh/cli v${Ae.version} */
|
|
141
140
|
|
|
142
|
-
`,
|
|
143
|
-
`),{css:
|
|
144
|
-
|
|
141
|
+
`,fn="**/*.{html,htm,js,ts,jsx,tsx,vue,svelte,astro,php,njk,liquid,pug,hbs,handlebars,twig,erb,ejs}",pn=["**/node_modules/**","**/dist/**","**/build/**","**/.next/**","**/.nuxt/**","**/.astro/**","**/.git/**","**/coverage/**","**/.pnpm/**","**/.pnpm-store/**","**/.npm/**","**/.cache/**","**/.turbo/**","**/.vercel/**","**/.svelte-kit/**","**/out/**","**/__snapshots__/**","**/*.config.{js,ts,mjs}","**/*.min.js","**/*.bundle.js","**/*.d.ts"],Ye=1e4,He=100;async function ze(e,t){if(!t.utilities||Object.keys(t.utilities).length===0)return[];const s={presets:[{name:"sugarcube",rules:ct(t.utilities,e),preflights:[]}]},r=await yt(s),o=await de([fn],{ignore:pn,dot:!1,onlyFiles:!0,absolute:!1});if(o.length===0)return[];if(o.length>Ye)throw new p(`Found ${o.length} files to scan (limit: ${Ye}). Are you running this from a monorepo root or a directory containing multiple projects? Run the command from within a single project directory instead.`);const a=[];let l=0;const f=He*1024*1024;for(const m of o){const g=await Ee(m,"utf8");if(l+=g.length,l>f)throw new p(`Total source size exceeds ${He}MB. Are you running this from a monorepo root or a directory containing multiple projects? Run the command from within a single project directory instead.`);a.push(g)}const d=a.join(`
|
|
142
|
+
`),{css:u}=await r.generate(d,{preflights:!1});return u?.trim()?[{path:`${t.output.utilities}/${t.output.utilitiesFilename}`,css:u}]:[]}i(ze,"generateSugarcubeUtilities");function Je(e){return e.map(t=>({...t,css:dn+t.css}))}i(Je,"addBanner");function qe(e,t){return e.map(n=>{const s=n.css.split(`
|
|
143
|
+
`).map(r=>r.trim()?` ${r}`:r).join(`
|
|
144
|
+
`);return{...n,css:`@layer ${t} {
|
|
145
|
+
${s}}
|
|
146
|
+
`}})}i(qe,"wrapInLayer$1");async function mn(e,t,n,s){const r=[],o=n.output.layers,a=await ae(e,t,n);let l=await _e(a,n,s);o&&(l=qe(l,o.variables));const f=Je(l);await $e(f),r.push(...f);let d=await ze(a,n);o&&(d=qe(d,o.utilities));const u=Je(d);return await Re(u),r.push(...u),r}i(mn,"generateAllCSS");function gn(e){let t;(e.fluidMin||e.fluidMax)&&(t={min:e.fluidMin?Number.parseInt(e.fluidMin,10):320,max:e.fluidMax?Number.parseInt(e.fluidMax,10):1200});const n={resolver:e.resolver,output:{cssRoot:e.stylesDir,variables:e.variablesDir,variablesFilename:e.variablesFilename,utilities:e.utilitiesDir,utilitiesFilename:e.utilitiesFilename},transforms:{fluid:t,colorFallbackStrategy:e.colorFallback}};return Ce(n)}i(gn,"buildConfigFromFlags");function hn(e,t){const n={min:t.fluidMin?Number.parseInt(t.fluidMin,10):e.transforms.fluid.min,max:t.fluidMax?Number.parseInt(t.fluidMax,10):e.transforms.fluid.max};return{...e,resolver:t.resolver??e.resolver,transforms:{fluid:n,colorFallbackStrategy:t.colorFallback??e.transforms.colorFallbackStrategy},output:{...e.output,cssRoot:t.stylesDir??e.output.cssRoot,variables:t.variablesDir??e.output.variables,variablesFilename:t.variablesFilename??e.output.variablesFilename,utilities:t.utilitiesDir??e.output.utilities,utilitiesFilename:t.utilitiesFilename??e.output.utilitiesFilename}}}i(hn,"mergeConfigWithFlags");function wn(e){return!!(e.resolver||e.stylesDir||e.variablesDir||e.variablesFilename||e.utilitiesDir||e.utilitiesFilename||e.fluidMin||e.fluidMax||e.colorFallback)}i(wn,"hasRelevantFlags");async function yn(e){if(ke()){const{config:s}=await ee();return hn(s,e)}const t=await oe(process.cwd());if(t.found==="multiple")throw new p(h.GENERATE_MULTIPLE_RESOLVERS_NO_CONFIG(t.paths));const n=e.resolver??(t.found==="one"?t.path:void 0);if(n||wn(e))return gn({...e,resolver:n});throw new p(h.GENERATE_NO_CONFIG_OR_RESOLVER())}i(yn,"resolveConfig");const Sn=new U().name("generate").description("Generate CSS from your design tokens").option("--force","Skip overwrite confirmation").option("-s, --silent","Suppress logs and prompts").option("--resolver <path>","Path to token resolver file (.resolver.json)").option("--styles-dir <dir>","CSS output directory (default: 'src/styles')").option("--variables-dir <dir>","Token variables output directory (default: 'src/styles/global')").option("--variables-filename <name>","Token variables filename (default: 'tokens.variables.gen.css')").option("--utilities-dir <dir>","Utilities output directory (default: 'src/styles/utilities')").option("--utilities-filename <name>","Utilities filename (default: 'utilities.gen.css')").option("--fluid-min <number>","Minimum viewport width for fluid scaling (default: 320)").option("--fluid-max <number>","Maximum viewport width for fluid scaling (default: 1200)").option("--color-fallback <strategy>","Color fallback strategy: 'native' or 'polyfill' (default: native)").action(async e=>{try{if(e.silent||z(Y("Generate CSS")),ie(e.variablesFilename,"--variables-filename"),ie(e.utilitiesFilename,"--utilities-filename"),P("@sugarcube-sh/vite"))throw new p("Sugarcube vite plugin detected. When using the plugin, CSS is generated automatically during your build process. Remove the plugin to use CLI generation instead.");const t=await yn(e),{trees:n,resolved:s,modifiers:r}=await K(t),o=await mn(n,s,t,r);if(!e.silent){const a=o.map(u=>u.path),d=[...new Set(a)].map(u=>N(process.cwd(),u)).map(u=>({pending:`Write ${u}`,start:`Writing ${u}`,end:`Wrote ${u}`,while:i(async()=>{},"while")}));await T.tasks(d,{spacing:1,minDurationMs:0,successPauseMs:100,successMessage:"\u{1F389} Files written!"}),T.space(1),se(c.green("CSS generated successfully."))}}catch(t){J(t)}});async function Tn(e){const t={};return(e.stylesDir||e.variablesDir||e.variablesFilename||e.utilitiesDir||e.utilitiesFilename)&&(t.output={},e.stylesDir&&(t.output.cssRoot=e.stylesDir),e.variablesDir&&(t.output.variables=e.variablesDir),e.variablesFilename&&(t.output.variablesFilename=e.variablesFilename),e.utilitiesDir&&(t.output.utilities=e.utilitiesDir),e.utilitiesFilename&&(t.output.utilitiesFilename=e.utilitiesFilename)),(e.fluidMin!==void 0||e.colorFallback)&&(t.transforms={},e.fluidMin!==void 0&&e.fluidMax!==void 0&&(t.transforms.fluid={min:Number(e.fluidMin),max:Number(e.fluidMax)}),e.colorFallback&&(t.transforms.colorFallbackStrategy=e.colorFallback)),t}i(Tn,"buildSugarcubeConfig");function Ze(e){try{const t=ue.resolve(e,"package.json");if(!D(t))return null;const n=be(t,"utf-8");return JSON.parse(n)}catch{return null}}i(Ze,"getPackageJson");function M(e,t){if(!e)return!1;const n=e.dependencies,s=e.devDependencies;return!!(n?.[t]||s?.[t])}i(M,"hasDependency");function In(e,t){if(!e)return!1;const n=e.dependencies,s=e.devDependencies,r={...n,...s};return Object.keys(r).some(o=>o.startsWith(t))}i(In,"hasDependencyStartingWith");function bn(e){const t=D(ue.resolve(e,"src")),n=Ze(e),s=t?"src/design-tokens":"design-tokens",r=t?"src/styles":"styles",o=t?"src/components":"components";let a="none";return M(n,"next")?a=D(ue.resolve(e,`${t?"src/":""}app`))?"next-app":"next-pages":M(n,"astro")?a="astro":M(n,"nuxt")?a="nuxt":M(n,"@sveltejs/kit")?a="sveltekit":In(n,"@remix-run/")?a="remix":M(n,"@11ty/eleventy")?a="eleventy":M(n,"vite")&&(a="vite"),{framework:a,isSrcDir:t,tokensDir:s,stylesDir:r,componentDir:o}}i(bn,"getProjectInfo");function En(e,t){if(["vite","astro","nuxt","sveltekit","remix"].includes(e))return!0;if(e==="eleventy"){const s=Ze(t);return M(s,"vite")}return!1}i(En,"shouldInstallVitePlugin");function Qe(e,t=0){if(typeof e!="object"||e===null||t>Et)return!1;for(const[n,s]of Object.entries(e))if(!n.startsWith("$")&&typeof s=="object"&&s!==null&&("$value"in s||Qe(s,t+1)))return!0;return!1}i(Qe,"hasAnyToken");async function vn(e){try{const t=await de([It],{cwd:e,absolute:!0});for(const n of t)try{const s=await re.readFile(n,"utf-8"),r=JSON.parse(s);if(Qe(r))return!0}catch{}return!1}catch{return!1}}i(vn,"detectExistingTokens");function kn(e=process.cwd()){return St(e)!==null}i(kn,"isTypeScriptProject");async function Xe(e=process.cwd()){return kn(e)?"sugarcube.config.ts":"sugarcube.config.js"}i(Xe,"getConfigFileName");function _n(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)}i(_n,"isValidIdentifier");function Se(e,t=0){const n=" ".repeat(t);if(e===null)return"null";if(e===void 0)return"undefined";if(typeof e=="string")return JSON.stringify(e);if(typeof e=="number"||typeof e=="boolean")return String(e);if(Array.isArray(e))return e.length===0?"[]":`[
|
|
147
|
+
${e.map(r=>`${n} ${Se(r,t+1)}`).join(`,
|
|
145
148
|
`)}
|
|
146
149
|
${n}]`;if(typeof e=="object"){const s=Object.entries(e);return s.length===0?"{}":`{
|
|
147
|
-
${s.map(([o,a])=>{const l
|
|
150
|
+
${s.map(([o,a])=>{const l=_n(o)?o:JSON.stringify(o);return`${n} ${l}: ${Se(a,t+1)}`}).join(`,
|
|
148
151
|
`)}
|
|
149
|
-
${n}}`}return JSON.stringify(e)}i(
|
|
152
|
+
${n}}`}return JSON.stringify(e)}i(Se,"formatValue");function $n(e,t){const n=Se(e,0);return t?`import { defineConfig } from "${t}";
|
|
150
153
|
|
|
151
154
|
export default defineConfig(${n});
|
|
152
|
-
`:`${`// Configuration reference: ${
|
|
155
|
+
`:`${`// Configuration reference: ${$.CONFIGURATION}
|
|
153
156
|
export default `}${n};
|
|
154
|
-
`}i(
|
|
157
|
+
`}i($n,"formatConfigAsCode");async function Rn(e,t){try{const n=await Xe(),s=$n(e,t);await X(n,s,"utf-8")}catch(n){const s=n instanceof Error?`: ${n.message}`:"";throw new p(`Failed to write config file${s}`)}}i(Rn,"writeSugarcubeConfig");const Cn=i(async e=>{T.space(2),await V(200);let t="Next steps";if(e.pluginToInstall===Le)t+=`
|
|
155
158
|
|
|
156
159
|
`,t+=`1. Configure the plugin
|
|
157
160
|
`,t+=` Add the plugin to your build configuration:
|
|
@@ -166,7 +169,7 @@ export default `}${n};
|
|
|
166
169
|
`,t+=` ${c.cyan(O.CUBE)}`,t+=`
|
|
167
170
|
|
|
168
171
|
`,t+=`4. (Optional) Add components
|
|
169
|
-
`,t+=` ${c.cyan(O.COMPONENTS)}`;else{const n=`${e.stylesDir}/global/${
|
|
172
|
+
`,t+=` ${c.cyan(O.COMPONENTS)}`;else{const n=`${e.stylesDir}/global/${ce.output.variablesFilename}`;t+=`
|
|
170
173
|
|
|
171
174
|
`,t+=`1. Import the generated CSS
|
|
172
175
|
`;const s=e.isSrcDir?`"${n}"`:`"./${n}"`;t+=` ${c.cyan(`import ${s}`)}`,t+=`
|
|
@@ -177,6 +180,6 @@ export default `}${n};
|
|
|
177
180
|
`,t+=`3. (Optional) Add components
|
|
178
181
|
`,t+=` ${c.cyan(O.COMPONENTS)}`}t+=`
|
|
179
182
|
|
|
180
|
-
`,t+=`Docs: ${c.cyan("https://sugarcube.sh")}`,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
`,t+=`Docs: ${c.cyan("https://sugarcube.sh")}`,nn(t,{width:.75}),await V(200),T.break(1)},"nextSteps");async function Fn(e){await Cn(e)}i(Fn,"next");const Nn=i(async()=>{const e=["Welcome to sugarcube \u2014 the toolkit for seriously sweet frontends!"];T.space(1),await T.animated(e,{clear:!1})},"welcome");async function Dn(){ke()&&(ye(h.CONFIG_EXISTS(),{}),process.exit(1))}i(Dn,"preflightInit");function On(e,t){return e.map(n=>({...n,css:`@layer ${t} {
|
|
184
|
+
${n.css}}
|
|
185
|
+
`}))}i(On,"wrapInLayer");async function An(e){const t=bn(process.cwd()),n=e.tokensDir||t.tokensDir,s=e.stylesDir||t.stylesDir,r=await vn(n);let o=null;if(r){const a=await oe(n);if(a.found==="none")throw new p(h.RESOLVER_NOT_FOUND(n));if(a.found==="multiple")throw new p(h.RESOLVER_MULTIPLE_FOUND(a.paths));o=a.path}return{tokensDir:n,stylesDir:s,isSrcDir:t.isSrcDir,hasExistingTokens:r,resolverPath:o,framework:t.framework}}i(An,"initializeProjectContext");function Ln(e,t,n){const s=t?null:e.kit||fe;if(e.skipDeps)return{starterKit:s,pluginToInstall:null,cliToInstall:null};const r=Pn(n,process.cwd());return{starterKit:s,pluginToInstall:r,cliToInstall:r?null:bt}}i(Ln,"determineInstallationTargets");function Pn(e,t){return En(e,t)?Le:null}i(Pn,"determinePlugin");async function Mn(e,t,n,s,r){const o=await Ke(process.cwd(),{withFallback:!0});return t.resolverPath&&(n.resolver=t.resolverPath),{options:e,...t,isSrcDir:t.isSrcDir,config:n,sugarcubeConfig:s,...r,packageManager:o,createdFiles:[],createdDirectories:[],installedDependencies:[],tasks:[]}}i(Mn,"buildInitContext");async function Un(e){const{trees:t,resolved:n}=await K(e.config);e.setupResult={config:e.config,createdTokenPaths:[],trees:t,resolved:n,tokenFiles:[],tokensDir:e.tokensDir}}i(Un,"processExistingTokens");async function jn(e){!e.hasExistingTokens&&e.starterKit?await Mt(e):await Un(e)}i(jn,"setupDesignTokens");async function Gn(e){if(!e.setupResult)throw new p(h.INITIALIZATION_INCOMPLETE());const{trees:t,resolved:n}=e.setupResult,s=e.config.output.layers,r=await ae(t,n,e.config);let o=await _e(r,e.config);s&&(o=On(o,s.variables)),await $e(o)}i(Gn,"writeCSSVariables");async function Bn(e){if(!e.setupResult)throw new p(h.INITIALIZATION_INCOMPLETE());const{trees:t,resolved:n}=e.setupResult,s=await ae(t,n,e.config),r=await ze(s,e.config);r.length&&await Re(r)}i(Bn,"writeCSSUtilities");async function Vn(e){if(e.pluginToInstall&&!P(e.pluginToInstall))try{await te([e.pluginToInstall],process.cwd(),e.packageManager,{devDependency:!0}),e.installedDependencies.push(e.pluginToInstall)}catch{throw new p(h.PLUGIN_INSTALL_FAILED({pluginToInstall:e.pluginToInstall,packageManager:e.packageManager}))}}i(Vn,"installPlugins");async function xn(e){if(e.cliToInstall&&!P(e.cliToInstall))try{await te([e.cliToInstall],process.cwd(),e.packageManager,{devDependency:!0}),e.installedDependencies.push(e.cliToInstall)}catch{throw new p(h.CLI_INSTALL_FAILED({packageManager:e.packageManager}))}}i(xn,"installCLI");function et(e){return!!(e.stylesDir||e.variablesDir||e.variablesFilename||e.utilitiesDir||e.utilitiesFilename||e.fluidMin||e.fluidMax||e.colorFallback)}i(et,"hasCustomizationFlags");function Wn(e){return e.pluginToInstall?"@sugarcube-sh/vite":e.cliToInstall?"@sugarcube-sh/cli":null}i(Wn,"getTypeSource");async function tt(e){if(et(e.options))try{await Rn(e.sugarcubeConfig,Wn(e));const t=await Xe();e.createdFiles.push(t)}catch{throw new p(h.CONFIG_WRITE_FAILED())}}i(tt,"finalize");function Kn(e){const t=[];if(e.hasExistingTokens?t.push({pending:"Looking for existing tokens",start:"Looking for existing tokens...",end:`Existing tokens found at ${e.tokensDir} ${b("\u2192","->")} using them`,while:i(async()=>{},"while")}):e.starterKit&&t.push({pending:"Looking for existing tokens",start:"Looking for existing tokens...",end:`No existing tokens detected ${b("\u2192","->")} adding starter kit`,while:i(async()=>{},"while")}),e.pluginToInstall){const n="Vite";P(e.pluginToInstall)?t.push({pending:`Checking for ${n} compatibility`,start:`Checking for ${n} compatibility...`,end:`${n} plugin already installed ${b("\u2192","->")} skipping plugin installation`,while:i(async()=>{},"while")}):t.push({pending:"Checking for Vite compatibility",start:"Checking for Vite compatibility...",end:`Vite detected ${b("\u2192","->")} plugin will be installed`,while:i(async()=>{},"while")})}else{const n=e.options.skipDeps;t.push({pending:"Checking for Vite compatibility",start:"Checking for Vite compatibility...",end:n?`Dependencies skipped ${b("\u2192","->")} no plugins or CLI will be installed`:`No Vite detected ${b("\u2192","->")} CSS will be generated as file(s)`,while:i(async()=>{},"while")})}return t}i(Kn,"buildDetectionTasks");async function Yn(e){if(e.tasks.push({pending:e.hasExistingTokens?"Process existing design tokens":"Add design tokens",start:e.hasExistingTokens?"Processing existing design tokens...":"Adding design tokens...",end:e.hasExistingTokens?"Design tokens processed":"Design tokens added",while:i(async()=>{await jn(e)},"while")}),!e.pluginToInstall)e.tasks.push({pending:"Generate CSS variables",start:"Generating CSS variables...",end:"CSS variables generated",while:i(async()=>{await Gn(e)},"while")}),e.tasks.push({pending:"Generate CSS utilities",start:"Generating CSS utilities...",end:"CSS utilities generated",while:i(async()=>{await Bn(e)},"while")}),e.cliToInstall&&!P(e.cliToInstall)&&e.tasks.push({pending:"Install CLI",start:"Installing CLI...",end:"CLI installed",while:i(async()=>{await xn(e)},"while")});else if(e.pluginToInstall&&!P(e.pluginToInstall)){const t="Vite";e.tasks.push({pending:`Install ${t} plugin`,start:`Installing ${t} plugin...`,end:`${t} plugin installed`,while:i(async()=>{await Vn(e)},"while")})}et(e.options)?e.tasks.push({pending:"Write configuration file",start:"Writing configuration file...",end:"Configuration file written",while:i(async()=>{await tt(e)},"while")}):e.tasks.push({pending:"Finalize setup",start:"Finalizing...",end:"Setup complete",while:i(async()=>{await tt(e)},"while")})}i(Yn,"buildExecutionTasks");const Hn=new U().name("init").description("Initialize a new sugarcube project").option("--kit <kit>",`Starter kit to use (default: ${fe})`,fe).option("--tokens-dir <dir>","Design tokens directory (e.g., 'src/design-tokens')").option("--styles-dir <dir>","Styles output directory (e.g., 'src/styles')").option("--variables-dir <dir>","Token variables directory (e.g., 'src/styles/global')").option("--variables-filename <name>","Token variables filename (default: 'tokens.variables.gen.css')").option("--utilities-dir <dir>","Utilities directory (e.g., 'src/styles/utilities')").option("--utilities-filename <name>","Utilities filename (default: 'utilities.gen.css')").option("--fluid-min <number>","Minimum viewport width for fluid scaling (default: 320)").option("--fluid-max <number>","Maximum viewport width for fluid scaling (default: 1200)").option("--color-fallback <strategy>","Color fallback strategy: 'native' or 'polyfill' (default: native)").option("--skip-deps","Don't install any sugarcube packages").action(async e=>{let t;try{ie(e.variablesFilename,"--variables-filename"),ie(e.utilitiesFilename,"--utilities-filename"),await Dn();const n=await An(e),s=await Tn(e),r=Ce(s),o=Ln(e,n.hasExistingTokens,n.framework);t=await Mn(e,n,r,s,o),z(Y("sugarcube")),await Nn();const a=Kn(t);a.length>0&&(T.message("Detecting project\u2026"),await T.tasks(a,{minDurationMs:1e3})),t.tasks=[],await Yn(t),t.tasks.length>0&&(T.message("Setting things up\u2026"),await T.tasks(t.tasks,{successMessage:"\u{1F389} Tasks completed successfully!"})),await Fn(t)}catch(n){J(n)}}),zn=new U().name("validate").description("Validate design token files").argument("[paths...]","Token files or directories to validate (e.g., src/design-tokens)").action(async e=>{try{if(z(Y("Validate")),!e.length)try{const{config:o}=await ee();await K(o),se(c.greenBright("All tokens valid \u2728"));return}catch{throw new p(h.VALIDATE_NO_PATH_SPECIFIED())}for(const o of e)if(!D(o))throw new p(h.VALIDATE_PATH_NOT_FOUND(o));const n=(await de(e.map(o=>o.endsWith(".json")?o:_(o,"**/*.json")),{absolute:!0})).filter(o=>!o.endsWith(".resolver.json"));if(n.length===0)throw new p(h.VALIDATE_NO_TOKEN_FILES());const s={};for(const o of n){const a=await Ee(o,"utf-8"),l=N(process.cwd(),o);s[l]={content:a}}const r={output:ce.output,transforms:ce.transforms};await K(r,s),se(c.greenBright("All tokens valid \u2728"))}catch(t){J(t)}});process.on("SIGINT",()=>process.exit(0)),process.on("SIGTERM",()=>process.exit(0));async function Jn(){const e=new U().name("sugarcube").description("CLI for sugarcube").version(Ae.version,"-v, --version","display the version number");e.addCommand(Hn).addCommand(Sn).addCommand(zn).addCommand(ln).addCommand(un),e.parse()}i(Jn,"main"),Jn();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sugarcube-sh/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": false
|
|
@@ -58,12 +58,12 @@
|
|
|
58
58
|
"picocolors": "1.1.1",
|
|
59
59
|
"tinyglobby": "^0.2.9",
|
|
60
60
|
"zod": "^3.23.8",
|
|
61
|
-
"@sugarcube-sh/core": "0.0.
|
|
61
|
+
"@sugarcube-sh/core": "0.0.3"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"cross-env": "7.0.3",
|
|
65
|
-
"pkgroll": "2.
|
|
66
|
-
"tsx": "4.
|
|
65
|
+
"pkgroll": "^2.26.0",
|
|
66
|
+
"tsx": "^4.21.0"
|
|
67
67
|
},
|
|
68
68
|
"engines": {
|
|
69
69
|
"node": ">=18.0.0"
|