create-eva-css 2.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/README.md +210 -0
- package/index.js +493 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# create-eva-css
|
|
2
|
+
|
|
3
|
+
Scaffolding tool for EVA CSS projects. Get started with a fully configured EVA CSS project in seconds.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Using npm
|
|
9
|
+
npm init eva-css my-project
|
|
10
|
+
|
|
11
|
+
# Using npx
|
|
12
|
+
npx create-eva-css my-project
|
|
13
|
+
|
|
14
|
+
# Using pnpm
|
|
15
|
+
pnpm create eva-css my-project
|
|
16
|
+
|
|
17
|
+
# Using yarn
|
|
18
|
+
yarn create eva-css my-project
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Interactive Setup
|
|
22
|
+
|
|
23
|
+
The CLI will guide you through:
|
|
24
|
+
|
|
25
|
+
1. **Template Selection** - Choose from 3 presets:
|
|
26
|
+
- **Minimal**: Variables only, no utility classes
|
|
27
|
+
- **Utility**: Full utility classes mode
|
|
28
|
+
- **Full**: Everything + examples + theme switching
|
|
29
|
+
|
|
30
|
+
2. **Design Sizes** - Enter your design system sizes (from Figma, etc.)
|
|
31
|
+
|
|
32
|
+
3. **Font Sizes** - Enter your font size scale
|
|
33
|
+
|
|
34
|
+
4. **Package Manager** - Choose npm, pnpm, or yarn
|
|
35
|
+
|
|
36
|
+
5. **Dependency Installation** - Automatically install dependencies
|
|
37
|
+
|
|
38
|
+
## CLI Options
|
|
39
|
+
|
|
40
|
+
For non-interactive usage:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx create-eva-css my-project \
|
|
44
|
+
--preset utility \
|
|
45
|
+
--sizes "16,24,32,64,128" \
|
|
46
|
+
--font-sizes "16,24,32,48" \
|
|
47
|
+
--package-manager pnpm
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Options
|
|
51
|
+
|
|
52
|
+
| Option | Description | Values |
|
|
53
|
+
|--------|-------------|--------|
|
|
54
|
+
| `--preset` | Project template | `minimal`, `utility`, `full` |
|
|
55
|
+
| `--sizes` | Comma-separated size values | e.g. `"16,24,32,64"` |
|
|
56
|
+
| `--font-sizes` | Comma-separated font sizes | e.g. `"16,24,32"` |
|
|
57
|
+
| `--package-manager` | Package manager to use | `npm`, `pnpm`, `yarn` |
|
|
58
|
+
| `--help` | Show help message | - |
|
|
59
|
+
|
|
60
|
+
## What Gets Generated
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
my-project/
|
|
64
|
+
├── eva.config.cjs # EVA CSS configuration
|
|
65
|
+
├── package.json # Project dependencies
|
|
66
|
+
├── .gitignore # Git ignore rules
|
|
67
|
+
├── README.md # Project documentation
|
|
68
|
+
├── index.html # Demo page
|
|
69
|
+
└── styles/
|
|
70
|
+
└── main.scss # Main stylesheet
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Generated Scripts
|
|
74
|
+
|
|
75
|
+
The scaffolded project includes these npm scripts:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"build": "sass styles/main.scss:styles/main.css",
|
|
80
|
+
"build:watch": "sass --watch styles/main.scss:styles/main.css",
|
|
81
|
+
"build:purge": "sass ... && eva-purge ...",
|
|
82
|
+
"dev": "npm run build:watch"
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Next Steps After Generation
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Navigate to project
|
|
90
|
+
cd my-project
|
|
91
|
+
|
|
92
|
+
# Start development (watch mode)
|
|
93
|
+
npm run dev
|
|
94
|
+
|
|
95
|
+
# Open index.html in your browser
|
|
96
|
+
|
|
97
|
+
# Build for production (with purge)
|
|
98
|
+
npm run build:purge
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Template Presets
|
|
102
|
+
|
|
103
|
+
### Minimal
|
|
104
|
+
|
|
105
|
+
Perfect for custom component libraries:
|
|
106
|
+
|
|
107
|
+
- Variables only mode (`@use 'eva-css-fluid/variables'`)
|
|
108
|
+
- No utility classes generated
|
|
109
|
+
- Minimal CSS output
|
|
110
|
+
- Full access to fluid size variables
|
|
111
|
+
|
|
112
|
+
### Utility
|
|
113
|
+
|
|
114
|
+
Best for rapid prototyping:
|
|
115
|
+
|
|
116
|
+
- Full utility class system
|
|
117
|
+
- All EVA CSS features enabled
|
|
118
|
+
- Pre-configured theme
|
|
119
|
+
- Example HTML with utility classes
|
|
120
|
+
|
|
121
|
+
### Full
|
|
122
|
+
|
|
123
|
+
Complete starter with examples:
|
|
124
|
+
|
|
125
|
+
- Everything from Utility preset
|
|
126
|
+
- Theme switching demo
|
|
127
|
+
- Gradient examples
|
|
128
|
+
- Component patterns
|
|
129
|
+
- Comprehensive documentation
|
|
130
|
+
|
|
131
|
+
## Configuration
|
|
132
|
+
|
|
133
|
+
All projects include `eva.config.cjs` for easy customization:
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
module.exports = {
|
|
137
|
+
sizes: [16, 24, 32, 64], // Your design sizes
|
|
138
|
+
fontSizes: [16, 24, 32], // Your font scale
|
|
139
|
+
buildClass: true, // Generate utilities
|
|
140
|
+
purge: {
|
|
141
|
+
enabled: false, // Enable for production
|
|
142
|
+
content: ['**/*.html'],
|
|
143
|
+
// ... more options
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Examples
|
|
149
|
+
|
|
150
|
+
### From Figma Design
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Extract sizes from your Figma design: 8, 16, 24, 32, 48, 64, 96
|
|
154
|
+
# Extract font sizes: 14, 16, 20, 24, 32, 48
|
|
155
|
+
|
|
156
|
+
npx create-eva-css my-figma-project \
|
|
157
|
+
--preset utility \
|
|
158
|
+
--sizes "8,16,24,32,48,64,96" \
|
|
159
|
+
--font-sizes "14,16,20,24,32,48"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Quick Prototype
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npx create-eva-css prototype --preset full
|
|
166
|
+
cd prototype
|
|
167
|
+
npm run dev
|
|
168
|
+
# Open index.html
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Component Library
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
npx create-eva-css my-components --preset minimal
|
|
175
|
+
cd my-components
|
|
176
|
+
npm install
|
|
177
|
+
npm run dev
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Troubleshooting
|
|
181
|
+
|
|
182
|
+
### Permission Errors
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# If you get permission errors on Windows:
|
|
186
|
+
npx create-eva-css my-project
|
|
187
|
+
|
|
188
|
+
# On Linux/Mac:
|
|
189
|
+
sudo npm init eva-css my-project
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Package Manager Issues
|
|
193
|
+
|
|
194
|
+
The tool auto-detects your package manager, but you can force one:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx create-eva-css my-project --package-manager pnpm
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Resources
|
|
201
|
+
|
|
202
|
+
- [EVA CSS Documentation](https://eva-css.xyz/)
|
|
203
|
+
- [GitHub Repository](https://github.com/nkdeus/eva)
|
|
204
|
+
- [Migration Guide](https://github.com/nkdeus/eva/blob/main/packages/eva-css/MIGRATION.md)
|
|
205
|
+
- [eva-css-fluid Package](https://www.npmjs.com/package/eva-css-fluid)
|
|
206
|
+
- [eva-css-purge Package](https://www.npmjs.com/package/eva-css-purge)
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT © [Michaël Tati](https://ulysse-2029.com/)
|
package/index.js
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create-eva-css
|
|
5
|
+
* Scaffolding tool for EVA CSS projects
|
|
6
|
+
*
|
|
7
|
+
* Usage: npm init eva-css my-project
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { createInterface } from 'readline';
|
|
14
|
+
import { execSync } from 'child_process';
|
|
15
|
+
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
|
|
18
|
+
// CLI colors
|
|
19
|
+
const colors = {
|
|
20
|
+
reset: '\x1b[0m',
|
|
21
|
+
bright: '\x1b[1m',
|
|
22
|
+
dim: '\x1b[2m',
|
|
23
|
+
green: '\x1b[32m',
|
|
24
|
+
blue: '\x1b[34m',
|
|
25
|
+
cyan: '\x1b[36m',
|
|
26
|
+
yellow: '\x1b[33m',
|
|
27
|
+
red: '\x1b[31m'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function log(msg) {
|
|
31
|
+
console.log(msg);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function success(msg) {
|
|
35
|
+
log(`${colors.green}✓${colors.reset} ${msg}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function info(msg) {
|
|
39
|
+
log(`${colors.blue}ℹ${colors.reset} ${msg}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function error(msg) {
|
|
43
|
+
log(`${colors.red}✗${colors.reset} ${msg}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function title(msg) {
|
|
47
|
+
log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Readline interface for prompts
|
|
51
|
+
function prompt(question) {
|
|
52
|
+
const rl = createInterface({
|
|
53
|
+
input: process.stdin,
|
|
54
|
+
output: process.stdout
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return new Promise(resolve => {
|
|
58
|
+
rl.question(`${colors.cyan}?${colors.reset} ${question} `, answer => {
|
|
59
|
+
rl.close();
|
|
60
|
+
resolve(answer.trim());
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function select(question, options) {
|
|
66
|
+
log(`${colors.cyan}?${colors.reset} ${question}`);
|
|
67
|
+
options.forEach((opt, i) => {
|
|
68
|
+
log(` ${colors.dim}${i + 1}.${colors.reset} ${opt.label}${opt.description ? ` ${colors.dim}- ${opt.description}${colors.reset}` : ''}`);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const answer = await prompt(' Select (1-' + options.length + '):');
|
|
72
|
+
const index = parseInt(answer) - 1;
|
|
73
|
+
|
|
74
|
+
if (index >= 0 && index < options.length) {
|
|
75
|
+
return options[index].value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
error('Invalid selection, using default');
|
|
79
|
+
return options[0].value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function confirm(question, defaultValue = true) {
|
|
83
|
+
const defaultText = defaultValue ? 'Y/n' : 'y/N';
|
|
84
|
+
const answer = await prompt(`${question} (${defaultText})`);
|
|
85
|
+
|
|
86
|
+
if (!answer) return defaultValue;
|
|
87
|
+
return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Template generators
|
|
91
|
+
function generatePackageJson(projectName, packageManager) {
|
|
92
|
+
return {
|
|
93
|
+
name: projectName,
|
|
94
|
+
version: '1.0.0',
|
|
95
|
+
description: 'EVA CSS Fluid Design Project',
|
|
96
|
+
private: true,
|
|
97
|
+
type: 'module',
|
|
98
|
+
scripts: {
|
|
99
|
+
build: 'sass styles/main.scss:styles/main.css',
|
|
100
|
+
'build:watch': 'sass --watch styles/main.scss:styles/main.css',
|
|
101
|
+
'build:purge': 'sass styles/main.scss:styles/main.css && eva-purge --css styles/main.css --content "**/*.html"',
|
|
102
|
+
dev: 'npm run build:watch'
|
|
103
|
+
},
|
|
104
|
+
dependencies: {
|
|
105
|
+
'eva-css-fluid': '^1.0.4'
|
|
106
|
+
},
|
|
107
|
+
devDependencies: {
|
|
108
|
+
'sass': '^1.77.0',
|
|
109
|
+
'eva-css-purge': '^1.0.4'
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function generateEvaConfig(sizes, fontSizes, preset) {
|
|
115
|
+
return `/**
|
|
116
|
+
* EVA CSS Configuration
|
|
117
|
+
*
|
|
118
|
+
* Customize these values to match your design system
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
// Size values for spacing, width, height, etc.
|
|
123
|
+
sizes: [${sizes.join(', ')}],
|
|
124
|
+
|
|
125
|
+
// Font size values
|
|
126
|
+
fontSizes: [${fontSizes.join(', ')}],
|
|
127
|
+
|
|
128
|
+
// Generate utility classes
|
|
129
|
+
buildClass: true,
|
|
130
|
+
|
|
131
|
+
// Show debug info during compilation
|
|
132
|
+
debug: ${preset === 'full'},
|
|
133
|
+
|
|
134
|
+
// Production optimization
|
|
135
|
+
purge: {
|
|
136
|
+
enabled: false, // Set to true for production
|
|
137
|
+
content: ['**/*.html', '**/*.js'],
|
|
138
|
+
css: 'styles/main.css',
|
|
139
|
+
output: 'styles/main-purged.css',
|
|
140
|
+
safelist: ['theme-', 'current-', 'toggle-theme']
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function generateScss(preset) {
|
|
147
|
+
if (preset === 'minimal') {
|
|
148
|
+
return `// EVA CSS - Variables Only Mode
|
|
149
|
+
@use 'eva-css-fluid/variables';
|
|
150
|
+
|
|
151
|
+
// Your custom styles here
|
|
152
|
+
body {
|
|
153
|
+
margin: 0;
|
|
154
|
+
padding: var(--16);
|
|
155
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (preset === 'utility') {
|
|
161
|
+
return `// EVA CSS - Utility Classes Mode
|
|
162
|
+
@use 'eva-css-fluid';
|
|
163
|
+
|
|
164
|
+
// Your custom styles here
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// full preset
|
|
169
|
+
return `// EVA CSS - Full Framework
|
|
170
|
+
@use 'eva-css-fluid' as *;
|
|
171
|
+
|
|
172
|
+
// Custom theme
|
|
173
|
+
.theme-myproject {
|
|
174
|
+
--brand-lightness: 62.8%;
|
|
175
|
+
--brand-chroma: 0.258;
|
|
176
|
+
--brand-hue: 29.23;
|
|
177
|
+
|
|
178
|
+
--accent-lightness: 51.7%;
|
|
179
|
+
--accent-chroma: 0.293;
|
|
180
|
+
--accent-hue: 289.66;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Your custom styles here
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function generateHtml(projectName, preset) {
|
|
188
|
+
const minimalContent = `<!DOCTYPE html>
|
|
189
|
+
<html lang="en">
|
|
190
|
+
<head>
|
|
191
|
+
<meta charset="UTF-8">
|
|
192
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
193
|
+
<title>${projectName}</title>
|
|
194
|
+
<link rel="stylesheet" href="styles/main.css">
|
|
195
|
+
</head>
|
|
196
|
+
<body>
|
|
197
|
+
<h1>Welcome to ${projectName}</h1>
|
|
198
|
+
<p>Using EVA CSS Variables</p>
|
|
199
|
+
</body>
|
|
200
|
+
</html>
|
|
201
|
+
`;
|
|
202
|
+
|
|
203
|
+
const utilityContent = `<!DOCTYPE html>
|
|
204
|
+
<html lang="en">
|
|
205
|
+
<head>
|
|
206
|
+
<meta charset="UTF-8">
|
|
207
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
208
|
+
<title>${projectName}</title>
|
|
209
|
+
<link rel="stylesheet" href="styles/main.css">
|
|
210
|
+
</head>
|
|
211
|
+
<body class="current-theme theme-myproject">
|
|
212
|
+
<div class="p-32">
|
|
213
|
+
<h1 class="fs-32 _c-brand">Welcome to ${projectName}</h1>
|
|
214
|
+
<p class="fs-16 _c-dark mt-16">Built with EVA CSS fluid design framework</p>
|
|
215
|
+
|
|
216
|
+
<div class="mt-32 p-24 _bg-brand_ br-16">
|
|
217
|
+
<p class="_c-dark">Fluid responsive design with no breakpoints!</p>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</body>
|
|
221
|
+
</html>
|
|
222
|
+
`;
|
|
223
|
+
|
|
224
|
+
const fullContent = `<!DOCTYPE html>
|
|
225
|
+
<html lang="en">
|
|
226
|
+
<head>
|
|
227
|
+
<meta charset="UTF-8">
|
|
228
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
229
|
+
<title>${projectName}</title>
|
|
230
|
+
<link rel="stylesheet" href="styles/main.css">
|
|
231
|
+
</head>
|
|
232
|
+
<body class="current-theme theme-myproject">
|
|
233
|
+
<div class="p-32">
|
|
234
|
+
<h1 class="fs-48 _c-brand">Welcome to ${projectName}</h1>
|
|
235
|
+
<p class="fs-16 _c-dark mt-16">Built with EVA CSS fluid design framework</p>
|
|
236
|
+
|
|
237
|
+
<div class="mt-32 p-24 _bg-brand_ br-16">
|
|
238
|
+
<h2 class="fs-24 _c-dark">Features</h2>
|
|
239
|
+
<ul class="mt-16">
|
|
240
|
+
<li class="_c-dark">Fluid responsive design</li>
|
|
241
|
+
<li class="_c-dark">OKLCH color system</li>
|
|
242
|
+
<li class="_c-dark">Modern gradients</li>
|
|
243
|
+
<li class="_c-dark">Theme switching</li>
|
|
244
|
+
</ul>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<div class="mt-32">
|
|
248
|
+
<button class="p-16 _bg-accent _c-light br-8" onclick="document.body.classList.toggle('toggle-theme')">
|
|
249
|
+
Toggle Theme
|
|
250
|
+
</button>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
</body>
|
|
254
|
+
</html>
|
|
255
|
+
`;
|
|
256
|
+
|
|
257
|
+
if (preset === 'minimal') return minimalContent;
|
|
258
|
+
if (preset === 'utility') return utilityContent;
|
|
259
|
+
return fullContent;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function generateReadme(projectName, preset) {
|
|
263
|
+
return `# ${projectName}
|
|
264
|
+
|
|
265
|
+
EVA CSS Fluid Design Project
|
|
266
|
+
|
|
267
|
+
## Getting Started
|
|
268
|
+
|
|
269
|
+
\`\`\`bash
|
|
270
|
+
# Install dependencies
|
|
271
|
+
npm install
|
|
272
|
+
|
|
273
|
+
# Build CSS
|
|
274
|
+
npm run build
|
|
275
|
+
|
|
276
|
+
# Watch mode
|
|
277
|
+
npm run dev
|
|
278
|
+
|
|
279
|
+
# Build with purge (production)
|
|
280
|
+
npm run build:purge
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
## Configuration
|
|
284
|
+
|
|
285
|
+
Edit \`eva.config.cjs\` to customize:
|
|
286
|
+
- Size values from your design
|
|
287
|
+
- Font sizes
|
|
288
|
+
- Build options
|
|
289
|
+
- Purge settings
|
|
290
|
+
|
|
291
|
+
## Documentation
|
|
292
|
+
|
|
293
|
+
- [EVA CSS Documentation](https://eva-css.xyz/)
|
|
294
|
+
- [GitHub Repository](https://github.com/nkdeus/eva)
|
|
295
|
+
|
|
296
|
+
## Project Structure
|
|
297
|
+
|
|
298
|
+
\`\`\`
|
|
299
|
+
${projectName}/
|
|
300
|
+
├── eva.config.cjs # EVA CSS configuration
|
|
301
|
+
├── package.json
|
|
302
|
+
├── index.html # Demo page
|
|
303
|
+
└── styles/
|
|
304
|
+
└── main.scss # Main stylesheet
|
|
305
|
+
\`\`\`
|
|
306
|
+
|
|
307
|
+
## Next Steps
|
|
308
|
+
|
|
309
|
+
1. Customize sizes in \`eva.config.cjs\` to match your design
|
|
310
|
+
2. Edit \`styles/main.scss\` to add custom styles
|
|
311
|
+
3. Build your project in \`index.html\`
|
|
312
|
+
4. Run \`npm run dev\` to watch for changes
|
|
313
|
+
|
|
314
|
+
Happy coding! 🚀
|
|
315
|
+
`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async function createProject(projectName, options = {}) {
|
|
319
|
+
try {
|
|
320
|
+
title('🎨 EVA CSS Project Scaffolding');
|
|
321
|
+
|
|
322
|
+
// Get project directory
|
|
323
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
324
|
+
|
|
325
|
+
// Check if directory exists
|
|
326
|
+
if (fs.existsSync(targetDir)) {
|
|
327
|
+
error(`Directory ${projectName} already exists!`);
|
|
328
|
+
const overwrite = await confirm('Overwrite?', false);
|
|
329
|
+
if (!overwrite) {
|
|
330
|
+
log('\nAborted.');
|
|
331
|
+
process.exit(0);
|
|
332
|
+
}
|
|
333
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Get configuration
|
|
337
|
+
let preset, sizes, fontSizes, packageManager;
|
|
338
|
+
|
|
339
|
+
if (options.preset) {
|
|
340
|
+
preset = options.preset;
|
|
341
|
+
} else {
|
|
342
|
+
preset = await select('Select project template:', [
|
|
343
|
+
{ label: 'Minimal', value: 'minimal', description: 'Variables only, no utilities' },
|
|
344
|
+
{ label: 'Utility', value: 'utility', description: 'Full utility classes' },
|
|
345
|
+
{ label: 'Full', value: 'full', description: 'Everything + examples' }
|
|
346
|
+
]);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (options.sizes) {
|
|
350
|
+
sizes = options.sizes.split(',').map(s => parseInt(s.trim()));
|
|
351
|
+
} else {
|
|
352
|
+
const sizesInput = await prompt('Design sizes (comma-separated) [16,24,32,64]:');
|
|
353
|
+
sizes = sizesInput ? sizesInput.split(',').map(s => parseInt(s.trim())) : [16, 24, 32, 64];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (options.fontSizes) {
|
|
357
|
+
fontSizes = options.fontSizes.split(',').map(s => parseInt(s.trim()));
|
|
358
|
+
} else {
|
|
359
|
+
const fontSizesInput = await prompt('Font sizes (comma-separated) [16,24,32]:');
|
|
360
|
+
fontSizes = fontSizesInput ? fontSizesInput.split(',').map(s => parseInt(s.trim())) : [16, 24, 32];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (options.packageManager) {
|
|
364
|
+
packageManager = options.packageManager;
|
|
365
|
+
} else {
|
|
366
|
+
packageManager = await select('Package manager:', [
|
|
367
|
+
{ label: 'npm', value: 'npm' },
|
|
368
|
+
{ label: 'pnpm', value: 'pnpm' },
|
|
369
|
+
{ label: 'yarn', value: 'yarn' }
|
|
370
|
+
]);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Create project structure
|
|
374
|
+
log('\n📁 Creating project structure...');
|
|
375
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
376
|
+
fs.mkdirSync(path.join(targetDir, 'styles'), { recursive: true });
|
|
377
|
+
|
|
378
|
+
// Generate files
|
|
379
|
+
log('📝 Generating files...');
|
|
380
|
+
|
|
381
|
+
// package.json
|
|
382
|
+
fs.writeFileSync(
|
|
383
|
+
path.join(targetDir, 'package.json'),
|
|
384
|
+
JSON.stringify(generatePackageJson(projectName, packageManager), null, 2)
|
|
385
|
+
);
|
|
386
|
+
success('Created package.json');
|
|
387
|
+
|
|
388
|
+
// eva.config.cjs
|
|
389
|
+
fs.writeFileSync(
|
|
390
|
+
path.join(targetDir, 'eva.config.cjs'),
|
|
391
|
+
generateEvaConfig(sizes, fontSizes, preset)
|
|
392
|
+
);
|
|
393
|
+
success('Created eva.config.cjs');
|
|
394
|
+
|
|
395
|
+
// styles/main.scss
|
|
396
|
+
fs.writeFileSync(
|
|
397
|
+
path.join(targetDir, 'styles', 'main.scss'),
|
|
398
|
+
generateScss(preset)
|
|
399
|
+
);
|
|
400
|
+
success('Created styles/main.scss');
|
|
401
|
+
|
|
402
|
+
// index.html
|
|
403
|
+
fs.writeFileSync(
|
|
404
|
+
path.join(targetDir, 'index.html'),
|
|
405
|
+
generateHtml(projectName, preset)
|
|
406
|
+
);
|
|
407
|
+
success('Created index.html');
|
|
408
|
+
|
|
409
|
+
// README.md
|
|
410
|
+
fs.writeFileSync(
|
|
411
|
+
path.join(targetDir, 'README.md'),
|
|
412
|
+
generateReadme(projectName, preset)
|
|
413
|
+
);
|
|
414
|
+
success('Created README.md');
|
|
415
|
+
|
|
416
|
+
// .gitignore
|
|
417
|
+
fs.writeFileSync(
|
|
418
|
+
path.join(targetDir, '.gitignore'),
|
|
419
|
+
'node_modules/\nstyles/*.css\nstyles/*.css.map\n.DS_Store\n'
|
|
420
|
+
);
|
|
421
|
+
success('Created .gitignore');
|
|
422
|
+
|
|
423
|
+
// Install dependencies
|
|
424
|
+
const shouldInstall = await confirm('\n📦 Install dependencies?', true);
|
|
425
|
+
|
|
426
|
+
if (shouldInstall) {
|
|
427
|
+
log(`\n⏳ Installing dependencies with ${packageManager}...`);
|
|
428
|
+
try {
|
|
429
|
+
const installCmd = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;
|
|
430
|
+
execSync(installCmd, { cwd: targetDir, stdio: 'inherit' });
|
|
431
|
+
success('Dependencies installed');
|
|
432
|
+
} catch (error) {
|
|
433
|
+
error('Failed to install dependencies');
|
|
434
|
+
log(' You can install them manually later');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Success message
|
|
439
|
+
title('✅ Project created successfully!');
|
|
440
|
+
|
|
441
|
+
log(`\n${colors.bright}Next steps:${colors.reset}\n`);
|
|
442
|
+
log(` ${colors.dim}1.${colors.reset} cd ${projectName}`);
|
|
443
|
+
if (!shouldInstall) {
|
|
444
|
+
log(` ${colors.dim}2.${colors.reset} ${packageManager} install`);
|
|
445
|
+
}
|
|
446
|
+
log(` ${colors.dim}${shouldInstall ? '2' : '3'}.${colors.reset} ${packageManager} run dev`);
|
|
447
|
+
log(` ${colors.dim}${shouldInstall ? '3' : '4'}.${colors.reset} Open index.html in your browser\n`);
|
|
448
|
+
|
|
449
|
+
log(`${colors.dim}Documentation: https://eva-css.xyz/${colors.reset}\n`);
|
|
450
|
+
|
|
451
|
+
} catch (error) {
|
|
452
|
+
log(`\n${colors.red}Error: ${error.message}${colors.reset}\n`);
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Parse CLI arguments
|
|
458
|
+
const args = process.argv.slice(2);
|
|
459
|
+
|
|
460
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
461
|
+
log(`
|
|
462
|
+
${colors.bright}${colors.cyan}create-eva-css${colors.reset} - EVA CSS Project Scaffolding
|
|
463
|
+
|
|
464
|
+
Usage:
|
|
465
|
+
npm init eva-css <project-name> [options]
|
|
466
|
+
npx create-eva-css <project-name> [options]
|
|
467
|
+
|
|
468
|
+
Options:
|
|
469
|
+
--preset <type> Template preset (minimal|utility|full)
|
|
470
|
+
--sizes <sizes> Comma-separated size values
|
|
471
|
+
--font-sizes <sizes> Comma-separated font size values
|
|
472
|
+
--package-manager <pm> Package manager (npm|pnpm|yarn)
|
|
473
|
+
--help, -h Show this help
|
|
474
|
+
|
|
475
|
+
Examples:
|
|
476
|
+
npm init eva-css my-project
|
|
477
|
+
npx create-eva-css my-app --preset utility
|
|
478
|
+
npx create-eva-css my-site --sizes "16,24,32,64" --font-sizes "16,24,32"
|
|
479
|
+
`);
|
|
480
|
+
process.exit(0);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const projectName = args[0];
|
|
484
|
+
const options = {};
|
|
485
|
+
|
|
486
|
+
for (let i = 1; i < args.length; i++) {
|
|
487
|
+
if (args[i] === '--preset') options.preset = args[++i];
|
|
488
|
+
if (args[i] === '--sizes') options.sizes = args[++i];
|
|
489
|
+
if (args[i] === '--font-sizes') options.fontSizes = args[++i];
|
|
490
|
+
if (args[i] === '--package-manager') options.packageManager = args[++i];
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
createProject(projectName, options);
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-eva-css",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Scaffolding tool for EVA CSS projects - npm init eva-css",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-eva-css": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"templates/"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"eva",
|
|
15
|
+
"eva-css",
|
|
16
|
+
"scaffolding",
|
|
17
|
+
"cli",
|
|
18
|
+
"starter",
|
|
19
|
+
"template",
|
|
20
|
+
"create",
|
|
21
|
+
"init"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "node index.js test-project --preset minimal"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/nkdeus/eva.git",
|
|
30
|
+
"directory": "packages/create-eva-css"
|
|
31
|
+
},
|
|
32
|
+
"author": {
|
|
33
|
+
"name": "Michaël Tati",
|
|
34
|
+
"url": "https://ulysse-2029.com/"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://eva-css.xyz/",
|
|
37
|
+
"license": "MIT"
|
|
38
|
+
}
|