saneprint 1.0.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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +257 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to saneprint will be documented here.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## [1.0.0] - 2026-03-02
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Initial release of the `saneprint` CLI
|
|
12
|
+
- Feature-based architecture support (`src/features/...`)
|
|
13
|
+
- `theme.json` ingestion with automatic "remification" of units
|
|
14
|
+
- Production-grade Next.js boilerplate with TanStack Query and Redux Toolkit
|
|
15
|
+
- Brand identity with custom terminal styling
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 saneprint contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# saneprint
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/saneprint)
|
|
4
|
+
[](https://www.npmjs.com/package/saneprint)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
|
|
8
|
+
**saneprint** is a scaffolding tool that eliminates the constant AI back-and-forth. Start with a production-grade foundation that AI actually understands—ship features faster with zero refactoring tax.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The Problem with "Vibe Coding"
|
|
13
|
+
|
|
14
|
+
You've probably been there: You ask your AI assistant (Cursor, Claude, Copilot) to "build a signup form" or "create a dashboard layout." The AI generates code that _looks_ right: nice indentation, modern syntax, the works.
|
|
15
|
+
|
|
16
|
+
But then reality hits:
|
|
17
|
+
|
|
18
|
+
- **Inconsistent Units**: One component uses `px`, another uses `rem`, another hardcodes pixel values
|
|
19
|
+
- **No Design System**: Colors are hardcoded HEX values (`#3b82f6`) scattered everywhere
|
|
20
|
+
- **Architectural Chaos**: AI invents new folder structures for every feature because there's no clear pattern to follow
|
|
21
|
+
- **Component Bloat**: 800-line "God Components" that mix logic, UI, and side effects
|
|
22
|
+
- **Copy-Paste Hell**: The same button styled 5 different ways across your app
|
|
23
|
+
|
|
24
|
+
This is **"Vibe Coding"**: code that feels correct but accumulates **massive technical debt from Day 1**.
|
|
25
|
+
|
|
26
|
+
Without a solid foundation, you're constantly fighting AI's tendency to hallucinate new patterns instead of following existing ones.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Why saneprint Works
|
|
31
|
+
|
|
32
|
+
**You stop explaining. AI starts shipping.**
|
|
33
|
+
|
|
34
|
+
With a solid foundation in place:
|
|
35
|
+
|
|
36
|
+
- ✅ **Reduced Cognitive Load**: No more "where does this go?" or "how do we handle auth?"
|
|
37
|
+
- ✅ **Faster Velocity**: AI references existing patterns instead of inventing new ones—features ship in hours, not days
|
|
38
|
+
- ✅ **Less Back-and-Forth**: Point to your auth flow once. AI replicates it perfectly for every new feature.
|
|
39
|
+
- ✅ **Quality by Default**: Design system enforcement means zero inconsistencies sneak into production
|
|
40
|
+
- ✅ **Lower Maintenance**: When everything follows the same pattern, scaling to 50+ routes is painless
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## What You Get Out of the Box
|
|
45
|
+
|
|
46
|
+
### 1. Design System Pipeline (JSON → Code)
|
|
47
|
+
|
|
48
|
+
Without a design system, it's easy to fall into the trap: copy-paste Tailwind classes, use `bg-blue-500` here and `bg-blue-600` there, hope it all looks consistent in the end.
|
|
49
|
+
|
|
50
|
+
saneprint **forces** a design system:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx saneprint
|
|
54
|
+
# Choose: Custom Design System
|
|
55
|
+
# Define your colors, spacing, typography
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The CLI automatically:
|
|
59
|
+
|
|
60
|
+
- ✅ Converts all `px` values to `rem` (responsive by default)
|
|
61
|
+
- ✅ Generates CSS custom properties mapped to Tailwind
|
|
62
|
+
- ✅ Creates semantic color roles (`--color-brand`, `--color-accent`)
|
|
63
|
+
- ✅ Injects theme into your entire UI system
|
|
64
|
+
|
|
65
|
+
**Impact**: No more "fix all the inconsistent buttons" tickets. No designer QA cycles wasted on color mismatches. Your AI assistant becomes a productivity multiplier, not a cleanup job generator.
|
|
66
|
+
|
|
67
|
+
### 2. Feature-Based Architecture
|
|
68
|
+
|
|
69
|
+
No more "components folder soup." Every feature is self-contained:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
src/features/
|
|
73
|
+
├── core/ # Reusable UI (buttons, inputs, modals)
|
|
74
|
+
├── auth/ # Complete auth flow (login, signup, OTP)
|
|
75
|
+
└── protected/ # Domain features (dashboard, users, etc.)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Each feature has its own:
|
|
79
|
+
|
|
80
|
+
- `components/` - Feature-specific UI
|
|
81
|
+
- `hooks/` - Business logic extraction
|
|
82
|
+
- `pages/` - Page-level compositions
|
|
83
|
+
- `schemas/` - Zod validation schemas
|
|
84
|
+
- `index.ts` - Public API exports
|
|
85
|
+
|
|
86
|
+
**Impact**: Zero "where should this file go?" questions. You and your AI work 3x faster because the next step is always obvious.
|
|
87
|
+
|
|
88
|
+
### 3. Production-Ready Auth Flow
|
|
89
|
+
|
|
90
|
+
Real apps need more than a basic login form. saneprint includes:
|
|
91
|
+
|
|
92
|
+
- ✅ Multi-step signup with OTP verification
|
|
93
|
+
- ✅ Forgot password flow with secure reset
|
|
94
|
+
- ✅ Cookie-based auth (HttpOnly, Secure, SameSite)
|
|
95
|
+
- ✅ Redux persistence for session state
|
|
96
|
+
- ✅ Protected route middleware
|
|
97
|
+
- ✅ Complete form validations with Zod
|
|
98
|
+
|
|
99
|
+
**Impact**: New features inherit production-grade patterns automatically. No "let's add error handling later" tech debt. Ship confidently from commit one.
|
|
100
|
+
|
|
101
|
+
### 4. Living Styleguide
|
|
102
|
+
|
|
103
|
+
Every project includes a `/styleguide` route that showcases:
|
|
104
|
+
|
|
105
|
+
- Color system with semantic roles
|
|
106
|
+
- Typography hierarchy
|
|
107
|
+
- All form components (Input, Select, OTP, MultiSelect)
|
|
108
|
+
- Interactive elements (Buttons, Modals, Tooltips)
|
|
109
|
+
- Data visualization (Tables with virtualization)
|
|
110
|
+
- Best practices guide
|
|
111
|
+
|
|
112
|
+
**Impact**: Stop recreating the same component 5 different ways. Your styleguide is a single source of truth that prevents drift before it starts.
|
|
113
|
+
|
|
114
|
+
### 5. Single Responsibility by Design
|
|
115
|
+
|
|
116
|
+
Components naturally stay focused and maintainable because the structure enforces separation of concerns:
|
|
117
|
+
|
|
118
|
+
- **Logic separated from UI**: Complex state management lives in custom hooks
|
|
119
|
+
- **Primitives vs Compositions**: Base components (`Button`, `Input`) live in `core/components`, feature-specific compositions stay in their domains
|
|
120
|
+
- **No mixed responsibilities**: Each component does one thing well
|
|
121
|
+
- **Design tokens, not inline styles**: All styling driven by the theme system
|
|
122
|
+
|
|
123
|
+
**Impact**: Onboard new developers in hours, not weeks. Every file is scannable. Debugging takes minutes because responsibilities are crystal clear.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Real-World Workflow
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npx saneprint
|
|
131
|
+
cd my-project
|
|
132
|
+
pnpm install
|
|
133
|
+
pnpm dev
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
When you prompt your AI:
|
|
137
|
+
|
|
138
|
+
> "Create a user management feature in `src/features/users`. Include a `UserListPage` that fetches data with TanStack Query, a `UserCard` component, and Zod schemas for validation. Follow the same structure as the auth feature."
|
|
139
|
+
|
|
140
|
+
AI has a clear reference to follow - it sees how auth is organized and replicates that pattern for users.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## What You Save
|
|
145
|
+
|
|
146
|
+
**Time:**
|
|
147
|
+
|
|
148
|
+
- No "which folder?" decisions (20+ mins per feature)
|
|
149
|
+
- No "let's standardize our buttons" refactors (5-10 hours)
|
|
150
|
+
- No "why is this color different?" design QA cycles (2-3 hours per sprint)
|
|
151
|
+
- No onboarding maze for new developers (2-3 days → 4 hours)
|
|
152
|
+
|
|
153
|
+
**Frustration:**
|
|
154
|
+
|
|
155
|
+
- Zero "AI reinvented the auth flow" rewrites
|
|
156
|
+
- Zero "I can't find where login logic lives" treasure hunts
|
|
157
|
+
- Zero "our codebase looks like 5 different people built it" embarrassment
|
|
158
|
+
|
|
159
|
+
**Money:**
|
|
160
|
+
|
|
161
|
+
- Lower maintenance costs (fewer bug tickets from inconsistent patterns)
|
|
162
|
+
- Faster feature delivery (ship 2-3x more with the same team)
|
|
163
|
+
- Better retention (developers actually enjoy working in the codebase)
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Quickstart
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npx saneprint
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Follow the prompts to choose:
|
|
174
|
+
|
|
175
|
+
- Project type (Next.js)
|
|
176
|
+
- Design system (default or custom)
|
|
177
|
+
- Project name
|
|
178
|
+
|
|
179
|
+
**Then:**
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
cd your-project-name
|
|
183
|
+
pnpm install
|
|
184
|
+
pnpm dev
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Visit `http://localhost:3000/styleguide` to see your design system in action.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## The Stack
|
|
192
|
+
|
|
193
|
+
**Opinionated and Modern:**
|
|
194
|
+
|
|
195
|
+
- **Framework**: Next.js 14+ (App Router, Server Components)
|
|
196
|
+
- **Styling**: Tailwind CSS v4 (driven by design tokens)
|
|
197
|
+
- **Validation**: Zod (type-safe runtime validation)
|
|
198
|
+
- **Forms**: React Hook Form (performance-optimized)
|
|
199
|
+
- **State**: Redux Toolkit + TanStack Query (persistent + server state)
|
|
200
|
+
- **Icons**: Phosphor Icons (one library, consistent style)
|
|
201
|
+
- **Color System**: OKLCH (perceptually uniform colors)
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## What Makes This "Production-Grade"?
|
|
206
|
+
|
|
207
|
+
❌ **NOT** a tutorial project
|
|
208
|
+
❌ **NOT** a minimal starter
|
|
209
|
+
✅ **IS** a foundation you'd actually use in production
|
|
210
|
+
|
|
211
|
+
- HttpOnly cookie authentication (not localStorage JWT)
|
|
212
|
+
- Middleware-based route protection (Edge-optimized)
|
|
213
|
+
- Comprehensive error boundaries
|
|
214
|
+
- SEO metadata helpers
|
|
215
|
+
- Accessibility standards (ARIA labels, keyboard navigation)
|
|
216
|
+
- Performance optimizations (virtualized tables, debounced search)
|
|
217
|
+
- Type-safe API layer with environment guards
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Philosophy
|
|
222
|
+
|
|
223
|
+
**Stop fighting your tools. Start shipping.**
|
|
224
|
+
|
|
225
|
+
- **Less Explaining, More Building** - AI learns from your code, not from document after document of rules you'll never keep updated.
|
|
226
|
+
|
|
227
|
+
- **Velocity That Scales** - Your first feature takes 2 hours. Your 50th feature? Still 2 hours. Structure prevents slowdown.
|
|
228
|
+
|
|
229
|
+
- **Design Systems Without the Overhead** - You get token-based styling and a living styleguide automatically. No design-dev translation layer needed.
|
|
230
|
+
|
|
231
|
+
- **Quality That Compounds** - Every feature you ship makes the next one easier. Patterns reinforce themselves instead of diverging.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Who This Is For
|
|
236
|
+
|
|
237
|
+
- **Solo Devs** shipping fast with AI assistance
|
|
238
|
+
- **Freelancers** delivering maintainable codebases to clients
|
|
239
|
+
- **Product Engineers** focused on features, not infrastructure
|
|
240
|
+
- **Designers who code** wanting a solid foundation that respects design systems and enforces their tokens from day one
|
|
241
|
+
- **Tech Leads** standardizing team output
|
|
242
|
+
- **Founders** who need quality code without a senior engineer (yet)
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Author
|
|
247
|
+
|
|
248
|
+
Built by **Karishma Garg**, Product Engineer
|
|
249
|
+
|
|
250
|
+
- GitHub: [@karishma-dev](https://github.com/karishma-dev)
|
|
251
|
+
- Portfolio: [karishma.dev](https://karishma.dev)
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
MIT. See [LICENSE](./LICENSE) for details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{Command as he}from"commander";import*as c from"@clack/prompts";import p from"chalk";import pe from"path";import*as i from"@clack/prompts";import f from"chalk";import b from"fs-extra";import re from"path";var u={version:"1.0.0",colors:{primary:{50:"oklch(0.985 0.015 180)",100:"oklch(0.97 0.04 180)",200:"oklch(0.94 0.07 180)",300:"oklch(0.89 0.1 180)",400:"oklch(0.79 0.13 180)",500:"oklch(0.7 0.14 180)",600:"oklch(0.59 0.13 185)",700:"oklch(0.5 0.11 190)",800:"oklch(0.41 0.09 190)",900:"oklch(0.35 0.07 195)"},secondary:{50:"oklch(0.98 0.01 200)",100:"oklch(0.95 0.02 200)",200:"oklch(0.88 0.04 200)",300:"oklch(0.8 0.06 200)",400:"oklch(0.7 0.08 200)",500:"oklch(0.6 0.09 200)",600:"oklch(0.5 0.08 200)",700:"oklch(0.4 0.07 200)",800:"oklch(0.3 0.06 200)",900:"oklch(0.2 0.05 200)"},tertiary:{50:"oklch(0.97 0.02 310)",100:"oklch(0.93 0.04 310)",200:"oklch(0.87 0.08 310)",300:"oklch(0.79 0.13 310)",400:"oklch(0.7 0.18 310)",500:"oklch(0.62 0.22 310)",600:"oklch(0.54 0.2 310)",700:"oklch(0.46 0.17 310)",800:"oklch(0.38 0.14 310)",900:"oklch(0.3 0.1 310)"},neutral:{0:"#ffffff",50:"oklch(0.99 0 0)",100:"oklch(0.97 0 0)",200:"oklch(0.92 0 0)",300:"oklch(0.86 0 0)",400:"oklch(0.68 0 0)",500:"oklch(0.52 0 0)",600:"oklch(0.38 0 0)",700:"oklch(0.3 0 0)",800:"oklch(0.19 0 0)",900:"oklch(0.13 0 0)",1e3:"#000000"},danger:{500:"oklch(0.628 0.218 29)",600:"oklch(0.55 0.2 29)"},success:{500:"oklch(0.698 0.176 142)",600:"oklch(0.6 0.16 142)"},warning:{500:"oklch(0.705 0.15 65)",600:"oklch(0.62 0.14 65)"},info:{500:"oklch(0.596 0.182 255)",600:"oklch(0.52 0.17 255)"}},typography:{fontFamily:{sans:"var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif",mono:"var(--font-geist-mono), ui-monospace, monospace"},styles:{heading1:{size:"48px",weight:"700",lineHeight:"1.1",letterSpacing:"-0.02em"},heading2:{size:"36px",weight:"700",lineHeight:"1.2",letterSpacing:"-0.01em"},heading3:{size:"30px",weight:"700",lineHeight:"1.25",letterSpacing:"-0.01em"},heading4:{size:"24px",weight:"600",lineHeight:"1.3",letterSpacing:"-0.005em"},heading5:{size:"20px",weight:"600",lineHeight:"1.35",letterSpacing:"0"},heading6:{size:"18px",weight:"600",lineHeight:"1.4",letterSpacing:"0"},body:{size:"16px",weight:"400",lineHeight:"1.5",letterSpacing:"0"},bodySm:{size:"14px",weight:"400",lineHeight:"1.5",letterSpacing:"0"},label:{size:"14px",weight:"600",lineHeight:"1.4",letterSpacing:"0.01em"},labelSm:{size:"12px",weight:"600",lineHeight:"1.35",letterSpacing:"0.01em"},caption:{size:"12px",weight:"400",lineHeight:"1.4",letterSpacing:"0"}}},themes:{light:{background:"{colors.neutral.50}",surface:"{colors.neutral.0}",text:"{colors.neutral.900}",textMuted:"{colors.neutral.600}",border:"{colors.neutral.200}",primary:"{colors.primary.500}",primaryHover:"{colors.primary.600}",secondary:"{colors.secondary.500}",secondaryHover:"{colors.secondary.600}",tertiary:"{colors.tertiary.500}",tertiaryHover:"{colors.tertiary.600}",danger:"{colors.danger.500}",dangerHover:"{colors.danger.600}",onPrimary:"{colors.neutral.0}",onSecondary:"{colors.neutral.0}",onTertiary:"{colors.neutral.0}",onDanger:"{colors.neutral.0}",inputBackground:"{colors.neutral.0}",inputBorder:"{colors.neutral.300}",inputFocusRing:"{colors.primary.500}"}}};var C="/* theme start */",S="/* theme end */",M={background:"background",surface:"surface",text:"foreground",textMuted:"muted",border:"border",primary:"brand",primaryHover:"brand-hover",secondary:"accent",secondaryHover:"accent-hover",tertiary:"tertiary",tertiaryHover:"tertiary-hover",danger:"danger",dangerHover:"danger-hover",onPrimary:"on-brand",onSecondary:"on-accent",onTertiary:"on-tertiary",onDanger:"on-danger",inputBackground:"input",inputBorder:"input-border",inputFocusRing:"focus-ring"},z=[{name:"primary",baseColor:"var(--color-brand)",hoverColor:"var(--color-brand-hover)",foregroundColor:"var(--color-on-brand)"},{name:"secondary",baseColor:"var(--color-accent)",hoverColor:"var(--color-accent-hover)",foregroundColor:"var(--color-on-accent)"},{name:"tertiary",baseColor:"var(--color-tertiary)",hoverColor:"var(--color-tertiary-hover)",foregroundColor:"var(--color-on-tertiary)"},{name:"danger",baseColor:"var(--color-danger)",hoverColor:"var(--color-danger-hover)",foregroundColor:"var(--color-on-danger)"}],V={heading1:"heading-1",heading2:"heading-2",heading3:"heading-3",heading4:"heading-4",heading5:"heading-5",heading6:"heading-6",body:"body",bodySm:"body-sm",label:"label",labelSm:"label-sm",caption:"caption"};function E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function B(e){return JSON.parse(JSON.stringify(e))}function J(e){return Number.parseFloat(e.toFixed(4)).toString()}function U(e){return e.replace(/(-?\d*\.?\d+)px\b/g,(r,o)=>{let t=Number.parseFloat(o)/16;return`${J(t)}rem`})}function X(e){return U(e)}function d(e,r,o){if(r===null||typeof r!="object"||Array.isArray(r)){if(typeof e!=typeof r)throw new Error(`Invalid value at ${o}. Expected ${typeof r}.`);return}if(e===null||typeof e!="object"||Array.isArray(e))throw new Error(`Invalid value at ${o}. Expected an object.`);let t=r,n=e,s=Object.keys(t).sort(),x=Object.keys(n).sort();if(s.length!==x.length||s.some((g,v)=>g!==x[v]))throw new Error(`Theme schema mismatch at ${o}. Edit values only; do not add or remove keys.`);for(let g of s){let v=o==="theme"?`theme.${g}`:`${o}.${g}`;d(n[g],t[g],v)}}function $(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Y(e){if(!$(e))throw new Error("Invalid value at theme.colors. Expected an object.");d(e,u.colors,"theme.colors")}function h(e,r){return` ${e}: ${r};`}function a(e,r){return[` ${e}`,...r.map(o=>` ${o}`)," }"]}function G(e,r){let o=e.split("."),t=r;for(let n of o){if(t===null||typeof t!="object"||!(n in t))throw new Error(`Could not resolve token reference {${e}}.`);t=t[n]}if(typeof t!="string")throw new Error(`Token reference {${e}} did not resolve to a string value.`);return t}function j(e,r){return e.replace(/\{([^}]+)\}/g,(o,t)=>j(G(t,r),r))}function m(e,r){return X(j(e,r))}function K(e,r){for(let[o,t]of Object.entries(r.colors))for(let[n,s]of Object.entries(t))e.push(h(`--color-${o}-${n}`,m(s,r)))}function W(e,r,o){for(let[t,n]of Object.entries(M))e.push(h(`--color-${n}`,m(r[t],o)))}function q(e,r){e.push(h("--font-sans",m(r.typography.fontFamily.sans,r))),e.push(h("--font-mono",m(r.typography.fontFamily.mono,r)));for(let[o,t]of Object.entries(r.typography.styles)){let n=t;e.push(h(`--text-${o}`,m(n.size,r))),e.push(h(`--text-${o}--line-height`,m(n.lineHeight,r))),e.push(h(`--tracking-${o}`,m(n.letterSpacing,r))),e.push(h(`--font-weight-${o}`,m(n.weight,r)))}}function Q(e){let r=["@theme inline {"];return K(r,e),W(r,e.themes.light,e),q(r,e),r.push("}"),r}function Z(e){let r=[];for(let o of Object.keys(e.typography.styles)){let t=V[o];r.push(`@utility ${t} {`,` font-size: var(--text-${o});`,` font-weight: var(--font-weight-${o});`,` line-height: var(--text-${o}--line-height);`,` letter-spacing: var(--tracking-${o});`,"}")}return r}function ee(){let e=["@layer components {"];e.push(...a(".btn {",["display: inline-flex;","align-items: center;","justify-content: center;","gap: 0.5rem;","border-radius: 0.75rem;","border: 1px solid transparent;","font-size: var(--text-label);","font-weight: var(--font-weight-label);","line-height: var(--text-label--line-height);","letter-spacing: var(--tracking-label);","transition-property: background-color, border-color, color, box-shadow, opacity;","transition-duration: 150ms;","transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);","cursor: pointer;"])),e.push(...a(".btn:focus-visible {",["outline: none;","box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus-ring) 35%, transparent);"])),e.push(...a(".btn:disabled {",["cursor: not-allowed;","opacity: 0.55;"]));for(let r of z)e.push(...a(`.btn-${r.name}-filled {`,[`background-color: ${r.baseColor};`,`border-color: ${r.baseColor};`,`color: ${r.foregroundColor};`])),e.push(...a(`.btn-${r.name}-filled:hover {`,[`background-color: ${r.hoverColor};`,`border-color: ${r.hoverColor};`])),e.push(...a(`.btn-${r.name}-outlined {`,["background-color: transparent;",`border-color: ${r.baseColor};`,`color: ${r.baseColor};`])),e.push(...a(`.btn-${r.name}-outlined:hover {`,[`background-color: color-mix(in srgb, ${r.baseColor} 10%, transparent);`,`border-color: ${r.hoverColor};`,`color: ${r.hoverColor};`])),e.push(...a(`.btn-${r.name}-ghost {`,["background-color: transparent;","border-color: transparent;",`color: ${r.baseColor};`])),e.push(...a(`.btn-${r.name}-ghost:hover {`,[`background-color: color-mix(in srgb, ${r.baseColor} 12%, transparent);`,`color: ${r.hoverColor};`]));return e.push(...a(".input {",["width: 100%;","border-radius: 0.75rem;","border: 1px solid var(--color-input-border);","background-color: var(--color-input);","font-size: var(--text-body);","font-weight: var(--font-weight-body);","line-height: var(--text-body--line-height);","letter-spacing: var(--tracking-body);","color: var(--color-foreground);","transition-property: border-color, box-shadow, background-color;","transition-duration: 150ms;","transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);","outline: none;"])),e.push(...a(".input::placeholder {",["color: var(--color-muted);"])),e.push(...a(".input:focus-visible {",["border-color: var(--color-focus-ring);","box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus-ring) 25%, transparent);"])),e.push("}"),e}function y(){return B(u)}function k(e){if(!$(e))throw new Error("Invalid value at theme. Expected an object.");let r=e.version,o=e.colors,t=e.typography,n=e.themes;if(typeof r!="string")throw new Error("Invalid value at theme.version. Expected a string.");return Y(o),d(t,u.typography,"theme.typography"),d(n,u.themes,"theme.themes"),{version:r,colors:o,typography:t,themes:{light:n.light}}}function O(e){return[C,...Q(e),"",...Z(e),"",...ee(),S].join(`
|
|
3
|
+
`)}function P(e,r){let o=new RegExp(`${E(C)}[\\s\\S]*?${E(S)}`,"m");if(!o.test(e))throw new Error("Could not find theme block in globals.css.");return e.replace(o,r.trim())}async function R(e){return e.path&&e.type&&e.name&&e.designSystem?{path:e.path,type:e.type,websiteName:e.name,designSystem:e.designSystem}:{...await i.group({path:()=>i.text({message:"Where should we create your project?",placeholder:"./my-app",initialValue:e.path}),websiteName:()=>i.text({message:"What is your website name?",placeholder:"Studio",initialValue:e.name}),designSystem:()=>i.select({message:"Choose your Design System",initialValue:e.designSystem,options:[{value:"default",label:"saneprint Default",hint:"Ready-to-go premium tokens"},{value:"custom",label:"Custom (Enterprise Level 2)",hint:"Generate canonical theme.json"}]})},{onCancel:()=>{i.cancel("Operation cancelled."),process.exit(0)}}),type:"next"}}async function N(e){let r=re.resolve(process.cwd(),"theme.json"),o=y();if(b.existsSync(r))try{return k(await b.readJSON(r))}catch{}for(e.primary&&(o.colors.primary[500]=e.primary,o.colors.primary[600]=e.primary,o.themes.light.primary=e.primary,o.themes.light.primaryHover=e.primary),e.secondary&&(o.colors.secondary[500]=e.secondary,o.colors.secondary[600]=e.secondary,o.themes.light.secondary=e.secondary,o.themes.light.secondaryHover=e.secondary),await b.writeJSON(r,o,{spaces:2}),i.note(`I've created a canonical ${f.hex("#106D7C")("theme.json")} in your current directory.
|
|
4
|
+
|
|
5
|
+
Edit values only. Do not add, delete, or rename keys.
|
|
6
|
+
The default schema now includes ${f.hex("#106D7C")("tertiary")} color tokens and semantic roles out of the box.
|
|
7
|
+
This schema drives the generated Tailwind tokens, color roles, and button/input variants.`,f.hex("#106D7C")("Custom Theme"));;){await i.confirm({message:"Done filling theme.json? Click continue to proceed."})!==!0&&(i.cancel("Operation cancelled."),process.exit(0));try{return k(await b.readJSON(r))}catch(n){i.log.error(f.red(`Error: ${n.message||"Invalid JSON"}`))}}}import l from"fs-extra";import T from"path";async function H(e,r){let o=T.join(e,"package.json");if(!l.existsSync(o))return;let t=await l.readJSON(o);t.name=r.toLowerCase().replace(/\s+/g,"-"),await l.writeJSON(o,t,{spaces:2})}async function L(e,r){let o=T.join(e,"src/app/layout.tsx");if(!l.existsSync(o))return;let n=(await l.readFile(o,"utf-8")).replace(/const siteName = ".*";/,`const siteName = "${r}";`);await l.writeFile(o,n)}async function _(e,r){let o=T.join(e,"src/app/globals.css");if(!l.existsSync(o))return;let t=await l.readFile(o,"utf-8"),n=P(t,O(r));await l.writeFile(o,n)}import D from"fs-extra";import w from"path";import{fileURLToPath as oe}from"url";import{downloadTemplate as te}from"giget";var ne=oe(import.meta.url),ie=w.dirname(ne),ae={next:"next-template",mobile:"mobile-template"},se={next:"github:BuildSanely/saneprint-templates/next-template",mobile:"github:BuildSanely/saneprint-templates/mobile-template"};function ce(e){return w.resolve(ie,"../../../templates",ae[e])}function le(e){let r=e==="next"?"PIX_TEMPLATE_SOURCE_NEXT":"PIX_TEMPLATE_SOURCE_MOBILE";return process.env[r]?.trim()||se[e]}async function I(e,r){if(process.env.PIX_DEV==="true"){let t=ce(e);if(!D.existsSync(t))throw new Error(`Template not found at ${t}`);await D.copy(t,r,{filter:n=>{let s=w.basename(n);return!["node_modules",".next","dist",".turbo"].includes(s)}});return}let o=le(e);await te(o,{dir:r,force:!0})}async function A(e){console.log(`
|
|
8
|
+
${p.bold(p.hex("#106D7C")("sane")+p.hex("#8D0D46")("print"))}`),console.log(p.hex("#F1F1F1").dim("Opinionated scaffolding for Next.js")),console.log(p.hex("#F1F1F1").dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(),c.intro(`${p.bgHex("#8D0D46").white(" saneprint ")} Modern Project Scaffolder`);let r=await R(e),o=y();r.designSystem==="custom"&&(o=await N(e));let t=c.spinner();t.start(`Setting up your ${r.type} project...`);let n=pe.resolve(process.cwd(),r.path);try{await I(r.type,n),await H(n,r.websiteName),await L(n,r.websiteName),await _(n,o),t.stop("Scaffolding complete!"),c.note(`Next steps:
|
|
9
|
+
cd ${r.path}
|
|
10
|
+
pnpm install
|
|
11
|
+
pnpm dev`,p.hex("#106D7C")("Success!")),c.outro(p.hex("#8D0D46")("Happy coding!"))}catch(s){t.stop("Scaffolding failed."),c.log.error(p.red(s.message||String(s))),process.exit(1)}}var F=new he;F.name("saneprint").description("Opinionated scaffolding for Next.js").version("1.0.0").option("-p, --path <path>","Path to create the project").option("-t, --type <type>","Project type (next, mobile)").option("-n, --name <name>","Website name").option("-ds, --design-system <system>","Design system (default, custom)").option("-pr, --primary <color>","Primary color").option("-sc, --secondary <color>","Secondary color").action(e=>{A(e)});F.parse();
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/prompts/init.ts","../src/constants/default-theme.ts","../src/utils/theme.ts","../src/utils/injection.ts","../src/utils/template-source.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { CLIOptions } from \"./types/index.js\";\n\nconst program = new Command();\n\nprogram\n\t.name(\"saneprint\")\n\t.description(\"Opinionated scaffolding for Next.js\")\n\t.version(\"1.0.0\")\n\t.option(\"-p, --path <path>\", \"Path to create the project\")\n\t.option(\"-t, --type <type>\", \"Project type (next, mobile)\")\n\t.option(\"-n, --name <name>\", \"Website name\")\n\t.option(\"-ds, --design-system <system>\", \"Design system (default, custom)\")\n\t.option(\"-pr, --primary <color>\", \"Primary color\")\n\t.option(\"-sc, --secondary <color>\", \"Secondary color\")\n\t.action((options: CLIOptions) => {\n\t\tinitCommand(options);\n\t});\n\nprogram.parse();\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport { CLIOptions, EnterpriseTheme } from \"../types/index.js\";\nimport { promptProjectConfig, promptEnterpriseTheme } from \"../prompts/init.js\";\nimport {\n\tinjectPackageMetadata,\n\tinjectLayoutMetadata,\n\tinjectEnterpriseTheme,\n} from \"../utils/injection.js\";\nimport { scaffoldProjectTemplate } from \"../utils/template-source.js\";\nimport { getDefaultTheme } from \"../utils/theme.js\";\n\nexport async function initCommand(options: CLIOptions) {\n\tconsole.log(\n\t\t`\\n${chalk.bold(chalk.hex(\"#106D7C\")(\"sane\") + chalk.hex(\"#8D0D46\")(\"print\"))}`,\n\t);\n\tconsole.log(chalk.hex(\"#F1F1F1\").dim(\"Opinionated scaffolding for Next.js\"));\n\tconsole.log(\n\t\tchalk\n\t\t\t.hex(\"#F1F1F1\")\n\t\t\t.dim(\"──────────────────────────────────────────────────\"),\n\t);\n\tconsole.log();\n\n\tp.intro(\n\t\t`${chalk.bgHex(\"#8D0D46\").white(\" saneprint \")} Modern Project Scaffolder`,\n\t);\n\tconst project = await promptProjectConfig(options);\n\n\t// 2. Handle Enterprise Level 2 Design System\n\tlet enterpriseTheme: EnterpriseTheme = getDefaultTheme();\n\tif (project.designSystem === \"custom\") {\n\t\tenterpriseTheme = await promptEnterpriseTheme(options);\n\t}\n\n\t// 3. Scaffolding\n\tconst s = p.spinner();\n\ts.start(`Setting up your ${project.type} project...`);\n\n\tconst targetPath = path.resolve(process.cwd(), project.path);\n\n\ttry {\n\t\tawait scaffoldProjectTemplate(project.type, targetPath);\n\n\t\t// 4. Injection\n\t\tawait injectPackageMetadata(targetPath, project.websiteName);\n\t\tawait injectLayoutMetadata(targetPath, project.websiteName);\n\n\t\tawait injectEnterpriseTheme(targetPath, enterpriseTheme);\n\n\t\ts.stop(\"Scaffolding complete!\");\n\n\t\tp.note(\n\t\t\t`Next steps:\\n cd ${project.path}\\n pnpm install\\n pnpm dev`,\n\t\t\tchalk.hex(\"#106D7C\")(\"Success!\"),\n\t\t);\n\t\tp.outro(chalk.hex(\"#8D0D46\")(\"Happy coding!\"));\n\t} catch (err: any) {\n\t\ts.stop(\"Scaffolding failed.\");\n\t\tp.log.error(chalk.red(err.message || String(err)));\n\t\tprocess.exit(1);\n\t}\n}\n","import * as p from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { ProjectConfig, EnterpriseTheme, CLIOptions } from \"../types/index.js\";\nimport { getDefaultTheme, validateTheme } from \"../utils/theme.js\";\n\n/**\n * Main project configuration prompts\n */\nexport async function promptProjectConfig(\n\toptions: CLIOptions,\n): Promise<ProjectConfig> {\n\tif (options.path && options.type && options.name && options.designSystem) {\n\t\treturn {\n\t\t\tpath: options.path,\n\t\t\ttype: options.type as any,\n\t\t\twebsiteName: options.name,\n\t\t\tdesignSystem: options.designSystem as any,\n\t\t};\n\t}\n\n\tconst group = (await p.group<Omit<ProjectConfig, \"type\">>(\n\t\t{\n\t\t\tpath: () =>\n\t\t\t\tp.text({\n\t\t\t\t\tmessage: \"Where should we create your project?\",\n\t\t\t\t\tplaceholder: \"./my-app\",\n\t\t\t\t\tinitialValue: options.path,\n\t\t\t\t}) as any,\n\t\t\twebsiteName: () =>\n\t\t\t\tp.text({\n\t\t\t\t\tmessage: \"What is your website name?\",\n\t\t\t\t\tplaceholder: \"Studio\",\n\t\t\t\t\tinitialValue: options.name,\n\t\t\t\t}) as any,\n\t\t\t/*\n\t\t\ttype: () =>\n\t\t\t\tp.select({\n\t\t\t\t\tmessage: \"What are you building today?\",\n\t\t\t\t\tinitialValue: options.type,\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"next\",\n\t\t\t\t\t\t\tlabel: \"Next.js (Web)\",\n\t\t\t\t\t\t\thint: \"Production-grade App Router\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"mobile\",\n\t\t\t\t\t\t\tlabel: \"React Native (Mobile)\",\n\t\t\t\t\t\t\thint: \"Expo Managed Workflow\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}) as any,\n\t\t\t*/\n\t\t\tdesignSystem: () =>\n\t\t\t\tp.select({\n\t\t\t\t\tmessage: \"Choose your Design System\",\n\t\t\t\t\tinitialValue: options.designSystem,\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"default\",\n\t\t\t\t\t\t\tlabel: \"saneprint Default\",\n\t\t\t\t\t\t\thint: \"Ready-to-go premium tokens\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvalue: \"custom\",\n\t\t\t\t\t\t\tlabel: \"Custom (Enterprise Level 2)\",\n\t\t\t\t\t\t\thint: \"Generate canonical theme.json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t}) as any,\n\t\t},\n\t\t{\n\t\t\tonCancel: () => {\n\t\t\t\tp.cancel(\"Operation cancelled.\");\n\t\t\t\tprocess.exit(0);\n\t\t\t},\n\t\t},\n\t)) as any;\n\n\treturn { ...group, type: \"next\" };\n}\n\n/**\n * Creates the canonical theme.json and waits for the user to edit it.\n */\nexport async function promptEnterpriseTheme(\n\toptions: CLIOptions,\n): Promise<EnterpriseTheme> {\n\tconst themePath = path.resolve(process.cwd(), \"theme.json\");\n\tconst defaultTheme = getDefaultTheme();\n\n\tif (fs.existsSync(themePath)) {\n\t\ttry {\n\t\t\treturn validateTheme(await fs.readJSON(themePath));\n\t\t} catch {\n\t\t\t// Fall through to overwrite with the canonical schema.\n\t\t}\n\t}\n\n\tif (options.primary) {\n\t\tdefaultTheme.colors.primary[\"500\"] = options.primary;\n\t\tdefaultTheme.colors.primary[\"600\"] = options.primary;\n\t\tdefaultTheme.themes.light.primary = options.primary;\n\t\tdefaultTheme.themes.light.primaryHover = options.primary;\n\t}\n\n\tif (options.secondary) {\n\t\tdefaultTheme.colors.secondary[\"500\"] = options.secondary;\n\t\tdefaultTheme.colors.secondary[\"600\"] = options.secondary;\n\t\tdefaultTheme.themes.light.secondary = options.secondary;\n\t\tdefaultTheme.themes.light.secondaryHover = options.secondary;\n\t}\n\n\tawait fs.writeJSON(themePath, defaultTheme, { spaces: 2 });\n\n\tp.note(\n\t\t`I've created a canonical ${chalk.hex(\"#106D7C\")(\"theme.json\")} in your current directory.\\n\\n` +\n\t\t\t`Edit values only. Do not add, delete, or rename keys.\\n` +\n\t\t\t`The default schema now includes ${chalk.hex(\"#106D7C\")(\"tertiary\")} color tokens and semantic roles out of the box.\\n` +\n\t\t\t`This schema drives the generated Tailwind tokens, color roles, and button/input variants.`,\n\t\tchalk.hex(\"#106D7C\")(\"Custom Theme\"),\n\t);\n\n\twhile (true) {\n\t\tconst ready = await p.confirm({\n\t\t\tmessage: \"Done filling theme.json? Click continue to proceed.\",\n\t\t});\n\t\tif (ready !== true) {\n\t\t\tp.cancel(\"Operation cancelled.\");\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\ttry {\n\t\t\treturn validateTheme(await fs.readJSON(themePath));\n\t\t} catch (err: any) {\n\t\t\tp.log.error(chalk.red(`Error: ${err.message || \"Invalid JSON\"}`));\n\t\t}\n\t}\n}\n","import { EnterpriseTheme } from \"../types/index.js\";\n\nexport const DEFAULT_THEME: EnterpriseTheme = {\n\tversion: \"1.0.0\",\n\tcolors: {\n\t\tprimary: {\n\t\t\t\"50\": \"oklch(0.985 0.015 180)\", // #f0fdfa\n\t\t\t\"100\": \"oklch(0.97 0.04 180)\", // #ccfbf1\n\t\t\t\"200\": \"oklch(0.94 0.07 180)\", // #99f6e4\n\t\t\t\"300\": \"oklch(0.89 0.1 180)\", // #5eead4\n\t\t\t\"400\": \"oklch(0.79 0.13 180)\", // #2dd4bf\n\t\t\t\"500\": \"oklch(0.7 0.14 180)\", // #14b8a6 - Teal primary\n\t\t\t\"600\": \"oklch(0.59 0.13 185)\", // #0d9488\n\t\t\t\"700\": \"oklch(0.5 0.11 190)\", // #0f766e\n\t\t\t\"800\": \"oklch(0.41 0.09 190)\", // #115e59\n\t\t\t\"900\": \"oklch(0.35 0.07 195)\", // #134e4a\n\t\t},\n\t\tsecondary: {\n\t\t\t\"50\": \"oklch(0.98 0.01 200)\",\n\t\t\t\"100\": \"oklch(0.95 0.02 200)\",\n\t\t\t\"200\": \"oklch(0.88 0.04 200)\",\n\t\t\t\"300\": \"oklch(0.8 0.06 200)\",\n\t\t\t\"400\": \"oklch(0.7 0.08 200)\",\n\t\t\t\"500\": \"oklch(0.6 0.09 200)\",\n\t\t\t\"600\": \"oklch(0.5 0.08 200)\",\n\t\t\t\"700\": \"oklch(0.4 0.07 200)\",\n\t\t\t\"800\": \"oklch(0.3 0.06 200)\",\n\t\t\t\"900\": \"oklch(0.2 0.05 200)\",\n\t\t},\n\t\ttertiary: {\n\t\t\t\"50\": \"oklch(0.97 0.02 310)\",\n\t\t\t\"100\": \"oklch(0.93 0.04 310)\",\n\t\t\t\"200\": \"oklch(0.87 0.08 310)\",\n\t\t\t\"300\": \"oklch(0.79 0.13 310)\",\n\t\t\t\"400\": \"oklch(0.7 0.18 310)\",\n\t\t\t\"500\": \"oklch(0.62 0.22 310)\",\n\t\t\t\"600\": \"oklch(0.54 0.2 310)\",\n\t\t\t\"700\": \"oklch(0.46 0.17 310)\",\n\t\t\t\"800\": \"oklch(0.38 0.14 310)\",\n\t\t\t\"900\": \"oklch(0.3 0.1 310)\",\n\t\t},\n\t\tneutral: {\n\t\t\t\"0\": \"#ffffff\",\n\t\t\t\"50\": \"oklch(0.99 0 0)\", // #fafafa\n\t\t\t\"100\": \"oklch(0.97 0 0)\", // #f5f5f5\n\t\t\t\"200\": \"oklch(0.92 0 0)\", // #e5e5e5\n\t\t\t\"300\": \"oklch(0.86 0 0)\", // #d4d4d4\n\t\t\t\"400\": \"oklch(0.68 0 0)\", // #a3a3a3\n\t\t\t\"500\": \"oklch(0.52 0 0)\", // #737373\n\t\t\t\"600\": \"oklch(0.38 0 0)\", // #525252\n\t\t\t\"700\": \"oklch(0.3 0 0)\", // #404040\n\t\t\t\"800\": \"oklch(0.19 0 0)\", // #262626\n\t\t\t\"900\": \"oklch(0.13 0 0)\", // #171717\n\t\t\t\"1000\": \"#000000\",\n\t\t},\n\t\tdanger: {\n\t\t\t\"500\": \"oklch(0.628 0.218 29)\", // #ef4444\n\t\t\t\"600\": \"oklch(0.55 0.2 29)\",\n\t\t},\n\t\tsuccess: {\n\t\t\t\"500\": \"oklch(0.698 0.176 142)\", // #22c55e\n\t\t\t\"600\": \"oklch(0.6 0.16 142)\",\n\t\t},\n\t\twarning: {\n\t\t\t\"500\": \"oklch(0.705 0.15 65)\", // #f59e0b\n\t\t\t\"600\": \"oklch(0.62 0.14 65)\",\n\t\t},\n\t\tinfo: {\n\t\t\t\"500\": \"oklch(0.596 0.182 255)\", // #3b82f6\n\t\t\t\"600\": \"oklch(0.52 0.17 255)\",\n\t\t},\n\t},\n\ttypography: {\n\t\tfontFamily: {\n\t\t\tsans: \"var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif\",\n\t\t\tmono: \"var(--font-geist-mono), ui-monospace, monospace\",\n\t\t},\n\t\tstyles: {\n\t\t\theading1: {\n\t\t\t\tsize: \"48px\",\n\t\t\t\tweight: \"700\",\n\t\t\t\tlineHeight: \"1.1\",\n\t\t\t\tletterSpacing: \"-0.02em\",\n\t\t\t},\n\t\t\theading2: {\n\t\t\t\tsize: \"36px\",\n\t\t\t\tweight: \"700\",\n\t\t\t\tlineHeight: \"1.2\",\n\t\t\t\tletterSpacing: \"-0.01em\",\n\t\t\t},\n\t\t\theading3: {\n\t\t\t\tsize: \"30px\",\n\t\t\t\tweight: \"700\",\n\t\t\t\tlineHeight: \"1.25\",\n\t\t\t\tletterSpacing: \"-0.01em\",\n\t\t\t},\n\t\t\theading4: {\n\t\t\t\tsize: \"24px\",\n\t\t\t\tweight: \"600\",\n\t\t\t\tlineHeight: \"1.3\",\n\t\t\t\tletterSpacing: \"-0.005em\",\n\t\t\t},\n\t\t\theading5: {\n\t\t\t\tsize: \"20px\",\n\t\t\t\tweight: \"600\",\n\t\t\t\tlineHeight: \"1.35\",\n\t\t\t\tletterSpacing: \"0\",\n\t\t\t},\n\t\t\theading6: {\n\t\t\t\tsize: \"18px\",\n\t\t\t\tweight: \"600\",\n\t\t\t\tlineHeight: \"1.4\",\n\t\t\t\tletterSpacing: \"0\",\n\t\t\t},\n\t\t\tbody: {\n\t\t\t\tsize: \"16px\",\n\t\t\t\tweight: \"400\",\n\t\t\t\tlineHeight: \"1.5\",\n\t\t\t\tletterSpacing: \"0\",\n\t\t\t},\n\t\t\tbodySm: {\n\t\t\t\tsize: \"14px\",\n\t\t\t\tweight: \"400\",\n\t\t\t\tlineHeight: \"1.5\",\n\t\t\t\tletterSpacing: \"0\",\n\t\t\t},\n\t\t\tlabel: {\n\t\t\t\tsize: \"14px\",\n\t\t\t\tweight: \"600\",\n\t\t\t\tlineHeight: \"1.4\",\n\t\t\t\tletterSpacing: \"0.01em\",\n\t\t\t},\n\t\t\tlabelSm: {\n\t\t\t\tsize: \"12px\",\n\t\t\t\tweight: \"600\",\n\t\t\t\tlineHeight: \"1.35\",\n\t\t\t\tletterSpacing: \"0.01em\",\n\t\t\t},\n\t\t\tcaption: {\n\t\t\t\tsize: \"12px\",\n\t\t\t\tweight: \"400\",\n\t\t\t\tlineHeight: \"1.4\",\n\t\t\t\tletterSpacing: \"0\",\n\t\t\t},\n\t\t},\n\t},\n\tthemes: {\n\t\tlight: {\n\t\t\tbackground: \"{colors.neutral.50}\",\n\t\t\tsurface: \"{colors.neutral.0}\",\n\t\t\ttext: \"{colors.neutral.900}\",\n\t\t\ttextMuted: \"{colors.neutral.600}\",\n\t\t\tborder: \"{colors.neutral.200}\",\n\t\t\tprimary: \"{colors.primary.500}\",\n\t\t\tprimaryHover: \"{colors.primary.600}\",\n\t\t\tsecondary: \"{colors.secondary.500}\",\n\t\t\tsecondaryHover: \"{colors.secondary.600}\",\n\t\t\ttertiary: \"{colors.tertiary.500}\",\n\t\t\ttertiaryHover: \"{colors.tertiary.600}\",\n\t\t\tdanger: \"{colors.danger.500}\",\n\t\t\tdangerHover: \"{colors.danger.600}\",\n\t\t\tonPrimary: \"{colors.neutral.0}\",\n\t\t\tonSecondary: \"{colors.neutral.0}\",\n\t\t\tonTertiary: \"{colors.neutral.0}\",\n\t\t\tonDanger: \"{colors.neutral.0}\",\n\t\t\tinputBackground: \"{colors.neutral.0}\",\n\t\t\tinputBorder: \"{colors.neutral.300}\",\n\t\t\tinputFocusRing: \"{colors.primary.500}\",\n\t\t},\n\t},\n};\n","import { DEFAULT_THEME } from \"../constants/default-theme.js\";\nimport {\n\tEnterpriseTheme,\n\tThemeRoles,\n\tTypographyStyle,\n} from \"../types/index.js\";\n\nconst THEME_START = \"/* theme start */\";\nconst THEME_END = \"/* theme end */\";\n\nconst THEME_ROLE_VARIABLES = {\n\tbackground: \"background\",\n\tsurface: \"surface\",\n\ttext: \"foreground\",\n\ttextMuted: \"muted\",\n\tborder: \"border\",\n\tprimary: \"brand\",\n\tprimaryHover: \"brand-hover\",\n\tsecondary: \"accent\",\n\tsecondaryHover: \"accent-hover\",\n\ttertiary: \"tertiary\",\n\ttertiaryHover: \"tertiary-hover\",\n\tdanger: \"danger\",\n\tdangerHover: \"danger-hover\",\n\tonPrimary: \"on-brand\",\n\tonSecondary: \"on-accent\",\n\tonTertiary: \"on-tertiary\",\n\tonDanger: \"on-danger\",\n\tinputBackground: \"input\",\n\tinputBorder: \"input-border\",\n\tinputFocusRing: \"focus-ring\",\n} satisfies Record<keyof ThemeRoles, string>;\n\nconst BUTTON_INTENTS = [\n\t{\n\t\tname: \"primary\",\n\t\tbaseColor: \"var(--color-brand)\",\n\t\thoverColor: \"var(--color-brand-hover)\",\n\t\tforegroundColor: \"var(--color-on-brand)\",\n\t},\n\t{\n\t\tname: \"secondary\",\n\t\tbaseColor: \"var(--color-accent)\",\n\t\thoverColor: \"var(--color-accent-hover)\",\n\t\tforegroundColor: \"var(--color-on-accent)\",\n\t},\n\t{\n\t\tname: \"tertiary\",\n\t\tbaseColor: \"var(--color-tertiary)\",\n\t\thoverColor: \"var(--color-tertiary-hover)\",\n\t\tforegroundColor: \"var(--color-on-tertiary)\",\n\t},\n\t{\n\t\tname: \"danger\",\n\t\tbaseColor: \"var(--color-danger)\",\n\t\thoverColor: \"var(--color-danger-hover)\",\n\t\tforegroundColor: \"var(--color-on-danger)\",\n\t},\n] as const;\n\nconst TYPOGRAPHY_CLASS_NAMES = {\n\theading1: \"heading-1\",\n\theading2: \"heading-2\",\n\theading3: \"heading-3\",\n\theading4: \"heading-4\",\n\theading5: \"heading-5\",\n\theading6: \"heading-6\",\n\tbody: \"body\",\n\tbodySm: \"body-sm\",\n\tlabel: \"label\",\n\tlabelSm: \"label-sm\",\n\tcaption: \"caption\",\n} as const;\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction cloneValue<T>(value: T): T {\n\treturn JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction formatNumber(value: number): string {\n\treturn Number.parseFloat(value.toFixed(4)).toString();\n}\n\nfunction pxToRem(value: string): string {\n\treturn value.replace(/(-?\\d*\\.?\\d+)px\\b/g, (_, rawNumber) => {\n\t\tconst remValue = Number.parseFloat(rawNumber) / 16;\n\t\treturn `${formatNumber(remValue)}rem`;\n\t});\n}\n\nfunction normalizeValue(value: string): string {\n\treturn pxToRem(value);\n}\n\nfunction assertObjectShape(\n\tvalue: unknown,\n\tschema: unknown,\n\tcurrentPath: string,\n): void {\n\tif (schema === null || typeof schema !== \"object\" || Array.isArray(schema)) {\n\t\tif (typeof value !== typeof schema) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid value at ${currentPath}. Expected ${typeof schema}.`,\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Invalid value at ${currentPath}. Expected an object.`);\n\t}\n\n\tconst schemaObject = schema as Record<string, unknown>;\n\tconst valueObject = value as Record<string, unknown>;\n\tconst schemaKeys = Object.keys(schemaObject).sort();\n\tconst valueKeys = Object.keys(valueObject).sort();\n\n\tif (\n\t\tschemaKeys.length !== valueKeys.length ||\n\t\tschemaKeys.some((key, index) => key !== valueKeys[index])\n\t) {\n\t\tthrow new Error(\n\t\t\t`Theme schema mismatch at ${currentPath}. Edit values only; do not add or remove keys.`,\n\t\t);\n\t}\n\n\tfor (const key of schemaKeys) {\n\t\tconst nextPath =\n\t\t\tcurrentPath === \"theme\" ? `theme.${key}` : `${currentPath}.${key}`;\n\t\tassertObjectShape(valueObject[key], schemaObject[key], nextPath);\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction assertStringRecord(value: unknown, currentPath: string): void {\n\tif (!isRecord(value)) {\n\t\tthrow new Error(`Invalid value at ${currentPath}. Expected an object.`);\n\t}\n\n\tfor (const [key, entry] of Object.entries(value)) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid value at ${currentPath}.${key}. Expected a string.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction assertThemeColorScales(colors: unknown): void {\n\tif (!isRecord(colors)) {\n\t\tthrow new Error(\"Invalid value at theme.colors. Expected an object.\");\n\t}\n\tassertObjectShape(colors, DEFAULT_THEME.colors, \"theme.colors\");\n}\n\nfunction themeLine(name: string, value: string): string {\n\treturn ` ${name}: ${value};`;\n}\n\nfunction cssRuleLines(selector: string, declarations: string[]): string[] {\n\treturn [\n\t\tselector,\n\t\t...declarations.map((declaration) => ` ${declaration}`),\n\t\t\"}\",\n\t];\n}\n\nfunction componentRuleLines(\n\tselector: string,\n\tdeclarations: string[],\n): string[] {\n\treturn [\n\t\t` ${selector}`,\n\t\t...declarations.map((declaration) => ` ${declaration}`),\n\t\t\" }\",\n\t];\n}\n\nfunction resolvePath(pathString: string, theme: EnterpriseTheme): string {\n\tconst keys = pathString.split(\".\");\n\tlet current: unknown = theme;\n\n\tfor (const key of keys) {\n\t\tif (\n\t\t\tcurrent === null ||\n\t\t\ttypeof current !== \"object\" ||\n\t\t\t!(key in (current as Record<string, unknown>))\n\t\t) {\n\t\t\tthrow new Error(`Could not resolve token reference {${pathString}}.`);\n\t\t}\n\n\t\tcurrent = (current as Record<string, unknown>)[key];\n\t}\n\n\tif (typeof current !== \"string\") {\n\t\tthrow new Error(\n\t\t\t`Token reference {${pathString}} did not resolve to a string value.`,\n\t\t);\n\t}\n\n\treturn current;\n}\n\nexport function resolveToken(value: string, theme: EnterpriseTheme): string {\n\treturn value.replace(/\\{([^}]+)\\}/g, (_, pathString) => {\n\t\treturn resolveToken(resolvePath(pathString, theme), theme);\n\t});\n}\n\nfunction resolveAndNormalize(value: string, theme: EnterpriseTheme): string {\n\treturn normalizeValue(resolveToken(value, theme));\n}\n\nfunction getRoleCssVariable(pathString: string): string | null {\n\tconst parts = pathString.split(\".\");\n\tif (parts[0] !== \"themes\" || parts.length !== 3) {\n\t\treturn null;\n\t}\n\n\tconst roleName = parts[2] as keyof ThemeRoles;\n\tconst cssName = THEME_ROLE_VARIABLES[roleName];\n\treturn cssName ? `var(--color-${cssName})` : null;\n}\n\nfunction getPaletteCssVariable(pathString: string): string | null {\n\tconst parts = pathString.split(\".\");\n\tif (parts[0] !== \"colors\" || parts.length !== 3) {\n\t\treturn null;\n\t}\n\n\treturn `var(--color-${parts[1]}-${parts[2]})`;\n}\n\nfunction resolveCssValue(value: string, theme: EnterpriseTheme): string {\n\treturn normalizeValue(\n\t\tvalue.replace(/\\{([^}]+)\\}/g, (_, pathString) => {\n\t\t\treturn (\n\t\t\t\tgetRoleCssVariable(pathString) ??\n\t\t\t\tgetPaletteCssVariable(pathString) ??\n\t\t\t\tresolveToken(`{${pathString}}`, theme)\n\t\t\t);\n\t\t}),\n\t);\n}\n\nfunction pushPaletteVariables(lines: string[], theme: EnterpriseTheme): void {\n\tfor (const [familyName, scale] of Object.entries(theme.colors)) {\n\t\tfor (const [tokenName, tokenValue] of Object.entries(\n\t\t\tscale as Record<string, string>,\n\t\t)) {\n\t\t\tlines.push(\n\t\t\t\tthemeLine(\n\t\t\t\t\t`--color-${familyName}-${tokenName}`,\n\t\t\t\t\tresolveAndNormalize(tokenValue, theme),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction pushRoleVariables(\n\tlines: string[],\n\troles: ThemeRoles,\n\ttheme: EnterpriseTheme,\n): void {\n\tfor (const [roleName, cssName] of Object.entries(THEME_ROLE_VARIABLES)) {\n\t\tlines.push(\n\t\t\tthemeLine(\n\t\t\t\t`--color-${cssName}`,\n\t\t\t\tresolveAndNormalize(roles[roleName as keyof ThemeRoles], theme),\n\t\t\t),\n\t\t);\n\t}\n}\n\nfunction pushTypographyVariables(\n\tlines: string[],\n\ttheme: EnterpriseTheme,\n): void {\n\tlines.push(\n\t\tthemeLine(\n\t\t\t\"--font-sans\",\n\t\t\tresolveAndNormalize(theme.typography.fontFamily.sans, theme),\n\t\t),\n\t);\n\tlines.push(\n\t\tthemeLine(\n\t\t\t\"--font-mono\",\n\t\t\tresolveAndNormalize(theme.typography.fontFamily.mono, theme),\n\t\t),\n\t);\n\n\tfor (const [tokenName, style] of Object.entries(theme.typography.styles)) {\n\t\tconst typedStyle = style as TypographyStyle;\n\t\tlines.push(\n\t\t\tthemeLine(\n\t\t\t\t`--text-${tokenName}`,\n\t\t\t\tresolveAndNormalize(typedStyle.size, theme),\n\t\t\t),\n\t\t);\n\t\tlines.push(\n\t\t\tthemeLine(\n\t\t\t\t`--text-${tokenName}--line-height`,\n\t\t\t\tresolveAndNormalize(typedStyle.lineHeight, theme),\n\t\t\t),\n\t\t);\n\t\tlines.push(\n\t\t\tthemeLine(\n\t\t\t\t`--tracking-${tokenName}`,\n\t\t\t\tresolveAndNormalize(typedStyle.letterSpacing, theme),\n\t\t\t),\n\t\t);\n\t\tlines.push(\n\t\t\tthemeLine(\n\t\t\t\t`--font-weight-${tokenName}`,\n\t\t\t\tresolveAndNormalize(typedStyle.weight, theme),\n\t\t\t),\n\t\t);\n\t}\n}\n\nfunction buildThemeInlineLines(theme: EnterpriseTheme): string[] {\n\tconst lines = [\"@theme inline {\"];\n\tpushPaletteVariables(lines, theme);\n\tpushRoleVariables(lines, theme.themes.light, theme);\n\tpushTypographyVariables(lines, theme);\n\tlines.push(\"}\");\n\treturn lines;\n}\n\nfunction buildTypographyUtilities(theme: EnterpriseTheme): string[] {\n\tconst lines: string[] = [];\n\n\tfor (const tokenName of Object.keys(theme.typography.styles) as Array<\n\t\tkeyof typeof TYPOGRAPHY_CLASS_NAMES\n\t>) {\n\t\tconst className = TYPOGRAPHY_CLASS_NAMES[tokenName];\n\t\tlines.push(\n\t\t\t`@utility ${className} {`,\n\t\t\t` font-size: var(--text-${tokenName});`,\n\t\t\t` font-weight: var(--font-weight-${tokenName});`,\n\t\t\t` line-height: var(--text-${tokenName}--line-height);`,\n\t\t\t` letter-spacing: var(--tracking-${tokenName});`,\n\t\t\t\"}\",\n\t\t);\n\t}\n\n\treturn lines;\n}\n\nfunction buildButtonVariantLines(): string[] {\n\tconst lines: string[] = [\"@layer components {\"];\n\n\tlines.push(\n\t\t...componentRuleLines(\".btn {\", [\n\t\t\t\"display: inline-flex;\",\n\t\t\t\"align-items: center;\",\n\t\t\t\"justify-content: center;\",\n\t\t\t\"gap: 0.5rem;\",\n\t\t\t\"border-radius: 0.75rem;\",\n\t\t\t\"border: 1px solid transparent;\",\n\t\t\t\"font-size: var(--text-label);\",\n\t\t\t\"font-weight: var(--font-weight-label);\",\n\t\t\t\"line-height: var(--text-label--line-height);\",\n\t\t\t\"letter-spacing: var(--tracking-label);\",\n\t\t\t\"transition-property: background-color, border-color, color, box-shadow, opacity;\",\n\t\t\t\"transition-duration: 150ms;\",\n\t\t\t\"transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\",\n\t\t\t\"cursor: pointer;\",\n\t\t]),\n\t);\n\tlines.push(\n\t\t...componentRuleLines(\".btn:focus-visible {\", [\n\t\t\t\"outline: none;\",\n\t\t\t\"box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus-ring) 35%, transparent);\",\n\t\t]),\n\t);\n\tlines.push(\n\t\t...componentRuleLines(\".btn:disabled {\", [\n\t\t\t\"cursor: not-allowed;\",\n\t\t\t\"opacity: 0.55;\",\n\t\t]),\n\t);\n\n\tfor (const intent of BUTTON_INTENTS) {\n\t\tlines.push(\n\t\t\t...componentRuleLines(`.btn-${intent.name}-filled {`, [\n\t\t\t\t`background-color: ${intent.baseColor};`,\n\t\t\t\t`border-color: ${intent.baseColor};`,\n\t\t\t\t`color: ${intent.foregroundColor};`,\n\t\t\t]),\n\t\t);\n\t\tlines.push(\n\t\t\t...componentRuleLines(`.btn-${intent.name}-filled:hover {`, [\n\t\t\t\t`background-color: ${intent.hoverColor};`,\n\t\t\t\t`border-color: ${intent.hoverColor};`,\n\t\t\t]),\n\t\t);\n\t\tlines.push(\n\t\t\t...componentRuleLines(`.btn-${intent.name}-outlined {`, [\n\t\t\t\t\"background-color: transparent;\",\n\t\t\t\t`border-color: ${intent.baseColor};`,\n\t\t\t\t`color: ${intent.baseColor};`,\n\t\t\t]),\n\t\t);\n\t\tlines.push(\n\t\t\t...componentRuleLines(`.btn-${intent.name}-outlined:hover {`, [\n\t\t\t\t`background-color: color-mix(in srgb, ${intent.baseColor} 10%, transparent);`,\n\t\t\t\t`border-color: ${intent.hoverColor};`,\n\t\t\t\t`color: ${intent.hoverColor};`,\n\t\t\t]),\n\t\t);\n\t\tlines.push(\n\t\t\t...componentRuleLines(`.btn-${intent.name}-ghost {`, [\n\t\t\t\t\"background-color: transparent;\",\n\t\t\t\t\"border-color: transparent;\",\n\t\t\t\t`color: ${intent.baseColor};`,\n\t\t\t]),\n\t\t);\n\t\tlines.push(\n\t\t\t...componentRuleLines(`.btn-${intent.name}-ghost:hover {`, [\n\t\t\t\t`background-color: color-mix(in srgb, ${intent.baseColor} 12%, transparent);`,\n\t\t\t\t`color: ${intent.hoverColor};`,\n\t\t\t]),\n\t\t);\n\t}\n\n\tlines.push(\n\t\t...componentRuleLines(\".input {\", [\n\t\t\t\"width: 100%;\",\n\t\t\t\"border-radius: 0.75rem;\",\n\t\t\t\"border: 1px solid var(--color-input-border);\",\n\t\t\t\"background-color: var(--color-input);\",\n\t\t\t\"font-size: var(--text-body);\",\n\t\t\t\"font-weight: var(--font-weight-body);\",\n\t\t\t\"line-height: var(--text-body--line-height);\",\n\t\t\t\"letter-spacing: var(--tracking-body);\",\n\t\t\t\"color: var(--color-foreground);\",\n\t\t\t\"transition-property: border-color, box-shadow, background-color;\",\n\t\t\t\"transition-duration: 150ms;\",\n\t\t\t\"transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\",\n\t\t\t\"outline: none;\",\n\t\t]),\n\t);\n\tlines.push(\n\t\t...componentRuleLines(\".input::placeholder {\", [\n\t\t\t\"color: var(--color-muted);\",\n\t\t]),\n\t);\n\tlines.push(\n\t\t...componentRuleLines(\".input:focus-visible {\", [\n\t\t\t\"border-color: var(--color-focus-ring);\",\n\t\t\t\"box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus-ring) 25%, transparent);\",\n\t\t]),\n\t);\n\n\tlines.push(\"}\");\n\treturn lines;\n}\n\nexport function getDefaultTheme(): EnterpriseTheme {\n\treturn cloneValue(DEFAULT_THEME);\n}\n\nexport function validateTheme(theme: unknown): EnterpriseTheme {\n\tif (!isRecord(theme)) {\n\t\tthrow new Error(\"Invalid value at theme. Expected an object.\");\n\t}\n\n\tconst version = theme.version;\n\tconst colors = theme.colors;\n\tconst typography = theme.typography;\n\tconst themes = theme.themes;\n\n\tif (typeof version !== \"string\") {\n\t\tthrow new Error(\"Invalid value at theme.version. Expected a string.\");\n\t}\n\n\tassertThemeColorScales(colors);\n\tassertObjectShape(\n\t\ttypography,\n\t\tDEFAULT_THEME.typography,\n\t\t\"theme.typography\",\n\t);\n\tassertObjectShape(themes, DEFAULT_THEME.themes, \"theme.themes\");\n\n\treturn {\n\t\tversion,\n\t\tcolors: colors as EnterpriseTheme[\"colors\"],\n\t\ttypography: typography as EnterpriseTheme[\"typography\"],\n\t\tthemes: {\n\t\t\tlight: (themes as EnterpriseTheme[\"themes\"]).light,\n\t\t},\n\t};\n}\n\nexport function generateThemeCss(theme: EnterpriseTheme): string {\n\treturn [\n\t\tTHEME_START,\n\t\t...buildThemeInlineLines(theme),\n\t\t\"\",\n\t\t...buildTypographyUtilities(theme),\n\t\t\"\",\n\t\t...buildButtonVariantLines(),\n\t\tTHEME_END,\n\t].join(\"\\n\");\n}\n\nexport function replaceThemeBlock(content: string, themeCss: string): string {\n\tconst pattern = new RegExp(\n\t\t`${escapeRegExp(THEME_START)}[\\\\s\\\\S]*?${escapeRegExp(THEME_END)}`,\n\t\t\"m\",\n\t);\n\n\tif (!pattern.test(content)) {\n\t\tthrow new Error(\"Could not find theme block in globals.css.\");\n\t}\n\n\treturn content.replace(pattern, themeCss.trim());\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { EnterpriseTheme } from \"../types/index.js\";\nimport { generateThemeCss, replaceThemeBlock } from \"./theme.js\";\n\nexport async function injectPackageMetadata(\n\ttargetPath: string,\n\twebsiteName: string,\n) {\n\tconst packagePath = path.join(targetPath, \"package.json\");\n\tif (!fs.existsSync(packagePath)) {\n\t\treturn;\n\t}\n\n\tconst packageJson = await fs.readJSON(packagePath);\n\tpackageJson.name = websiteName.toLowerCase().replace(/\\s+/g, \"-\");\n\tawait fs.writeJSON(packagePath, packageJson, { spaces: 2 });\n}\n\nexport async function injectLayoutMetadata(\n\ttargetPath: string,\n\twebsiteName: string,\n) {\n\tconst layoutPath = path.join(targetPath, \"src/app/layout.tsx\");\n\tif (!fs.existsSync(layoutPath)) {\n\t\treturn;\n\t}\n\n\tconst currentContent = await fs.readFile(layoutPath, \"utf-8\");\n\tconst nextContent = currentContent.replace(\n\t\t/const siteName = \".*\";/,\n\t\t`const siteName = \"${websiteName}\";`,\n\t);\n\tawait fs.writeFile(layoutPath, nextContent);\n}\n\nexport async function injectEnterpriseTheme(\n\ttargetPath: string,\n\ttheme: EnterpriseTheme,\n) {\n\tconst cssPath = path.join(targetPath, \"src/app/globals.css\");\n\tif (!fs.existsSync(cssPath)) {\n\t\treturn;\n\t}\n\n\tconst currentContent = await fs.readFile(cssPath, \"utf-8\");\n\tconst nextContent = replaceThemeBlock(currentContent, generateThemeCss(theme));\n\tawait fs.writeFile(cssPath, nextContent);\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { downloadTemplate } from \"giget\";\nimport { ProjectType } from \"../types/index.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst TEMPLATE_DIRECTORIES: Record<ProjectType, string> = {\n\tnext: \"next-template\",\n\tmobile: \"mobile-template\",\n};\n\nconst DEFAULT_REMOTE_TEMPLATE_SOURCES: Record<ProjectType, string> = {\n\tnext: \"github:BuildSanely/saneprint-templates/next-template\",\n\tmobile: \"github:BuildSanely/saneprint-templates/mobile-template\",\n};\n\nfunction getLocalTemplatePath(projectType: ProjectType) {\n\treturn path.resolve(\n\t\t__dirname,\n\t\t\"../../../templates\",\n\t\tTEMPLATE_DIRECTORIES[projectType],\n\t);\n}\n\nfunction getRemoteTemplateSource(projectType: ProjectType) {\n\tconst envKey =\n\t\tprojectType === \"next\"\n\t\t\t? \"PIX_TEMPLATE_SOURCE_NEXT\"\n\t\t\t: \"PIX_TEMPLATE_SOURCE_MOBILE\";\n\n\treturn (\n\t\tprocess.env[envKey]?.trim() || DEFAULT_REMOTE_TEMPLATE_SOURCES[projectType]\n\t);\n}\n\nexport async function scaffoldProjectTemplate(\n\tprojectType: ProjectType,\n\ttargetPath: string,\n) {\n\tif (process.env.PIX_DEV === \"true\") {\n\t\tconst sourcePath = getLocalTemplatePath(projectType);\n\n\t\tif (!fs.existsSync(sourcePath)) {\n\t\t\tthrow new Error(`Template not found at ${sourcePath}`);\n\t\t}\n\n\t\tawait fs.copy(sourcePath, targetPath, {\n\t\t\tfilter: (src) => {\n\t\t\t\tconst basename = path.basename(src);\n\t\t\t\treturn ![\"node_modules\", \".next\", \"dist\", \".turbo\"].includes(basename);\n\t\t\t},\n\t\t});\n\t\treturn;\n\t}\n\n\tconst source = getRemoteTemplateSource(projectType);\n\tawait downloadTemplate(source, { dir: targetPath, force: true });\n}\n"],"mappings":"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","names":["Command","p","chalk","path","p","chalk","fs","path","DEFAULT_THEME","THEME_START","THEME_END","THEME_ROLE_VARIABLES","BUTTON_INTENTS","TYPOGRAPHY_CLASS_NAMES","escapeRegExp","value","cloneValue","formatNumber","pxToRem","_","rawNumber","remValue","normalizeValue","assertObjectShape","schema","currentPath","schemaObject","valueObject","schemaKeys","valueKeys","key","index","nextPath","isRecord","assertThemeColorScales","colors","isRecord","assertObjectShape","DEFAULT_THEME","themeLine","name","value","componentRuleLines","selector","declarations","declaration","resolvePath","pathString","theme","keys","current","key","resolveToken","value","_","resolveAndNormalize","normalizeValue","pushPaletteVariables","lines","theme","familyName","scale","tokenName","tokenValue","themeLine","resolveAndNormalize","pushRoleVariables","roles","roleName","cssName","THEME_ROLE_VARIABLES","pushTypographyVariables","style","typedStyle","buildThemeInlineLines","buildTypographyUtilities","className","TYPOGRAPHY_CLASS_NAMES","buildButtonVariantLines","componentRuleLines","intent","BUTTON_INTENTS","getDefaultTheme","cloneValue","DEFAULT_THEME","validateTheme","isRecord","version","colors","typography","themes","assertThemeColorScales","assertObjectShape","generateThemeCss","THEME_START","THEME_END","replaceThemeBlock","content","themeCss","pattern","escapeRegExp","promptProjectConfig","options","promptEnterpriseTheme","themePath","path","defaultTheme","getDefaultTheme","fs","validateTheme","chalk","err","fs","path","injectPackageMetadata","targetPath","websiteName","packagePath","path","fs","packageJson","injectLayoutMetadata","layoutPath","nextContent","injectEnterpriseTheme","theme","cssPath","currentContent","replaceThemeBlock","generateThemeCss","fs","path","fileURLToPath","downloadTemplate","__filename","__dirname","TEMPLATE_DIRECTORIES","DEFAULT_REMOTE_TEMPLATE_SOURCES","getLocalTemplatePath","projectType","getRemoteTemplateSource","envKey","scaffoldProjectTemplate","targetPath","sourcePath","src","basename","source","initCommand","options","chalk","project","promptProjectConfig","enterpriseTheme","getDefaultTheme","promptEnterpriseTheme","s","targetPath","path","scaffoldProjectTemplate","injectPackageMetadata","injectLayoutMetadata","injectEnterpriseTheme","err","program","Command","options","initCommand"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "saneprint",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "The official saneprint CLI",
|
|
6
|
+
"author": "Karishma Garg",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"nextjs",
|
|
10
|
+
"react",
|
|
11
|
+
"scaffolding",
|
|
12
|
+
"cli",
|
|
13
|
+
"architecture",
|
|
14
|
+
"ai-governance"
|
|
15
|
+
],
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"CHANGELOG.md"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"saneprint": "dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"dev": "tsup --watch",
|
|
32
|
+
"start": "node dist/index.js",
|
|
33
|
+
"lint": "eslint src/**/*.ts"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"commander": "^12.0.0",
|
|
37
|
+
"@clack/prompts": "^0.7.0",
|
|
38
|
+
"fs-extra": "^11.0.0",
|
|
39
|
+
"chalk": "^5.0.0",
|
|
40
|
+
"giget": "^1.2.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20.0.0",
|
|
44
|
+
"@types/fs-extra": "^11.0.0",
|
|
45
|
+
"typescript": "^5.0.0",
|
|
46
|
+
"tsup": "^8.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|