bertui 0.2.9 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -116
- package/bin/bertui.js +0 -0
- package/package.json +2 -4
- package/src/build/css-builder.js +28 -31
- package/src/build.js +41 -11
- package/src/client/compiler.js +41 -17
package/README.md
CHANGED
|
@@ -2,110 +2,101 @@
|
|
|
2
2
|
|
|
3
3
|
Lightning-fast React development powered by Bun.
|
|
4
4
|
|
|
5
|
+
## ⚠️ Important Notice - CSS Animations Temporarily Unavailable
|
|
6
|
+
|
|
7
|
+
**The built-in CSS animation utilities have been temporarily removed** due to compatibility issues with `bun.build`. We're working on a solution and they will be back in an upcoming release.
|
|
8
|
+
|
|
9
|
+
**What this means:**
|
|
10
|
+
- The 15+ animation classes (`.fadein`, `.scalein`, `.bouncein`, etc.) are not currently available
|
|
11
|
+
- You can still use your own CSS animations or external libraries
|
|
12
|
+
- All other BertUI features work normally
|
|
13
|
+
|
|
14
|
+
**We apologize for any inconvenience caused.** This feature will return soon! 🚀
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
5
18
|
## Features
|
|
6
19
|
|
|
7
20
|
- ⚡ **Blazing Fast** - Built on Bun
|
|
8
|
-
-
|
|
21
|
+
- 📁 **File-Based Routing** - Zero config routing
|
|
9
22
|
- 🔥 **Hot Module Replacement** - Instant updates
|
|
10
23
|
- 📦 **Zero Config** - Works out of the box
|
|
11
24
|
- 🚀 **Production Ready** - Optimized builds
|
|
12
25
|
|
|
13
|
-
##
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Create New App (Recommended)
|
|
14
29
|
```bash
|
|
15
|
-
|
|
30
|
+
bunx create-bertui my-app
|
|
31
|
+
cd my-app
|
|
32
|
+
bun run dev
|
|
16
33
|
```
|
|
17
34
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import ReactDOM from 'react-dom/client';
|
|
35
|
+
This creates a complete BertUI project with:
|
|
36
|
+
- Pre-configured file structure
|
|
37
|
+
- Sample pages with routing
|
|
38
|
+
- Beautiful example components
|
|
39
|
+
- All dependencies installed
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
### Manual Installation (Advanced)
|
|
42
|
+
If you want to configure everything yourself:
|
|
43
|
+
```bash
|
|
44
|
+
bun add bertui react react-dom
|
|
28
45
|
```
|
|
29
46
|
|
|
47
|
+
Then you'll need to manually set up:
|
|
48
|
+
- Project structure (`src/pages/`, `src/main.jsx`, etc.)
|
|
49
|
+
- Router configuration
|
|
50
|
+
- Build configuration
|
|
51
|
+
|
|
52
|
+
**Note:** We recommend using `bunx create-bertui` for the best experience!
|
|
53
|
+
|
|
30
54
|
## Commands
|
|
31
55
|
```bash
|
|
32
56
|
bertui dev # Start dev server
|
|
33
57
|
bertui build # Build for production
|
|
34
58
|
```
|
|
35
59
|
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
- `.split` - Split text animation
|
|
39
|
-
- `.moveright` - Slide from left
|
|
40
|
-
- `.moveleft` - Slide from right
|
|
41
|
-
- `.fadein` - Fade in
|
|
42
|
-
- `.scalein` - Scale in
|
|
43
|
-
- `.bouncein` - Bounce in
|
|
44
|
-
- `.slideup` - Slide up
|
|
45
|
-
- `.slidedown` - Slide down
|
|
46
|
-
- `.rotatein` - Rotate in
|
|
47
|
-
- `.pulse` - Pulse animation
|
|
48
|
-
- `.shake` - Shake animation
|
|
49
|
-
|
|
50
|
-
# 🎉 BertUI Now Has File-Based Routing!
|
|
51
|
-
|
|
52
|
-
## What We Built
|
|
53
|
-
|
|
54
|
-
I've added a **complete file-based routing system** to BertUI. Here's what's included:
|
|
55
|
-
|
|
56
|
-
### 📁 New Files to Add
|
|
60
|
+
## File-Based Routing
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
- Scans `src/pages/` directory
|
|
60
|
-
- Generates route definitions
|
|
61
|
-
- Creates React Router component
|
|
62
|
-
- Provides `Link` and `navigate` utilities
|
|
62
|
+
BertUI now has **complete file-based routing**! Here's what's included:
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
- Detects `pages/` directory
|
|
66
|
-
- Auto-generates router code
|
|
67
|
-
- Supports both routing and non-routing modes
|
|
64
|
+
### 📁 Features
|
|
68
65
|
|
|
69
|
-
|
|
70
|
-
- Serves SPA-style HTML for all routes
|
|
71
|
-
- Notifies clients of route changes
|
|
72
|
-
- Better HMR integration
|
|
73
|
-
|
|
74
|
-
## 🚀 Features
|
|
75
|
-
|
|
76
|
-
### ✅ File-Based Routing
|
|
66
|
+
#### ✅ File-Based Routing
|
|
77
67
|
```
|
|
78
68
|
src/pages/index.jsx → /
|
|
79
69
|
src/pages/about.jsx → /about
|
|
80
70
|
src/pages/blog/index.jsx → /blog
|
|
81
71
|
```
|
|
82
72
|
|
|
83
|
-
|
|
73
|
+
#### ✅ Dynamic Routes
|
|
84
74
|
```
|
|
85
75
|
src/pages/user/[id].jsx → /user/:id
|
|
86
76
|
src/pages/blog/[slug].jsx → /blog/:slug
|
|
87
77
|
src/pages/shop/[cat]/[prod].jsx → /shop/:cat/:prod
|
|
88
78
|
```
|
|
89
79
|
|
|
90
|
-
|
|
80
|
+
#### ✅ Navigation Components
|
|
91
81
|
```jsx
|
|
92
|
-
import { Link, navigate } from '
|
|
82
|
+
import { Link, navigate } from 'bertui/router';
|
|
93
83
|
|
|
94
84
|
// Link component
|
|
95
|
-
<Link
|
|
85
|
+
<Link to="/about">About</Link>
|
|
96
86
|
|
|
97
87
|
// Programmatic navigation
|
|
88
|
+
const { navigate } = useRouter();
|
|
98
89
|
navigate('/dashboard');
|
|
99
90
|
```
|
|
100
91
|
|
|
101
|
-
|
|
92
|
+
#### ✅ Route Parameters
|
|
102
93
|
```jsx
|
|
103
94
|
export default function UserProfile({ params }) {
|
|
104
95
|
return <div>User ID: {params.id}</div>;
|
|
105
96
|
}
|
|
106
97
|
```
|
|
107
98
|
|
|
108
|
-
|
|
99
|
+
#### ✅ Backward Compatible
|
|
109
100
|
- Still works with `src/main.jsx` if no `pages/` directory
|
|
110
101
|
- Automatically detects routing mode
|
|
111
102
|
- No breaking changes!
|
|
@@ -139,44 +130,31 @@ export default function UserProfile({ params }) {
|
|
|
139
130
|
- Client-side routing handles navigation
|
|
140
131
|
- HMR updates routes on file changes
|
|
141
132
|
|
|
142
|
-
##
|
|
143
|
-
|
|
144
|
-
### 1. Add Router Files
|
|
145
|
-
Copy these files to your BertUI project:
|
|
146
|
-
- `src/router/router.js` (new)
|
|
147
|
-
- `src/client/compiler.js` (replace)
|
|
148
|
-
- `src/server/dev-server.js` (replace)
|
|
149
|
-
|
|
150
|
-
### 2. Update Dependencies
|
|
151
|
-
No new dependencies needed! Uses existing React ecosystem.
|
|
152
|
-
|
|
153
|
-
### 3. Test It
|
|
154
|
-
```bash
|
|
155
|
-
# Create example pages
|
|
156
|
-
mkdir -p src/pages
|
|
157
|
-
echo 'export default () => <h1>Home</h1>' > src/pages/index.jsx
|
|
158
|
-
echo 'export default () => <h1>About</h1>' > src/pages/about.jsx
|
|
159
|
-
|
|
160
|
-
# Start dev server
|
|
161
|
-
bertui dev
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### 4. Watch the Magic
|
|
165
|
-
- Navigate to `http://localhost:3000` → Home page
|
|
166
|
-
- Click links → No page reload!
|
|
167
|
-
- Edit files → Instant HMR!
|
|
168
|
-
- Check console → Route discovery logs
|
|
169
|
-
|
|
170
|
-
## 🎨 Works with BertUI Animations
|
|
133
|
+
## 🎓 Usage Example
|
|
171
134
|
|
|
172
135
|
```jsx
|
|
136
|
+
// src/pages/index.jsx
|
|
137
|
+
import { Link } from 'bertui/router';
|
|
138
|
+
|
|
173
139
|
export default function Home() {
|
|
174
140
|
return (
|
|
175
141
|
<div>
|
|
176
|
-
<h1
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
142
|
+
<h1>Welcome to My App!</h1>
|
|
143
|
+
<nav>
|
|
144
|
+
<Link to="/about">About</Link>
|
|
145
|
+
<Link to="/blog">Blog</Link>
|
|
146
|
+
<Link to="/user/123">My Profile</Link>
|
|
147
|
+
</nav>
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/pages/user/[id].jsx
|
|
153
|
+
export default function UserProfile({ params }) {
|
|
154
|
+
return (
|
|
155
|
+
<div>
|
|
156
|
+
<h1>User {params.id}</h1>
|
|
157
|
+
<p>Profile page for user {params.id}</p>
|
|
180
158
|
</div>
|
|
181
159
|
);
|
|
182
160
|
}
|
|
@@ -210,34 +188,13 @@ Update `build.js` to:
|
|
|
210
188
|
- Create optimized bundles per route
|
|
211
189
|
- Handle dynamic routes appropriately
|
|
212
190
|
|
|
213
|
-
##
|
|
214
|
-
|
|
215
|
-
```jsx
|
|
216
|
-
// src/pages/index.jsx
|
|
217
|
-
import { Link } from '../.bertui/router';
|
|
191
|
+
## 🏁 Conclusion
|
|
218
192
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
<Link href="/about">About</Link>
|
|
225
|
-
<Link href="/blog">Blog</Link>
|
|
226
|
-
<Link href="/user/123">My Profile</Link>
|
|
227
|
-
</nav>
|
|
228
|
-
</div>
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// src/pages/user/[id].jsx
|
|
233
|
-
export default function UserProfile({ params }) {
|
|
234
|
-
return (
|
|
235
|
-
<div className="scalein">
|
|
236
|
-
<h1>User {params.id}</h1>
|
|
237
|
-
<p>Profile page for user {params.id}</p>
|
|
238
|
-
</div>
|
|
239
|
-
);
|
|
240
|
-
}
|
|
193
|
+
BertUI now has **production-ready file-based routing** that's:
|
|
194
|
+
- ⚡ **Fast** - Built on Bun
|
|
195
|
+
- 🎯 **Simple** - Zero config
|
|
196
|
+
- 💪 **Powerful** - Dynamic routes, params, navigation
|
|
197
|
+
- 🔥 **Modern** - HMR, code splitting, SPA
|
|
241
198
|
|
|
242
199
|
## License
|
|
243
200
|
|
package/bin/bertui.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bertui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Lightning-fast React dev server powered by Bun and Elysia",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -46,9 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"elysia": "^1.0.0",
|
|
48
48
|
"ernest-logger": "latest",
|
|
49
|
-
"
|
|
50
|
-
"autoprefixer": "^10.4.16",
|
|
51
|
-
"cssnano": "^6.0.2"
|
|
49
|
+
"lightningcss": "^1.30.2"
|
|
52
50
|
},
|
|
53
51
|
"peerDependencies": {
|
|
54
52
|
"react": "^18.0.0 || ^19.0.0",
|
package/src/build/css-builder.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
// src/build/css-builder.js
|
|
2
1
|
import { join } from 'path';
|
|
3
2
|
import { existsSync, mkdirSync } from 'fs';
|
|
4
|
-
import
|
|
5
|
-
import autoprefixer from 'autoprefixer';
|
|
6
|
-
import cssnano from 'cssnano';
|
|
3
|
+
import { transform } from 'lightningcss';
|
|
7
4
|
import logger from '../logger/logger.js';
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
|
-
* Build and minify CSS for production
|
|
7
|
+
* Build and minify CSS for production using Lightning CSS
|
|
11
8
|
* @param {string} srcPath - Source CSS file path
|
|
12
9
|
* @param {string} destPath - Destination CSS file path
|
|
13
10
|
*/
|
|
14
11
|
export async function buildCSS(srcPath, destPath) {
|
|
15
12
|
try {
|
|
16
|
-
logger.info(
|
|
13
|
+
logger.info(`Processing CSS: ${srcPath.split('/').pop()}`);
|
|
17
14
|
|
|
18
15
|
// Ensure destination directory exists
|
|
19
16
|
const destDir = join(destPath, '..');
|
|
@@ -23,38 +20,38 @@ export async function buildCSS(srcPath, destPath) {
|
|
|
23
20
|
|
|
24
21
|
// Read source CSS
|
|
25
22
|
const css = await Bun.file(srcPath).text();
|
|
23
|
+
const originalSize = Buffer.byteLength(css);
|
|
26
24
|
|
|
27
|
-
//
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
// Transform with Lightning CSS (blazing fast)
|
|
26
|
+
const { code } = transform({
|
|
27
|
+
filename: srcPath,
|
|
28
|
+
code: Buffer.from(css),
|
|
29
|
+
minify: true,
|
|
30
|
+
sourceMap: false,
|
|
31
|
+
targets: {
|
|
32
|
+
// Support last 2 versions of major browsers
|
|
33
|
+
chrome: 90 << 16,
|
|
34
|
+
firefox: 88 << 16,
|
|
35
|
+
safari: 14 << 16,
|
|
36
|
+
edge: 90 << 16
|
|
37
|
+
},
|
|
38
|
+
drafts: {
|
|
39
|
+
nesting: true // Enable CSS nesting
|
|
40
|
+
}
|
|
41
|
+
});
|
|
40
42
|
|
|
41
43
|
// Write minified CSS
|
|
42
|
-
await Bun.write(destPath,
|
|
44
|
+
await Bun.write(destPath, code);
|
|
43
45
|
|
|
44
46
|
// Calculate size reduction
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const
|
|
47
|
+
const minifiedSize = code.length;
|
|
48
|
+
const originalKB = (originalSize / 1024).toFixed(2);
|
|
49
|
+
const minifiedKB = (minifiedSize / 1024).toFixed(2);
|
|
50
|
+
const reduction = ((1 - minifiedSize / originalSize) * 100).toFixed(1);
|
|
48
51
|
|
|
49
|
-
logger.success(`CSS minified: ${
|
|
52
|
+
logger.success(`CSS minified: ${originalKB}KB → ${minifiedKB}KB (-${reduction}%)`);
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
result.warnings().forEach(warn => {
|
|
53
|
-
logger.warn(warn.toString());
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return { success: true, size: minifiedSize };
|
|
54
|
+
return { success: true, size: minifiedKB };
|
|
58
55
|
} catch (error) {
|
|
59
56
|
logger.error(`CSS build failed: ${error.message}`);
|
|
60
57
|
throw error;
|
package/src/build.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// src/build.js
|
|
2
1
|
import { join } from 'path';
|
|
3
2
|
import { existsSync, mkdirSync, rmSync, cpSync, readdirSync, statSync } from 'fs';
|
|
4
3
|
import { extname, relative, dirname } from 'path';
|
|
@@ -32,11 +31,9 @@ export async function buildProduction(options = {}) {
|
|
|
32
31
|
await compileForBuild(root, buildDir);
|
|
33
32
|
logger.success('Production compilation complete');
|
|
34
33
|
|
|
35
|
-
// Step 2: Build CSS
|
|
36
|
-
logger.info('Step 2: Building CSS...');
|
|
37
|
-
|
|
38
|
-
const bertuiCssDest = join(outDir, 'styles/bertui.min.css');
|
|
39
|
-
await buildCSS(bertuiCssSource, bertuiCssDest);
|
|
34
|
+
// Step 2: Build CSS with Lightning CSS
|
|
35
|
+
logger.info('Step 2: Building CSS with Lightning CSS...');
|
|
36
|
+
await buildAllCSS(root, outDir);
|
|
40
37
|
|
|
41
38
|
// Step 3: Copy public assets if they exist
|
|
42
39
|
const publicDir = join(root, 'public');
|
|
@@ -49,7 +46,7 @@ export async function buildProduction(options = {}) {
|
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
// Step 4: Build JavaScript with Bun's bundler
|
|
52
|
-
logger.info('Step 4: Bundling JavaScript...');
|
|
49
|
+
logger.info('Step 4: Bundling JavaScript with Bun...');
|
|
53
50
|
const buildEntry = join(buildDir, 'main.js');
|
|
54
51
|
|
|
55
52
|
if (!existsSync(buildEntry)) {
|
|
@@ -57,6 +54,7 @@ export async function buildProduction(options = {}) {
|
|
|
57
54
|
process.exit(1);
|
|
58
55
|
}
|
|
59
56
|
|
|
57
|
+
// FIXED: Let Bun handle ALL imports with proper externals
|
|
60
58
|
const result = await Bun.build({
|
|
61
59
|
entrypoints: [buildEntry],
|
|
62
60
|
outdir: join(outDir, 'assets'),
|
|
@@ -69,7 +67,8 @@ export async function buildProduction(options = {}) {
|
|
|
69
67
|
chunk: 'chunks/[name]-[hash].js',
|
|
70
68
|
asset: '[name]-[hash].[ext]'
|
|
71
69
|
},
|
|
72
|
-
|
|
70
|
+
// FIXED: Use CDN externals - Bun handles tree shaking automatically
|
|
71
|
+
external: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime']
|
|
73
72
|
});
|
|
74
73
|
|
|
75
74
|
if (!result.success) {
|
|
@@ -78,7 +77,7 @@ export async function buildProduction(options = {}) {
|
|
|
78
77
|
process.exit(1);
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
logger.success('JavaScript bundled');
|
|
80
|
+
logger.success('JavaScript bundled with tree-shaking');
|
|
82
81
|
|
|
83
82
|
// Step 5: Generate index.html
|
|
84
83
|
logger.info('Step 5: Generating index.html...');
|
|
@@ -121,6 +120,27 @@ export async function buildProduction(options = {}) {
|
|
|
121
120
|
}
|
|
122
121
|
}
|
|
123
122
|
|
|
123
|
+
async function buildAllCSS(root, outDir) {
|
|
124
|
+
const srcStylesDir = join(root, 'src', 'styles');
|
|
125
|
+
const bertuiCssSource = join(import.meta.dir, 'styles/bertui.css');
|
|
126
|
+
const stylesOutDir = join(outDir, 'styles');
|
|
127
|
+
|
|
128
|
+
mkdirSync(stylesOutDir, { recursive: true });
|
|
129
|
+
|
|
130
|
+
// Build BertUI's built-in CSS
|
|
131
|
+
await buildCSS(bertuiCssSource, join(stylesOutDir, 'bertui.min.css'));
|
|
132
|
+
|
|
133
|
+
// Build user's CSS files if they exist
|
|
134
|
+
if (existsSync(srcStylesDir)) {
|
|
135
|
+
const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
|
|
136
|
+
for (const cssFile of cssFiles) {
|
|
137
|
+
const srcPath = join(srcStylesDir, cssFile);
|
|
138
|
+
const destPath = join(stylesOutDir, cssFile.replace('.css', '.min.css'));
|
|
139
|
+
await buildCSS(srcPath, destPath);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
124
144
|
async function compileForBuild(root, buildDir) {
|
|
125
145
|
const srcDir = join(root, 'src');
|
|
126
146
|
const pagesDir = join(srcDir, 'pages');
|
|
@@ -160,6 +180,10 @@ async function discoverRoutes(pagesDir) {
|
|
|
160
180
|
await scanDirectory(fullPath, relativePath);
|
|
161
181
|
} else if (entry.isFile()) {
|
|
162
182
|
const ext = extname(entry.name);
|
|
183
|
+
|
|
184
|
+
// FIXED: Ignore CSS files
|
|
185
|
+
if (ext === '.css') continue;
|
|
186
|
+
|
|
163
187
|
if (['.jsx', '.tsx', '.js', '.ts'].includes(ext)) {
|
|
164
188
|
const fileName = entry.name.replace(ext, '');
|
|
165
189
|
|
|
@@ -345,6 +369,9 @@ async function compileBuildDirectory(srcDir, buildDir, root) {
|
|
|
345
369
|
} else {
|
|
346
370
|
const ext = extname(file);
|
|
347
371
|
|
|
372
|
+
// FIXED: Skip CSS files in build
|
|
373
|
+
if (ext === '.css') continue;
|
|
374
|
+
|
|
348
375
|
if (['.jsx', '.tsx', '.ts'].includes(ext)) {
|
|
349
376
|
await compileBuildFile(srcPath, buildDir, file, root);
|
|
350
377
|
} else if (ext === '.js') {
|
|
@@ -395,6 +422,7 @@ async function compileBuildFile(srcPath, buildDir, filename, root) {
|
|
|
395
422
|
}
|
|
396
423
|
}
|
|
397
424
|
|
|
425
|
+
// FIXED: Only fix router imports, preserve all others
|
|
398
426
|
function fixBuildImports(code, srcPath, outPath, root) {
|
|
399
427
|
// Remove bertui/styles imports
|
|
400
428
|
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
@@ -406,7 +434,7 @@ function fixBuildImports(code, srcPath, outPath, root) {
|
|
|
406
434
|
const relativeToRouter = relative(dirname(outPath), routerPath).replace(/\\/g, '/');
|
|
407
435
|
const routerImport = relativeToRouter.startsWith('.') ? relativeToRouter : './' + relativeToRouter;
|
|
408
436
|
|
|
409
|
-
//
|
|
437
|
+
// ONLY replace bertui/router imports
|
|
410
438
|
code = code.replace(
|
|
411
439
|
/from\s+['"]bertui\/router['"]/g,
|
|
412
440
|
`from '${routerImport}'`
|
|
@@ -451,7 +479,9 @@ async function generateProductionHTML(root, outDir, buildResult) {
|
|
|
451
479
|
{
|
|
452
480
|
"imports": {
|
|
453
481
|
"react": "https://esm.sh/react@18.2.0",
|
|
454
|
-
"react-dom": "https://esm.sh/react-dom@18.2.0"
|
|
482
|
+
"react-dom": "https://esm.sh/react-dom@18.2.0",
|
|
483
|
+
"react-dom/client": "https://esm.sh/react-dom@18.2.0/client",
|
|
484
|
+
"react/jsx-runtime": "https://esm.sh/react@18.2.0/jsx-runtime"
|
|
455
485
|
}
|
|
456
486
|
}
|
|
457
487
|
</script>
|
package/src/client/compiler.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, statSync } from 'fs';
|
|
2
|
-
import { join, extname, relative } from 'path';
|
|
2
|
+
import { join, extname, relative, dirname } from 'path';
|
|
3
3
|
import logger from '../logger/logger.js';
|
|
4
4
|
|
|
5
5
|
export async function compileProject(root) {
|
|
@@ -64,6 +64,14 @@ async function discoverRoutes(pagesDir) {
|
|
|
64
64
|
await scanDirectory(fullPath, relativePath);
|
|
65
65
|
} else if (entry.isFile()) {
|
|
66
66
|
const ext = extname(entry.name);
|
|
67
|
+
|
|
68
|
+
// FIXED: Ignore CSS files completely
|
|
69
|
+
if (ext === '.css') {
|
|
70
|
+
logger.debug(`Skipping CSS file: ${relativePath}`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Only process valid page files
|
|
67
75
|
if (['.jsx', '.tsx', '.js', '.ts'].includes(ext)) {
|
|
68
76
|
const fileName = entry.name.replace(ext, '');
|
|
69
77
|
|
|
@@ -255,14 +263,26 @@ async function compileDirectory(srcDir, outDir, root) {
|
|
|
255
263
|
const ext = extname(file);
|
|
256
264
|
const relativePath = relative(join(root, 'src'), srcPath);
|
|
257
265
|
|
|
258
|
-
|
|
266
|
+
// FIXED: Handle CSS files properly - copy to styles output
|
|
267
|
+
if (ext === '.css') {
|
|
268
|
+
const stylesOutDir = join(root, '.bertui', 'styles');
|
|
269
|
+
if (!existsSync(stylesOutDir)) {
|
|
270
|
+
mkdirSync(stylesOutDir, { recursive: true });
|
|
271
|
+
}
|
|
272
|
+
const cssOutPath = join(stylesOutDir, file);
|
|
273
|
+
await Bun.write(cssOutPath, Bun.file(srcPath));
|
|
274
|
+
logger.debug(`Copied CSS: ${relativePath}`);
|
|
275
|
+
stats.files++;
|
|
276
|
+
} else if (['.jsx', '.tsx', '.ts'].includes(ext)) {
|
|
259
277
|
await compileFile(srcPath, outDir, file, relativePath);
|
|
260
278
|
stats.files++;
|
|
261
279
|
} else if (ext === '.js') {
|
|
262
280
|
const outPath = join(outDir, file);
|
|
263
281
|
let code = await Bun.file(srcPath).text();
|
|
264
282
|
|
|
265
|
-
|
|
283
|
+
// FIXED: Don't modify imports - let Bun handle them
|
|
284
|
+
// Only fix router imports
|
|
285
|
+
code = fixRouterImports(code, outPath, root);
|
|
266
286
|
|
|
267
287
|
await Bun.write(outPath, code);
|
|
268
288
|
logger.debug(`Copied: ${relativePath}`);
|
|
@@ -284,7 +304,10 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
284
304
|
try {
|
|
285
305
|
let code = await Bun.file(srcPath).text();
|
|
286
306
|
|
|
287
|
-
|
|
307
|
+
// FIXED: Don't remove any imports - preserve them all
|
|
308
|
+
// Only fix router imports to point to compiled location
|
|
309
|
+
const outPath = join(outDir, filename.replace(/\.(jsx|tsx|ts)$/, '.js'));
|
|
310
|
+
code = fixRouterImports(code, outPath, process.cwd());
|
|
288
311
|
|
|
289
312
|
const transpiler = new Bun.Transpiler({
|
|
290
313
|
loader,
|
|
@@ -304,29 +327,31 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
304
327
|
|
|
305
328
|
compiled = fixRelativeImports(compiled);
|
|
306
329
|
|
|
307
|
-
const outFilename = filename.replace(/\.(jsx|tsx|ts)$/, '.js');
|
|
308
|
-
const outPath = join(outDir, outFilename);
|
|
309
|
-
|
|
310
330
|
await Bun.write(outPath, compiled);
|
|
311
|
-
logger.debug(`Compiled: ${relativePath} → ${
|
|
331
|
+
logger.debug(`Compiled: ${relativePath} → ${filename.replace(/\.(jsx|tsx|ts)$/, '.js')}`);
|
|
312
332
|
} catch (error) {
|
|
313
333
|
logger.error(`Failed to compile ${relativePath}: ${error.message}`);
|
|
314
334
|
throw error;
|
|
315
335
|
}
|
|
316
336
|
}
|
|
317
337
|
|
|
318
|
-
function
|
|
319
|
-
|
|
338
|
+
// FIXED: New function - only fixes bertui/router imports
|
|
339
|
+
function fixRouterImports(code, outPath, root) {
|
|
340
|
+
const buildDir = join(root, '.bertui', 'compiled');
|
|
341
|
+
const routerPath = join(buildDir, 'router.js');
|
|
320
342
|
|
|
343
|
+
// Calculate relative path from output file to router.js
|
|
344
|
+
const relativeToRouter = relative(dirname(outPath), routerPath).replace(/\\/g, '/');
|
|
345
|
+
const routerImport = relativeToRouter.startsWith('.') ? relativeToRouter : './' + relativeToRouter;
|
|
346
|
+
|
|
347
|
+
// ONLY replace bertui/router imports
|
|
321
348
|
code = code.replace(
|
|
322
349
|
/from\s+['"]bertui\/router['"]/g,
|
|
323
|
-
|
|
350
|
+
`from '${routerImport}'`
|
|
324
351
|
);
|
|
325
352
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
"from '/compiled/$1'"
|
|
329
|
-
);
|
|
353
|
+
// Remove bertui/styles imports (CSS handled separately)
|
|
354
|
+
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
330
355
|
|
|
331
356
|
return code;
|
|
332
357
|
}
|
|
@@ -342,5 +367,4 @@ function fixRelativeImports(code) {
|
|
|
342
367
|
});
|
|
343
368
|
|
|
344
369
|
return code;
|
|
345
|
-
}
|
|
346
|
-
|
|
370
|
+
}
|