bertui 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/build.js +53 -51
package/index.js CHANGED
@@ -32,5 +32,5 @@ export default {
32
32
  buildCSS,
33
33
  copyCSS,
34
34
  program,
35
- version: "0.3.9"
35
+ version: "1.0.3"
36
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bertui",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Lightning-fast React dev server powered by Bun and Elysia",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/src/build.js CHANGED
@@ -1,4 +1,4 @@
1
- // src/build.js - COMPLETE FIXED VERSION v1.0.1
1
+ // src/build.js - COMPLETE v1.0.0 FIXED VERSION
2
2
  import { join, relative, basename, extname, dirname } from 'path';
3
3
  import { existsSync, mkdirSync, rmSync, cpSync, readdirSync, statSync } from 'fs';
4
4
  import logger from './logger/logger.js';
@@ -11,7 +11,8 @@ export async function buildProduction(options = {}) {
11
11
  const buildDir = join(root, '.bertuibuild');
12
12
  const outDir = join(root, 'dist');
13
13
 
14
- logger.bigLog('BUILDING FOR PRODUCTION', { color: 'green' });
14
+ logger.bigLog('BUILDING FOR PRODUCTION v1.0.0', { color: 'green' });
15
+ logger.info('🔥 SINGLE CSS FILE SOLUTION - NO BULLSHIT');
15
16
 
16
17
  // Clean up old builds
17
18
  if (existsSync(buildDir)) {
@@ -38,7 +39,7 @@ export async function buildProduction(options = {}) {
38
39
  const { routes } = await compileForBuild(root, buildDir, envVars);
39
40
  logger.success(`Production compilation complete - ${routes.length} routes`);
40
41
 
41
- logger.info('Step 2: Building CSS with Lightning CSS...');
42
+ logger.info('Step 2: Combining ALL CSS into ONE file...');
42
43
  await buildAllCSS(root, outDir);
43
44
 
44
45
  logger.info('Step 3: Checking image optimization tools...');
@@ -87,15 +88,7 @@ export async function buildProduction(options = {}) {
87
88
 
88
89
  logger.success('JavaScript bundled successfully');
89
90
 
90
- // ✅ DEBUG: Show what was built
91
- logger.info('Built outputs:');
92
- result.outputs.forEach((output, i) => {
93
- const relativePath = relative(outDir, output.path);
94
- logger.info(` ${i + 1}. ${relativePath} (${output.kind}, ${output.size} bytes)`);
95
- });
96
-
97
- logger.info('Step 6: Generating HTML files...');
98
- // ✅ CRITICAL FIX: Generate HTML files WITH CSS
91
+ logger.info('Step 6: Generating HTML files with SINGLE CSS...');
99
92
  await generateProductionHTML(root, outDir, result, routes);
100
93
 
101
94
  // Clean up build directory
@@ -108,7 +101,6 @@ export async function buildProduction(options = {}) {
108
101
  logger.success(`✨ Build complete in ${duration}ms`);
109
102
  logger.info(`📦 Output: ${outDir}`);
110
103
 
111
- // Show build summary
112
104
  logger.table(result.outputs.map(o => ({
113
105
  file: o.path.replace(outDir, ''),
114
106
  size: `${(o.size / 1024).toFixed(2)} KB`,
@@ -136,7 +128,7 @@ export async function buildProduction(options = {}) {
136
128
  }
137
129
  }
138
130
 
139
- // SIMPLE asset copying
131
+ // SIMPLE asset copying
140
132
  async function copyAllStaticAssets(root, outDir, optimize = true) {
141
133
  const publicDir = join(root, 'public');
142
134
  const srcImagesDir = join(root, 'src', 'images');
@@ -164,6 +156,8 @@ async function copyAllStaticAssets(root, outDir, optimize = true) {
164
156
  logger.success('✅ All assets copied');
165
157
  }
166
158
 
159
+ // COMBINE ALL CSS INTO ONE FILE
160
+ // COMBINE ALL CSS INTO ONE FILE - FIXED BUN API
167
161
  async function buildAllCSS(root, outDir) {
168
162
  const srcStylesDir = join(root, 'src', 'styles');
169
163
  const stylesOutDir = join(outDir, 'styles');
@@ -172,15 +166,47 @@ async function buildAllCSS(root, outDir) {
172
166
 
173
167
  if (existsSync(srcStylesDir)) {
174
168
  const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
175
- logger.info(`Found ${cssFiles.length} CSS files to minify`);
169
+ logger.info(`📦 Found ${cssFiles.length} CSS files to combine`);
170
+
171
+ if (cssFiles.length === 0) {
172
+ logger.warn('⚠️ No CSS files found in src/styles/');
173
+ return;
174
+ }
175
+
176
+ // COMBINE ALL CSS INTO ONE FILE
177
+ let combinedCSS = '';
178
+ let totalOriginalSize = 0;
179
+
176
180
  for (const cssFile of cssFiles) {
177
181
  const srcPath = join(srcStylesDir, cssFile);
178
- const destPath = join(stylesOutDir, cssFile.replace('.css', '.min.css'));
179
- await buildCSS(srcPath, destPath);
182
+ const file = Bun.file(srcPath);
183
+ const cssContent = await file.text();
184
+ totalOriginalSize += file.size;
185
+ combinedCSS += `/* === ${cssFile} === */\n${cssContent}\n\n`;
180
186
  }
187
+
188
+ // Write combined CSS
189
+ const combinedPath = join(stylesOutDir, 'bertui.min.css');
190
+ await Bun.write(combinedPath, combinedCSS);
191
+
192
+ // Minify it
193
+ const minified = await buildCSS(combinedPath, combinedPath);
194
+
195
+ // Get final size
196
+ const finalFile = Bun.file(combinedPath);
197
+ const finalSize = finalFile.size / 1024;
198
+ const originalSize = totalOriginalSize / 1024;
199
+ const savings = ((originalSize - finalSize) / originalSize * 100).toFixed(1);
200
+
201
+ logger.success(`✅ Combined ${cssFiles.length} CSS files (${originalSize.toFixed(1)}KB) → bertui.min.css (${finalSize.toFixed(1)}KB, -${savings}%)`);
202
+
203
+ } else {
204
+ logger.warn('⚠️ No src/styles/ directory found');
205
+ // Create empty CSS file so build doesn't fail
206
+ const emptyPath = join(stylesOutDir, 'bertui.min.css');
207
+ await Bun.write(emptyPath, '/* No CSS files found */');
181
208
  }
182
209
  }
183
-
184
210
  async function compileForBuild(root, buildDir, envVars) {
185
211
  const srcDir = join(root, 'src');
186
212
  const pagesDir = join(srcDir, 'pages');
@@ -552,11 +578,10 @@ function extractMetaFromSource(code) {
552
578
  }
553
579
  }
554
580
 
555
- // CRITICAL FIX: Generate HTML files WITH CSS
581
+ // GENERATE HTML WITH SINGLE CSS FILE
556
582
  async function generateProductionHTML(root, outDir, buildResult, routes) {
557
- logger.info('Step 6: Generating HTML files with CSS...');
583
+ logger.info('Step 6: Generating HTML files with SINGLE CSS...');
558
584
 
559
- // Find main JS bundle
560
585
  const mainBundle = buildResult.outputs.find(o =>
561
586
  o.path.includes('main') && o.kind === 'entry-point'
562
587
  );
@@ -569,28 +594,6 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
569
594
  const bundlePath = relative(outDir, mainBundle.path).replace(/\\/g, '/');
570
595
  logger.info(`Main JS bundle: /${bundlePath}`);
571
596
 
572
- // ✅ CRITICAL FIX: Get CSS files from DIST directory
573
- const stylesOutDir = join(outDir, 'styles');
574
- let cssLinks = '';
575
-
576
- if (existsSync(stylesOutDir)) {
577
- const cssFiles = readdirSync(stylesOutDir).filter(f => f.endsWith('.min.css'));
578
- logger.info(`Found ${cssFiles.length} CSS files: ${cssFiles.join(', ')}`);
579
-
580
- if (cssFiles.length > 0) {
581
- // Create CSS link tags
582
- cssLinks = cssFiles.map(cssFile =>
583
- ` <link rel="stylesheet" href="/styles/${cssFile}">`
584
- ).join('\n');
585
-
586
- logger.info(`Generated CSS links:\n${cssLinks}`);
587
- } else {
588
- logger.warn('⚠️ No .min.css files found in dist/styles/');
589
- }
590
- } else {
591
- logger.error('❌ dist/styles/ directory not found!');
592
- }
593
-
594
597
  // Load config
595
598
  const { loadConfig } = await import('./config/loadConfig.js');
596
599
  const config = await loadConfig(root);
@@ -598,20 +601,18 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
598
601
 
599
602
  logger.info(`Generating HTML for ${routes.length} routes...`);
600
603
 
601
- // Generate HTML for each route
602
604
  for (const route of routes) {
603
605
  try {
604
606
  const sourceCode = await Bun.file(route.path).text();
605
607
  const pageMeta = extractMetaFromSource(sourceCode);
606
608
  const meta = { ...defaultMeta, ...pageMeta };
607
609
 
608
- const html = generateHTML(meta, route, bundlePath, cssLinks);
610
+ const html = generateHTML(meta, route, bundlePath);
609
611
 
610
612
  let htmlPath;
611
613
  if (route.route === '/') {
612
614
  htmlPath = join(outDir, 'index.html');
613
615
  } else {
614
- // Remove leading slash for directory creation
615
616
  const routeDir = join(outDir, route.route.replace(/^\//, ''));
616
617
  mkdirSync(routeDir, { recursive: true });
617
618
  htmlPath = join(routeDir, 'index.html');
@@ -625,10 +626,10 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
625
626
  }
626
627
  }
627
628
 
628
- logger.success('✨ All HTML files generated with CSS!');
629
+ logger.success('✨ All HTML files generated with SINGLE CSS file!');
629
630
  }
630
631
 
631
- function generateHTML(meta, route, bundlePath, cssLinks) {
632
+ function generateHTML(meta, route, bundlePath) {
632
633
  return `<!DOCTYPE html>
633
634
  <html lang="${meta.lang || 'en'}">
634
635
  <head>
@@ -636,7 +637,7 @@ function generateHTML(meta, route, bundlePath, cssLinks) {
636
637
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
637
638
  <title>${meta.title || 'BertUI App'}</title>
638
639
 
639
- <meta name="description" content="${meta.description || 'Built with BertUI'}">
640
+ <meta name="description" content="${meta.description || 'Built with BertUI - Lightning fast React development'}">
640
641
  ${meta.keywords ? `<meta name="keywords" content="${meta.keywords}">` : ''}
641
642
  ${meta.author ? `<meta name="author" content="${meta.author}">` : ''}
642
643
  ${meta.themeColor ? `<meta name="theme-color" content="${meta.themeColor}">` : ''}
@@ -652,11 +653,12 @@ function generateHTML(meta, route, bundlePath, cssLinks) {
652
653
  <meta name="twitter:description" content="${meta.twitterDescription || meta.ogDescription || meta.description || 'Built with BertUI'}">
653
654
  ${meta.twitterImage || meta.ogImage ? `<meta name="twitter:image" content="${meta.twitterImage || meta.ogImage}">` : ''}
654
655
 
656
+ <!-- 🔥 ONE CSS FILE FOR ALL PAGES - NO BULLSHIT -->
657
+ <link rel="stylesheet" href="/styles/bertui.min.css">
658
+
655
659
  <link rel="icon" type="image/svg+xml" href="/favicon.svg">
656
660
  <link rel="canonical" href="${route.route}">
657
661
 
658
- ${cssLinks}
659
-
660
662
  <script type="importmap">
661
663
  {
662
664
  "imports": {