bertui 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/build.js +68 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bertui",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
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 - COMPLETELY FIXED VERSION
1
+ // src/build.js - COMPLETE FIXED VERSION v1.0.1
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';
@@ -45,8 +45,7 @@ export async function buildProduction(options = {}) {
45
45
  const optimizationTools = await checkOptimizationTools();
46
46
 
47
47
  logger.info('Step 4: Copying and optimizing static assets...');
48
- // SKIP OPTIMIZATION FOR NOW - JUST COPY
49
- await copyAllStaticAssets(root, outDir);
48
+ await copyAllStaticAssets(root, outDir, false);
50
49
 
51
50
  logger.info('Step 5: Bundling JavaScript with Bun...');
52
51
  const buildEntry = join(buildDir, 'main.js');
@@ -88,14 +87,15 @@ export async function buildProduction(options = {}) {
88
87
 
89
88
  logger.success('JavaScript bundled successfully');
90
89
 
91
- // DEBUG: Show what was built
90
+ // DEBUG: Show what was built
92
91
  logger.info('Built outputs:');
93
92
  result.outputs.forEach((output, i) => {
94
- logger.info(` ${i + 1}. ${relative(outDir, output.path)} (${output.kind})`);
93
+ const relativePath = relative(outDir, output.path);
94
+ logger.info(` ${i + 1}. ${relativePath} (${output.kind}, ${output.size} bytes)`);
95
95
  });
96
96
 
97
97
  logger.info('Step 6: Generating HTML files...');
98
- // ✅ CRITICAL FIX: Generate HTML files
98
+ // ✅ CRITICAL FIX: Generate HTML files WITH CSS
99
99
  await generateProductionHTML(root, outDir, result, routes);
100
100
 
101
101
  // Clean up build directory
@@ -136,23 +136,29 @@ export async function buildProduction(options = {}) {
136
136
  }
137
137
  }
138
138
 
139
- async function copyAllStaticAssets(root, outDir) {
139
+ // SIMPLE asset copying
140
+ async function copyAllStaticAssets(root, outDir, optimize = true) {
140
141
  const publicDir = join(root, 'public');
141
142
  const srcImagesDir = join(root, 'src', 'images');
142
143
 
143
144
  logger.info('📦 Copying static assets...');
144
145
 
145
- // Copy from public/ to dist/
146
+ // Copy from public/ to root of dist/
146
147
  if (existsSync(publicDir)) {
147
148
  logger.info(' Copying public/ directory...');
148
149
  copyImages(publicDir, outDir);
150
+ } else {
151
+ logger.info(' No public/ directory found');
149
152
  }
150
153
 
151
154
  // Copy from src/images/ to dist/images/
152
155
  if (existsSync(srcImagesDir)) {
156
+ logger.info(' Copying src/images/ to dist/images/...');
153
157
  const distImagesDir = join(outDir, 'images');
154
- logger.info(` Copying src/images/ to ${relative(root, distImagesDir)}/...`);
158
+ mkdirSync(distImagesDir, { recursive: true });
155
159
  copyImages(srcImagesDir, distImagesDir);
160
+ } else {
161
+ logger.info(' No src/images/ directory found');
156
162
  }
157
163
 
158
164
  logger.success('✅ All assets copied');
@@ -166,6 +172,7 @@ async function buildAllCSS(root, outDir) {
166
172
 
167
173
  if (existsSync(srcStylesDir)) {
168
174
  const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
175
+ logger.info(`Found ${cssFiles.length} CSS files to minify`);
169
176
  for (const cssFile of cssFiles) {
170
177
  const srcPath = join(srcStylesDir, cssFile);
171
178
  const destPath = join(stylesOutDir, cssFile.replace('.css', '.min.css'));
@@ -545,14 +552,9 @@ function extractMetaFromSource(code) {
545
552
  }
546
553
  }
547
554
 
548
- // ✅ CRITICAL FIX: Generate HTML files
555
+ // ✅ CRITICAL FIX: Generate HTML files WITH CSS
549
556
  async function generateProductionHTML(root, outDir, buildResult, routes) {
550
- if (routes.length === 0) {
551
- logger.warn('No routes found, skipping HTML generation');
552
- return;
553
- }
554
-
555
- logger.info(`Generating HTML files for ${routes.length} routes...`);
557
+ logger.info('Step 6: Generating HTML files with CSS...');
556
558
 
557
559
  // Find main JS bundle
558
560
  const mainBundle = buildResult.outputs.find(o =>
@@ -560,23 +562,42 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
560
562
  );
561
563
 
562
564
  if (!mainBundle) {
563
- logger.error('Could not find main bundle in build output');
564
- // List all outputs for debugging
565
- logger.info('Available outputs:');
566
- buildResult.outputs.forEach((o, i) => {
567
- logger.info(` ${i + 1}. ${o.path} (${o.kind})`);
568
- });
565
+ logger.error('Could not find main bundle');
569
566
  return;
570
567
  }
571
568
 
572
569
  const bundlePath = relative(outDir, mainBundle.path).replace(/\\/g, '/');
573
- logger.info(`Main bundle: ${bundlePath}`);
570
+ logger.info(`Main JS bundle: /${bundlePath}`);
571
+
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
+ }
574
593
 
575
- // Load config for default meta
594
+ // Load config
576
595
  const { loadConfig } = await import('./config/loadConfig.js');
577
596
  const config = await loadConfig(root);
578
597
  const defaultMeta = config.meta || {};
579
598
 
599
+ logger.info(`Generating HTML for ${routes.length} routes...`);
600
+
580
601
  // Generate HTML for each route
581
602
  for (const route of routes) {
582
603
  try {
@@ -584,32 +605,30 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
584
605
  const pageMeta = extractMetaFromSource(sourceCode);
585
606
  const meta = { ...defaultMeta, ...pageMeta };
586
607
 
587
- const html = generateHTML(meta, route, bundlePath);
608
+ const html = generateHTML(meta, route, bundlePath, cssLinks);
588
609
 
589
610
  let htmlPath;
590
611
  if (route.route === '/') {
591
612
  htmlPath = join(outDir, 'index.html');
592
613
  } else {
593
- // Create directory for the route
594
- const routeDir = join(outDir, route.route.slice(1)); // Remove leading slash
614
+ // Remove leading slash for directory creation
615
+ const routeDir = join(outDir, route.route.replace(/^\//, ''));
595
616
  mkdirSync(routeDir, { recursive: true });
596
617
  htmlPath = join(routeDir, 'index.html');
597
618
  }
598
619
 
599
620
  await Bun.write(htmlPath, html);
600
- logger.success(`Generated: ${route.route === '/' ? 'index.html' : route.route + '/index.html'}`);
621
+ logger.success(`✅ Generated: ${route.route === '/' ? '/' : route.route}`);
622
+
601
623
  } catch (error) {
602
624
  logger.error(`Failed to generate HTML for ${route.route}: ${error.message}`);
603
625
  }
604
626
  }
627
+
628
+ logger.success('✨ All HTML files generated with CSS!');
605
629
  }
606
630
 
607
- function generateHTML(meta, route, bundlePath) {
608
- const cssFiles = ['global.min.css', 'home.min.css'];
609
- const stylesheets = cssFiles.map(css =>
610
- ` <link rel="stylesheet" href="/styles/${css}">`
611
- ).join('\n');
612
-
631
+ function generateHTML(meta, route, bundlePath, cssLinks) {
613
632
  return `<!DOCTYPE html>
614
633
  <html lang="${meta.lang || 'en'}">
615
634
  <head>
@@ -617,13 +636,26 @@ function generateHTML(meta, route, bundlePath) {
617
636
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
618
637
  <title>${meta.title || 'BertUI App'}</title>
619
638
 
620
- <meta name="description" content="${meta.description || 'Built with BertUI - Lightning fast React development'}">
639
+ <meta name="description" content="${meta.description || 'Built with BertUI'}">
621
640
  ${meta.keywords ? `<meta name="keywords" content="${meta.keywords}">` : ''}
622
641
  ${meta.author ? `<meta name="author" content="${meta.author}">` : ''}
642
+ ${meta.themeColor ? `<meta name="theme-color" content="${meta.themeColor}">` : ''}
643
+
644
+ <meta property="og:title" content="${meta.ogTitle || meta.title || 'BertUI App'}">
645
+ <meta property="og:description" content="${meta.ogDescription || meta.description || 'Built with BertUI'}">
646
+ ${meta.ogImage ? `<meta property="og:image" content="${meta.ogImage}">` : ''}
647
+ <meta property="og:type" content="website">
648
+ <meta property="og:url" content="${route.route}">
649
+
650
+ <meta name="twitter:card" content="summary_large_image">
651
+ <meta name="twitter:title" content="${meta.twitterTitle || meta.ogTitle || meta.title || 'BertUI App'}">
652
+ <meta name="twitter:description" content="${meta.twitterDescription || meta.ogDescription || meta.description || 'Built with BertUI'}">
653
+ ${meta.twitterImage || meta.ogImage ? `<meta name="twitter:image" content="${meta.twitterImage || meta.ogImage}">` : ''}
623
654
 
624
655
  <link rel="icon" type="image/svg+xml" href="/favicon.svg">
656
+ <link rel="canonical" href="${route.route}">
625
657
 
626
- ${stylesheets}
658
+ ${cssLinks}
627
659
 
628
660
  <script type="importmap">
629
661
  {