bertui 1.0.0 → 1.0.2
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/package.json +1 -1
- package/src/build.js +64 -46
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/build.js -
|
|
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,15 +39,14 @@ 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:
|
|
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...');
|
|
45
46
|
const optimizationTools = await checkOptimizationTools();
|
|
46
47
|
|
|
47
48
|
logger.info('Step 4: Copying and optimizing static assets...');
|
|
48
|
-
|
|
49
|
-
await copyAllStaticAssets(root, outDir);
|
|
49
|
+
await copyAllStaticAssets(root, outDir, false);
|
|
50
50
|
|
|
51
51
|
logger.info('Step 5: Bundling JavaScript with Bun...');
|
|
52
52
|
const buildEntry = join(buildDir, 'main.js');
|
|
@@ -88,14 +88,7 @@ export async function buildProduction(options = {}) {
|
|
|
88
88
|
|
|
89
89
|
logger.success('JavaScript bundled successfully');
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
logger.info('Built outputs:');
|
|
93
|
-
result.outputs.forEach((output, i) => {
|
|
94
|
-
logger.info(` ${i + 1}. ${relative(outDir, output.path)} (${output.kind})`);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
logger.info('Step 6: Generating HTML files...');
|
|
98
|
-
// ✅ CRITICAL FIX: Generate HTML files
|
|
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,28 +128,35 @@ export async function buildProduction(options = {}) {
|
|
|
136
128
|
}
|
|
137
129
|
}
|
|
138
130
|
|
|
139
|
-
|
|
131
|
+
// SIMPLE asset copying
|
|
132
|
+
async function copyAllStaticAssets(root, outDir, optimize = true) {
|
|
140
133
|
const publicDir = join(root, 'public');
|
|
141
134
|
const srcImagesDir = join(root, 'src', 'images');
|
|
142
135
|
|
|
143
136
|
logger.info('📦 Copying static assets...');
|
|
144
137
|
|
|
145
|
-
// Copy from public/ to dist/
|
|
138
|
+
// Copy from public/ to root of dist/
|
|
146
139
|
if (existsSync(publicDir)) {
|
|
147
140
|
logger.info(' Copying public/ directory...');
|
|
148
141
|
copyImages(publicDir, outDir);
|
|
142
|
+
} else {
|
|
143
|
+
logger.info(' No public/ directory found');
|
|
149
144
|
}
|
|
150
145
|
|
|
151
146
|
// Copy from src/images/ to dist/images/
|
|
152
147
|
if (existsSync(srcImagesDir)) {
|
|
148
|
+
logger.info(' Copying src/images/ to dist/images/...');
|
|
153
149
|
const distImagesDir = join(outDir, 'images');
|
|
154
|
-
|
|
150
|
+
mkdirSync(distImagesDir, { recursive: true });
|
|
155
151
|
copyImages(srcImagesDir, distImagesDir);
|
|
152
|
+
} else {
|
|
153
|
+
logger.info(' No src/images/ directory found');
|
|
156
154
|
}
|
|
157
155
|
|
|
158
156
|
logger.success('✅ All assets copied');
|
|
159
157
|
}
|
|
160
158
|
|
|
159
|
+
// COMBINE ALL CSS INTO ONE FILE
|
|
161
160
|
async function buildAllCSS(root, outDir) {
|
|
162
161
|
const srcStylesDir = join(root, 'src', 'styles');
|
|
163
162
|
const stylesOutDir = join(outDir, 'styles');
|
|
@@ -166,11 +165,29 @@ async function buildAllCSS(root, outDir) {
|
|
|
166
165
|
|
|
167
166
|
if (existsSync(srcStylesDir)) {
|
|
168
167
|
const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
|
|
168
|
+
logger.info(`📦 Found ${cssFiles.length} CSS files to combine`);
|
|
169
|
+
|
|
170
|
+
// COMBINE ALL CSS INTO ONE FILE
|
|
171
|
+
let combinedCSS = '';
|
|
172
|
+
|
|
169
173
|
for (const cssFile of cssFiles) {
|
|
170
174
|
const srcPath = join(srcStylesDir, cssFile);
|
|
171
|
-
const
|
|
172
|
-
|
|
175
|
+
const cssContent = await Bun.file(srcPath).text();
|
|
176
|
+
combinedCSS += `/* === ${cssFile} === */\n${cssContent}\n\n`;
|
|
173
177
|
}
|
|
178
|
+
|
|
179
|
+
// Write combined CSS
|
|
180
|
+
const combinedPath = join(stylesOutDir, 'bertui.min.css');
|
|
181
|
+
await Bun.write(combinedPath, combinedCSS);
|
|
182
|
+
|
|
183
|
+
// Minify it
|
|
184
|
+
await buildCSS(combinedPath, combinedPath);
|
|
185
|
+
|
|
186
|
+
const size = (await Bun.file(combinedPath).size()) / 1024;
|
|
187
|
+
logger.success(`✅ Combined ${cssFiles.length} CSS files → bertui.min.css (${size.toFixed(1)}KB)`);
|
|
188
|
+
|
|
189
|
+
} else {
|
|
190
|
+
logger.warn('⚠️ No src/styles/ directory found');
|
|
174
191
|
}
|
|
175
192
|
}
|
|
176
193
|
|
|
@@ -545,39 +562,29 @@ function extractMetaFromSource(code) {
|
|
|
545
562
|
}
|
|
546
563
|
}
|
|
547
564
|
|
|
548
|
-
//
|
|
565
|
+
// GENERATE HTML WITH SINGLE CSS FILE
|
|
549
566
|
async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
550
|
-
|
|
551
|
-
logger.warn('No routes found, skipping HTML generation');
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
567
|
+
logger.info('Step 6: Generating HTML files with SINGLE CSS...');
|
|
554
568
|
|
|
555
|
-
logger.info(`Generating HTML files for ${routes.length} routes...`);
|
|
556
|
-
|
|
557
|
-
// Find main JS bundle
|
|
558
569
|
const mainBundle = buildResult.outputs.find(o =>
|
|
559
570
|
o.path.includes('main') && o.kind === 'entry-point'
|
|
560
571
|
);
|
|
561
572
|
|
|
562
573
|
if (!mainBundle) {
|
|
563
|
-
logger.error('Could not find main bundle
|
|
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
|
-
});
|
|
574
|
+
logger.error('❌ Could not find main bundle');
|
|
569
575
|
return;
|
|
570
576
|
}
|
|
571
577
|
|
|
572
578
|
const bundlePath = relative(outDir, mainBundle.path).replace(/\\/g, '/');
|
|
573
|
-
logger.info(`Main bundle:
|
|
579
|
+
logger.info(`Main JS bundle: /${bundlePath}`);
|
|
574
580
|
|
|
575
|
-
// Load config
|
|
581
|
+
// Load config
|
|
576
582
|
const { loadConfig } = await import('./config/loadConfig.js');
|
|
577
583
|
const config = await loadConfig(root);
|
|
578
584
|
const defaultMeta = config.meta || {};
|
|
579
585
|
|
|
580
|
-
|
|
586
|
+
logger.info(`Generating HTML for ${routes.length} routes...`);
|
|
587
|
+
|
|
581
588
|
for (const route of routes) {
|
|
582
589
|
try {
|
|
583
590
|
const sourceCode = await Bun.file(route.path).text();
|
|
@@ -590,26 +597,23 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
590
597
|
if (route.route === '/') {
|
|
591
598
|
htmlPath = join(outDir, 'index.html');
|
|
592
599
|
} else {
|
|
593
|
-
|
|
594
|
-
const routeDir = join(outDir, route.route.slice(1)); // Remove leading slash
|
|
600
|
+
const routeDir = join(outDir, route.route.replace(/^\//, ''));
|
|
595
601
|
mkdirSync(routeDir, { recursive: true });
|
|
596
602
|
htmlPath = join(routeDir, 'index.html');
|
|
597
603
|
}
|
|
598
604
|
|
|
599
605
|
await Bun.write(htmlPath, html);
|
|
600
|
-
logger.success(
|
|
606
|
+
logger.success(`✅ Generated: ${route.route === '/' ? '/' : route.route}`);
|
|
607
|
+
|
|
601
608
|
} catch (error) {
|
|
602
609
|
logger.error(`Failed to generate HTML for ${route.route}: ${error.message}`);
|
|
603
610
|
}
|
|
604
611
|
}
|
|
612
|
+
|
|
613
|
+
logger.success('✨ All HTML files generated with SINGLE CSS file!');
|
|
605
614
|
}
|
|
606
615
|
|
|
607
616
|
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
|
-
|
|
613
617
|
return `<!DOCTYPE html>
|
|
614
618
|
<html lang="${meta.lang || 'en'}">
|
|
615
619
|
<head>
|
|
@@ -620,10 +624,24 @@ function generateHTML(meta, route, bundlePath) {
|
|
|
620
624
|
<meta name="description" content="${meta.description || 'Built with BertUI - Lightning fast React development'}">
|
|
621
625
|
${meta.keywords ? `<meta name="keywords" content="${meta.keywords}">` : ''}
|
|
622
626
|
${meta.author ? `<meta name="author" content="${meta.author}">` : ''}
|
|
627
|
+
${meta.themeColor ? `<meta name="theme-color" content="${meta.themeColor}">` : ''}
|
|
623
628
|
|
|
624
|
-
<
|
|
629
|
+
<meta property="og:title" content="${meta.ogTitle || meta.title || 'BertUI App'}">
|
|
630
|
+
<meta property="og:description" content="${meta.ogDescription || meta.description || 'Built with BertUI'}">
|
|
631
|
+
${meta.ogImage ? `<meta property="og:image" content="${meta.ogImage}">` : ''}
|
|
632
|
+
<meta property="og:type" content="website">
|
|
633
|
+
<meta property="og:url" content="${route.route}">
|
|
634
|
+
|
|
635
|
+
<meta name="twitter:card" content="summary_large_image">
|
|
636
|
+
<meta name="twitter:title" content="${meta.twitterTitle || meta.ogTitle || meta.title || 'BertUI App'}">
|
|
637
|
+
<meta name="twitter:description" content="${meta.twitterDescription || meta.ogDescription || meta.description || 'Built with BertUI'}">
|
|
638
|
+
${meta.twitterImage || meta.ogImage ? `<meta name="twitter:image" content="${meta.twitterImage || meta.ogImage}">` : ''}
|
|
625
639
|
|
|
626
|
-
|
|
640
|
+
<!-- 🔥 ONE CSS FILE FOR ALL PAGES - NO BULLSHIT -->
|
|
641
|
+
<link rel="stylesheet" href="/styles/bertui.min.css">
|
|
642
|
+
|
|
643
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
644
|
+
<link rel="canonical" href="${route.route}">
|
|
627
645
|
|
|
628
646
|
<script type="importmap">
|
|
629
647
|
{
|