bertui 1.2.8 → 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.
Files changed (182) hide show
  1. package/README.md +45 -196
  2. package/TYPES_PATCH.md +17 -0
  3. package/bin/bertui.js +2 -7
  4. package/package.json +32 -98
  5. package/src/config.ts +4 -0
  6. package/src/index.ts +32 -0
  7. package/src/optional.ts +49 -0
  8. package/src/router.ts +3 -0
  9. package/tsconfig.json +29 -0
  10. package/LICENSE +0 -21
  11. package/index.js +0 -103
  12. package/src/analyzer/index.js +0 -370
  13. package/src/build/compiler/file-transpiler.js +0 -216
  14. package/src/build/compiler/index.js +0 -31
  15. package/src/build/compiler/route-discoverer.js +0 -49
  16. package/src/build/compiler/router-generator.js +0 -105
  17. package/src/build/css-builder.js +0 -81
  18. package/src/build/generators/html-generator.js +0 -151
  19. package/src/build/generators/robots-generator.js +0 -58
  20. package/src/build/generators/sitemap-generator.js +0 -63
  21. package/src/build/image-optimizer.js +0 -137
  22. package/src/build/processors/asset-processor.js +0 -19
  23. package/src/build/processors/css-builder.js +0 -142
  24. package/src/build/server-island-validator.js +0 -12
  25. package/src/build.js +0 -266
  26. package/src/cli.js +0 -131
  27. package/src/client/compiler.js +0 -522
  28. package/src/client/fast-refresh.js +0 -72
  29. package/src/client/hmr-runtime.js +0 -59
  30. package/src/compiler/index.js +0 -25
  31. package/src/compiler/router-generator-pure.js +0 -104
  32. package/src/compiler/transform.js +0 -149
  33. package/src/config/defaultConfig.js +0 -37
  34. package/src/config/index.js +0 -2
  35. package/src/config/loadConfig.js +0 -64
  36. package/src/config/og-image.png +0 -0
  37. package/src/css/index.js +0 -46
  38. package/src/css/processor.js +0 -172
  39. package/src/dev.js +0 -68
  40. package/src/hydration/index.js +0 -151
  41. package/src/image-optimizer/index.js +0 -103
  42. package/src/images/index.js +0 -102
  43. package/src/images/processor.js +0 -169
  44. package/src/layouts/index.js +0 -165
  45. package/src/loading/index.js +0 -210
  46. package/src/logger/logger.js +0 -320
  47. package/src/logger/notes.md +0 -20
  48. package/src/middleware/index.js +0 -182
  49. package/src/router/Router.js +0 -150
  50. package/src/router/SSRRouter.js +0 -156
  51. package/src/router/index.js +0 -3
  52. package/src/scaffolder/index.js +0 -310
  53. package/src/serve.js +0 -193
  54. package/src/server/dev-handler.js +0 -195
  55. package/src/server/dev-server-utils.js +0 -406
  56. package/src/server/dev-server.js +0 -15
  57. package/src/server/hmr-handler.js +0 -148
  58. package/src/server/index.js +0 -3
  59. package/src/server/notes.md +0 -1
  60. package/src/server/request-handler.js +0 -36
  61. package/src/server-islands/extractor.js +0 -198
  62. package/src/server-islands/index.js +0 -59
  63. package/src/styles/bertui.css +0 -210
  64. package/src/utils/cache.js +0 -297
  65. package/src/utils/env.js +0 -87
  66. package/src/utils/importhow.js +0 -52
  67. package/src/utils/index.js +0 -11
  68. package/src/utils/meta-extractor.js +0 -127
  69. package/types/bin/bertui.d.ts +0 -3
  70. package/types/bin/bertui.d.ts.map +0 -1
  71. package/types/error-overlay.d.ts +0 -2
  72. package/types/error-overlay.d.ts.map +0 -1
  73. package/types/index.d.ts +0 -26
  74. package/types/index.d.ts.map +0 -1
  75. package/types/scripts/fix-wasm-exports.d.ts +0 -2
  76. package/types/scripts/fix-wasm-exports.d.ts.map +0 -1
  77. package/types/src/analyzer/index.d.ts +0 -8
  78. package/types/src/analyzer/index.d.ts.map +0 -1
  79. package/types/src/build/compiler/file-transpiler.d.ts +0 -5
  80. package/types/src/build/compiler/file-transpiler.d.ts.map +0 -1
  81. package/types/src/build/compiler/index.d.ts +0 -12
  82. package/types/src/build/compiler/index.d.ts.map +0 -1
  83. package/types/src/build/compiler/route-discoverer.d.ts +0 -2
  84. package/types/src/build/compiler/route-discoverer.d.ts.map +0 -1
  85. package/types/src/build/compiler/router-generator.d.ts +0 -2
  86. package/types/src/build/compiler/router-generator.d.ts.map +0 -1
  87. package/types/src/build/css-builder.d.ts +0 -18
  88. package/types/src/build/css-builder.d.ts.map +0 -1
  89. package/types/src/build/generators/html-generator.d.ts +0 -2
  90. package/types/src/build/generators/html-generator.d.ts.map +0 -1
  91. package/types/src/build/generators/robots-generator.d.ts +0 -11
  92. package/types/src/build/generators/robots-generator.d.ts.map +0 -1
  93. package/types/src/build/generators/sitemap-generator.d.ts +0 -5
  94. package/types/src/build/generators/sitemap-generator.d.ts.map +0 -1
  95. package/types/src/build/image-optimizer.d.ts +0 -11
  96. package/types/src/build/image-optimizer.d.ts.map +0 -1
  97. package/types/src/build/processors/asset-processor.d.ts +0 -2
  98. package/types/src/build/processors/asset-processor.d.ts.map +0 -1
  99. package/types/src/build/processors/css-builder.d.ts +0 -2
  100. package/types/src/build/processors/css-builder.d.ts.map +0 -1
  101. package/types/src/build/server-island-validator.d.ts +0 -27
  102. package/types/src/build/server-island-validator.d.ts.map +0 -1
  103. package/types/src/build.d.ts +0 -5
  104. package/types/src/build.d.ts.map +0 -1
  105. package/types/src/cli.d.ts +0 -2
  106. package/types/src/cli.d.ts.map +0 -1
  107. package/types/src/client/compiler.d.ts +0 -16
  108. package/types/src/client/compiler.d.ts.map +0 -1
  109. package/types/src/client/fast-refresh.d.ts +0 -3
  110. package/types/src/client/fast-refresh.d.ts.map +0 -1
  111. package/types/src/client/hmr-runtime.d.ts +0 -4
  112. package/types/src/client/hmr-runtime.d.ts.map +0 -1
  113. package/types/src/compiler/index.d.ts +0 -8
  114. package/types/src/compiler/index.d.ts.map +0 -1
  115. package/types/src/compiler/router-generator-pure.d.ts +0 -2
  116. package/types/src/compiler/router-generator-pure.d.ts.map +0 -1
  117. package/types/src/compiler/transform.d.ts +0 -36
  118. package/types/src/compiler/transform.d.ts.map +0 -1
  119. package/types/src/config/defaultConfig.d.ts +0 -26
  120. package/types/src/config/defaultConfig.d.ts.map +0 -1
  121. package/types/src/config/index.d.ts +0 -3
  122. package/types/src/config/index.d.ts.map +0 -1
  123. package/types/src/config/loadConfig.d.ts +0 -2
  124. package/types/src/config/loadConfig.d.ts.map +0 -1
  125. package/types/src/css/index.d.ts +0 -6
  126. package/types/src/css/index.d.ts.map +0 -1
  127. package/types/src/css/processor.d.ts +0 -23
  128. package/types/src/css/processor.d.ts.map +0 -1
  129. package/types/src/dev.d.ts +0 -2
  130. package/types/src/dev.d.ts.map +0 -1
  131. package/types/src/hydration/index.d.ts +0 -33
  132. package/types/src/hydration/index.d.ts.map +0 -1
  133. package/types/src/image-optimizer/index.d.ts +0 -24
  134. package/types/src/image-optimizer/index.d.ts.map +0 -1
  135. package/types/src/images/index.d.ts +0 -12
  136. package/types/src/images/index.d.ts.map +0 -1
  137. package/types/src/images/processor.d.ts +0 -30
  138. package/types/src/images/processor.d.ts.map +0 -1
  139. package/types/src/layouts/index.d.ts +0 -28
  140. package/types/src/layouts/index.d.ts.map +0 -1
  141. package/types/src/loading/index.d.ts +0 -28
  142. package/types/src/loading/index.d.ts.map +0 -1
  143. package/types/src/logger/logger.d.ts +0 -30
  144. package/types/src/logger/logger.d.ts.map +0 -1
  145. package/types/src/middleware/index.d.ts +0 -61
  146. package/types/src/middleware/index.d.ts.map +0 -1
  147. package/types/src/router/Router.d.ts +0 -16
  148. package/types/src/router/Router.d.ts.map +0 -1
  149. package/types/src/router/SSRRouter.d.ts +0 -20
  150. package/types/src/router/SSRRouter.d.ts.map +0 -1
  151. package/types/src/router/index.d.ts +0 -3
  152. package/types/src/router/index.d.ts.map +0 -1
  153. package/types/src/scaffolder/index.d.ts +0 -14
  154. package/types/src/scaffolder/index.d.ts.map +0 -1
  155. package/types/src/serve.d.ts +0 -3
  156. package/types/src/serve.d.ts.map +0 -1
  157. package/types/src/server/dev-handler.d.ts +0 -13
  158. package/types/src/server/dev-handler.d.ts.map +0 -1
  159. package/types/src/server/dev-server-utils.d.ts +0 -6
  160. package/types/src/server/dev-server-utils.d.ts.map +0 -1
  161. package/types/src/server/dev-server.d.ts +0 -18
  162. package/types/src/server/dev-server.d.ts.map +0 -1
  163. package/types/src/server/hmr-handler.d.ts +0 -19
  164. package/types/src/server/hmr-handler.d.ts.map +0 -1
  165. package/types/src/server/index.d.ts +0 -4
  166. package/types/src/server/index.d.ts.map +0 -1
  167. package/types/src/server/request-handler.d.ts +0 -19
  168. package/types/src/server/request-handler.d.ts.map +0 -1
  169. package/types/src/server-islands/extractor.d.ts +0 -16
  170. package/types/src/server-islands/extractor.d.ts.map +0 -1
  171. package/types/src/server-islands/index.d.ts +0 -3
  172. package/types/src/server-islands/index.d.ts.map +0 -1
  173. package/types/src/utils/cache.d.ts +0 -52
  174. package/types/src/utils/cache.d.ts.map +0 -1
  175. package/types/src/utils/env.d.ts +0 -20
  176. package/types/src/utils/env.d.ts.map +0 -1
  177. package/types/src/utils/importhow.d.ts +0 -15
  178. package/types/src/utils/importhow.d.ts.map +0 -1
  179. package/types/src/utils/index.d.ts +0 -3
  180. package/types/src/utils/index.d.ts.map +0 -1
  181. package/types/src/utils/meta-extractor.d.ts +0 -13
  182. package/types/src/utils/meta-extractor.d.ts.map +0 -1
@@ -1,104 +0,0 @@
1
- // bertui/src/compiler/router-generator-pure.js - NEW FILE
2
- // PURE function - no file system, no server
3
-
4
- export function generateRouterCode(routes) {
5
- const imports = routes.map((route, i) => {
6
- const componentName = `Page${i}`;
7
- const importPath = route.importPath || `./pages/${route.file.replace(/\.(jsx|tsx|ts)$/, '.js')}`;
8
- return `import ${componentName} from '${importPath}';`;
9
- }).join('\n');
10
-
11
- const routeConfigs = routes.map((route, i) => {
12
- const componentName = `Page${i}`;
13
- return ` { path: '${route.route}', component: ${componentName}, type: '${route.type}' }`;
14
- }).join(',\n');
15
-
16
- return `import React, { useState, useEffect, createContext, useContext } from 'react';
17
-
18
- const RouterContext = createContext(null);
19
-
20
- export function useRouter() {
21
- const context = useContext(RouterContext);
22
- if (!context) throw new Error('useRouter must be used within a Router');
23
- return context;
24
- }
25
-
26
- export function Router({ routes }) {
27
- const [currentRoute, setCurrentRoute] = useState(null);
28
- const [params, setParams] = useState({});
29
-
30
- useEffect(() => {
31
- matchAndSetRoute(window.location.pathname);
32
- const handlePopState = () => matchAndSetRoute(window.location.pathname);
33
- window.addEventListener('popstate', handlePopState);
34
- return () => window.removeEventListener('popstate', handlePopState);
35
- }, [routes]);
36
-
37
- function matchAndSetRoute(pathname) {
38
- // Static routes
39
- for (const route of routes) {
40
- if (route.type === 'static' && route.path === pathname) {
41
- setCurrentRoute(route);
42
- setParams({});
43
- return;
44
- }
45
- }
46
- // Dynamic routes
47
- for (const route of routes) {
48
- if (route.type === 'dynamic') {
49
- const pattern = route.path.replace(/\\[([^\\]]+)\\]/g, '([^/]+)');
50
- const regex = new RegExp('^' + pattern + '$');
51
- const match = pathname.match(regex);
52
- if (match) {
53
- const paramNames = [...route.path.matchAll(/\\[([^\\]]+)\\]/g)].map(m => m[1]);
54
- const extractedParams = {};
55
- paramNames.forEach((name, i) => { extractedParams[name] = match[i + 1]; });
56
- setCurrentRoute(route);
57
- setParams(extractedParams);
58
- return;
59
- }
60
- }
61
- }
62
- setCurrentRoute(null);
63
- setParams({});
64
- }
65
-
66
- function navigate(path) {
67
- window.history.pushState({}, '', path);
68
- matchAndSetRoute(path);
69
- }
70
-
71
- const Component = currentRoute?.component;
72
- return React.createElement(
73
- RouterContext.Provider,
74
- { value: { currentRoute, params, navigate, pathname: window.location.pathname } },
75
- Component ? React.createElement(Component, { params }) : React.createElement(NotFound)
76
- );
77
- }
78
-
79
- export function Link({ to, children, ...props }) {
80
- const { navigate } = useRouter();
81
- return React.createElement('a', {
82
- href: to,
83
- onClick: (e) => { e.preventDefault(); navigate(to); },
84
- ...props
85
- }, children);
86
- }
87
-
88
- function NotFound() {
89
- return React.createElement('div', {
90
- style: { display: 'flex', flexDirection: 'column', alignItems: 'center',
91
- justifyContent: 'center', minHeight: '100vh', fontFamily: 'system-ui' }
92
- },
93
- React.createElement('h1', { style: { fontSize: '6rem', margin: 0 } }, '404'),
94
- React.createElement('p', { style: { fontSize: '1.5rem', color: '#666' } }, 'Page not found'),
95
- React.createElement('a', { href: '/', style: { color: '#10b981', textDecoration: 'none' } }, 'Go home')
96
- );
97
- }
98
-
99
- ${imports}
100
-
101
- export const routes = [
102
- ${routeConfigs}
103
- ];`;
104
- }
@@ -1,149 +0,0 @@
1
- // bertui/src/compiler/transform.js - NEW FILE
2
- // PURE JSX/TSX transformation function - NO FILE SYSTEM
3
-
4
- /**
5
- * Transform JSX/TSX code to JavaScript
6
- * @param {string} sourceCode - The source code to transform
7
- * @param {Object} options - Transformation options
8
- * @param {string} options.loader - 'jsx', 'tsx', 'ts', 'js' (default: 'tsx')
9
- * @param {string} options.env - 'development' or 'production' (default: 'development')
10
- * @param {boolean} options.addReactImport - Automatically add React import if missing (default: true)
11
- * @returns {Promise<string>} Transformed JavaScript code
12
- */
13
- export async function transformJSX(sourceCode, options = {}) {
14
- const {
15
- loader = 'tsx',
16
- env = 'development',
17
- addReactImport = true
18
- } = options;
19
-
20
- // Skip transformation if it's plain JS without JSX
21
- if (loader === 'js' && !sourceCode.includes('React.createElement') && !/<[A-Z]/.test(sourceCode)) {
22
- return sourceCode;
23
- }
24
-
25
- try {
26
- // Create Bun transpiler instance
27
- const transpiler = new Bun.Transpiler({
28
- loader,
29
- target: 'browser',
30
- define: {
31
- 'process.env.NODE_ENV': JSON.stringify(env)
32
- },
33
- tsconfig: {
34
- compilerOptions: {
35
- jsx: 'react',
36
- jsxFactory: 'React.createElement',
37
- jsxFragmentFactory: 'React.Fragment',
38
- target: 'ES2020',
39
- module: 'ESNext'
40
- }
41
- }
42
- });
43
-
44
- let transformed = await transpiler.transform(sourceCode);
45
-
46
- // Add React import if needed and not already present
47
- if (addReactImport &&
48
- !transformed.includes('import React') &&
49
- !transformed.includes('import * as React') &&
50
- (transformed.includes('React.createElement') || transformed.includes('jsx(') || transformed.includes('jsxs('))) {
51
- transformed = `import React from 'react';\n${transformed}`;
52
- }
53
-
54
- // Clean up any dev JSX references
55
- if (env === 'production') {
56
- transformed = transformed.replace(/jsxDEV/g, 'jsx');
57
- }
58
-
59
- return transformed;
60
-
61
- } catch (error) {
62
- throw new Error(`JSX transformation failed: ${error.message}`);
63
- }
64
- }
65
-
66
- /**
67
- * Synchronous version of transformJSX
68
- * Use only when you know the code is small and you need sync execution
69
- */
70
- export function transformJSXSync(sourceCode, options = {}) {
71
- const {
72
- loader = 'tsx',
73
- env = 'development',
74
- addReactImport = true
75
- } = options;
76
-
77
- try {
78
- const transpiler = new Bun.Transpiler({
79
- loader,
80
- target: 'browser',
81
- define: {
82
- 'process.env.NODE_ENV': JSON.stringify(env)
83
- }
84
- });
85
-
86
- let transformed = transpiler.transformSync(sourceCode);
87
-
88
- if (addReactImport &&
89
- !transformed.includes('import React') &&
90
- !transformed.includes('import * as React') &&
91
- (transformed.includes('React.createElement') || transformed.includes('jsx('))) {
92
- transformed = `import React from 'react';\n${transformed}`;
93
- }
94
-
95
- if (env === 'production') {
96
- transformed = transformed.replace(/jsxDEV/g, 'jsx');
97
- }
98
-
99
- return transformed;
100
-
101
- } catch (error) {
102
- throw new Error(`JSX transformation failed: ${error.message}`);
103
- }
104
- }
105
-
106
- /**
107
- * Check if code contains JSX syntax
108
- */
109
- export function containsJSX(code) {
110
- return code.includes('React.createElement') ||
111
- code.includes('React.Fragment') ||
112
- /<[A-Z]/.test(code) ||
113
- code.includes('jsx(') ||
114
- code.includes('jsxs(') ||
115
- /<[a-z][a-z0-9]*\s/.test(code);
116
- }
117
-
118
- /**
119
- * Remove CSS imports from code (for production builds)
120
- */
121
- export function removeCSSImports(code) {
122
- return code
123
- .replace(/import\s+['"][^'"]*\.css['"];?\s*/g, '')
124
- .replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
125
- }
126
-
127
- /**
128
- * Remove dotenv imports (for browser)
129
- */
130
- export function removeDotenvImports(code) {
131
- return code
132
- .replace(/import\s+\w+\s+from\s+['"]dotenv['"]\s*;?\s*/g, '')
133
- .replace(/import\s+\{[^}]+\}\s+from\s+['"]dotenv['"]\s*;?\s*/g, '')
134
- .replace(/\w+\.config\(\s*\)\s*;?\s*/g, '');
135
- }
136
-
137
- /**
138
- * Fix relative imports to include .js extension
139
- */
140
- export function fixRelativeImports(code) {
141
- const importRegex = /from\s+['"](\.\.?\/[^'"]+?)(?<!\.js|\.jsx|\.ts|\.tsx|\.json)['"]/g;
142
-
143
- return code.replace(importRegex, (match, path) => {
144
- if (path.endsWith('/') || /\.\w+$/.test(path)) {
145
- return match;
146
- }
147
- return `from '${path}.js'`;
148
- });
149
- }
@@ -1,37 +0,0 @@
1
- // bertui/src/config/defaultConfig.js
2
- export const defaultConfig = {
3
- siteName: "BertUI App",
4
- baseUrl: "http://localhost:3000",
5
-
6
- // importhow: alias → relative path from project root
7
- // Example:
8
- // importhow: {
9
- // amani: '../../components',
10
- // ui: '../../components/ui',
11
- // text: '../../utils/text',
12
- // }
13
- importhow: {},
14
-
15
- meta: {
16
- title: "BertUI - Lightning Fast React",
17
- description: "Build lightning-fast React applications with file-based routing powered by Bun",
18
- keywords: "react, bun, bertui, fast, file-based routing",
19
- author: "Pease Ernest",
20
- themeColor: "#667eea",
21
- lang: "en",
22
- ogTitle: "BertUI - Lightning Fast React Framework",
23
- ogDescription: "Build lightning-fast React apps with zero config",
24
- ogImage: "/og-image.png"
25
- },
26
-
27
- appShell: {
28
- loading: true,
29
- loadingText: "Loading...",
30
- backgroundColor: "#ffffff"
31
- },
32
-
33
- robots: {
34
- disallow: [],
35
- crawlDelay: null
36
- }
37
- };
@@ -1,2 +0,0 @@
1
- export { loadConfig } from './loadConfig.js';
2
- export { defaultConfig } from './defaultConfig.js';
@@ -1,64 +0,0 @@
1
- // bertui/src/config/loadConfig.js
2
- import { join } from 'path';
3
- import { existsSync } from 'fs';
4
- import { defaultConfig } from './defaultConfig.js';
5
- import logger from '../logger/logger.js';
6
-
7
- export async function loadConfig(root) {
8
- const configPath = join(root, 'bertui.config.js');
9
-
10
- if (!existsSync(configPath)) {
11
- logger.info('No config found, using defaults');
12
- return defaultConfig;
13
- }
14
-
15
- try {
16
- // Read and transpile the config file manually —
17
- // avoids Bun's dynamic import() build step which errors on plain JS configs
18
- const source = await Bun.file(configPath).text();
19
-
20
- const transpiler = new Bun.Transpiler({
21
- loader: 'js',
22
- target: 'bun',
23
- });
24
-
25
- let code = await transpiler.transform(source);
26
-
27
- // Strip any leftover 'export default' so we can eval it
28
- // and grab the value directly
29
- code = code.replace(/export\s+default\s+/, 'globalThis.__bertuiConfig = ');
30
-
31
- // Run it in the current context
32
- const fn = new Function('globalThis', code);
33
- fn(globalThis);
34
-
35
- const userConfig = globalThis.__bertuiConfig;
36
- delete globalThis.__bertuiConfig;
37
-
38
- if (!userConfig) {
39
- logger.warn('bertui.config.js did not export a default value, using defaults');
40
- return defaultConfig;
41
- }
42
-
43
- logger.success('Loaded bertui.config.js');
44
-
45
- logger.info(`📋 Config: importhow=${JSON.stringify(Object.keys(userConfig.importhow || {}))}`);
46
-
47
- return mergeConfig(defaultConfig, userConfig);
48
-
49
- } catch (error) {
50
- logger.error(`Failed to load bertui.config.js: ${error.message}`);
51
- return defaultConfig;
52
- }
53
- }
54
-
55
- function mergeConfig(defaults, user) {
56
- const merged = { ...user };
57
- merged.meta = { ...defaults.meta, ...(user.meta || {}) };
58
- merged.appShell = { ...defaults.appShell, ...(user.appShell || {}) };
59
- merged.robots = { ...defaults.robots, ...(user.robots || {}) };
60
- merged.importhow = { ...(defaults.importhow || {}), ...(user.importhow || {}) };
61
- if (!merged.siteName) merged.siteName = defaults.siteName;
62
- if (!merged.baseUrl) merged.baseUrl = defaults.baseUrl;
63
- return merged;
64
- }
Binary file
package/src/css/index.js DELETED
@@ -1,46 +0,0 @@
1
- // bertui/src/css/index.js - NEW FILE
2
- // PURE CSS processing - no server
3
-
4
- import { transform } from 'lightningcss';
5
- import logger from '../logger/logger.js';
6
-
7
- export async function minifyCSS(css, options = {}) {
8
- try {
9
- const { code } = transform({
10
- filename: options.filename || 'style.css',
11
- code: Buffer.from(css),
12
- minify: true,
13
- sourceMap: false,
14
- targets: {
15
- chrome: 90 << 16,
16
- firefox: 88 << 16,
17
- safari: 14 << 16,
18
- edge: 90 << 16
19
- },
20
- drafts: {
21
- nesting: true
22
- }
23
- });
24
- return code.toString();
25
- } catch (error) {
26
- logger.warn(`CSS minification failed: ${error.message}`);
27
- // Fallback minification
28
- return css
29
- .replace(/\/\*[\s\S]*?\*\//g, '')
30
- .replace(/\s+/g, ' ')
31
- .replace(/\s*([{}:;,])\s*/g, '$1')
32
- .replace(/;}/g, '}')
33
- .trim();
34
- }
35
- }
36
-
37
- export function combineCSS(files) {
38
- return files.map(({ filename, content }) =>
39
- `/* ${filename} */\n${content}`
40
- ).join('\n\n');
41
- }
42
-
43
-
44
- export { minifyCSS, minifyCSSSync, combineCSS, extractCSSImports, isCSSFile } from './processor.js';
45
- export { buildAllCSS } from '../build/processors/css-builder.js';
46
- export { buildCSS, copyCSS } from '../build/css-builder.js';
@@ -1,172 +0,0 @@
1
- // bertui/src/css/processor.js - PURE CSS PROCESSING
2
- import { transform } from 'lightningcss';
3
- import logger from '../logger/logger.js';
4
-
5
- /**
6
- * Minify CSS using Lightning CSS with fallback
7
- */
8
- export async function minifyCSS(css, options = {}) {
9
- const {
10
- filename = 'style.css',
11
- minify = true,
12
- sourceMap = false,
13
- targets = {
14
- chrome: 90 << 16,
15
- firefox: 88 << 16,
16
- safari: 14 << 16,
17
- edge: 90 << 16
18
- }
19
- } = options;
20
-
21
- // Empty CSS
22
- if (!css || css.trim() === '') {
23
- return '/* Empty CSS */';
24
- }
25
-
26
- try {
27
- const { code } = transform({
28
- filename,
29
- code: Buffer.from(css),
30
- minify,
31
- sourceMap,
32
- targets,
33
- drafts: {
34
- nesting: true
35
- }
36
- });
37
-
38
- return code.toString();
39
- } catch (error) {
40
- logger.warn(`Lightning CSS failed: ${error.message}, using fallback minifier`);
41
- return fallbackMinifyCSS(css);
42
- }
43
- }
44
-
45
- /**
46
- * Synchronous version for build scripts
47
- */
48
- export function minifyCSSSync(css, options = {}) {
49
- const {
50
- filename = 'style.css',
51
- minify = true,
52
- sourceMap = false
53
- } = options;
54
-
55
- if (!css || css.trim() === '') {
56
- return '/* Empty CSS */';
57
- }
58
-
59
- try {
60
- const { code } = transform({
61
- filename,
62
- code: Buffer.from(css),
63
- minify,
64
- sourceMap,
65
- drafts: {
66
- nesting: true
67
- }
68
- });
69
- return code.toString();
70
- } catch (error) {
71
- return fallbackMinifyCSS(css);
72
- }
73
- }
74
-
75
- /**
76
- * Combine multiple CSS files into one
77
- */
78
- export function combineCSS(files) {
79
- if (!Array.isArray(files)) {
80
- throw new Error('combineCSS expects an array of {filename, content}');
81
- }
82
-
83
- return files.map(({ filename, content }) => {
84
- // Add file comment for debugging
85
- const header = `/* ${filename} */\n`;
86
- return header + content;
87
- }).join('\n\n');
88
- }
89
-
90
- /**
91
- * Fallback CSS minifier (simple but works)
92
- */
93
- function fallbackMinifyCSS(css) {
94
- return css
95
- // Remove comments
96
- .replace(/\/\*[\s\S]*?\*\//g, '')
97
- // Remove whitespace
98
- .replace(/\s+/g, ' ')
99
- // Remove space around { } : ; ,
100
- .replace(/\s*([{}:;,])\s*/g, '$1')
101
- // Remove last semicolon before }
102
- .replace(/;}/g, '}')
103
- // Remove leading/trailing space
104
- .trim();
105
- }
106
-
107
- /**
108
- * Extract CSS imports from JavaScript
109
- */
110
- export function extractCSSImports(code) {
111
- const imports = [];
112
- const regex = /import\s+['"]([^'"]*\.css)['"];?/g;
113
- let match;
114
-
115
- while ((match = regex.exec(code)) !== null) {
116
- imports.push(match[1]);
117
- }
118
-
119
- return imports;
120
- }
121
-
122
- /**
123
- * Check if file is CSS
124
- */
125
- export function isCSSFile(filename) {
126
- return filename.toLowerCase().endsWith('.css');
127
- }
128
-
129
- // ============================================
130
- // OPTIONAL SCSS SUPPORT - COMMENTED OUT BY DEFAULT
131
- // Uncomment only if you install 'sass' package
132
- // ============================================
133
-
134
-
135
- export async function processSCSS(scssCode, options = {}) {
136
- try {
137
- // Dynamic import so it doesn't fail if sass isn't installed
138
- const sass = await import('sass').catch(() => {
139
- throw new Error('sass package not installed. Run: bun add sass');
140
- });
141
-
142
- const result = sass.compileString(scssCode, {
143
- style: options.compressed ? 'compressed' : 'expanded',
144
- sourceMap: false,
145
- loadPaths: options.loadPaths || []
146
- });
147
-
148
- return result.css;
149
- } catch (error) {
150
- logger.error(`SCSS compilation failed: ${error.message}`);
151
- throw error;
152
- }
153
- }
154
-
155
- export async function compileSCSSFile(filePath, options = {}) {
156
- try {
157
- const sass = await import('sass').catch(() => {
158
- throw new Error('sass package not installed. Run: bun add sass');
159
- });
160
-
161
- const result = sass.compile(filePath, {
162
- style: options.compressed ? 'compressed' : 'expanded',
163
- sourceMap: false,
164
- loadPaths: options.loadPaths || [require('path').dirname(filePath)]
165
- });
166
-
167
- return result.css;
168
- } catch (error) {
169
- logger.error(`SCSS file compilation failed: ${error.message}`);
170
- throw error;
171
- }
172
- }
package/src/dev.js DELETED
@@ -1,68 +0,0 @@
1
- // bertui/src/dev.js
2
- import { compileProject } from './client/compiler.js';
3
- import { startDevServer } from './server/dev-server.js';
4
- import { MiddlewareManager } from './middleware/index.js';
5
- import { compileLayouts } from './layouts/index.js';
6
- import { compileLoadingComponents } from './loading/index.js';
7
- import { analyzeRoutes, logHydrationReport } from './hydration/index.js';
8
- import logger from './logger/logger.js';
9
- import { loadConfig } from './config/loadConfig.js';
10
-
11
- const TOTAL_STEPS = 6;
12
-
13
- export async function startDev(options = {}) {
14
- const root = options.root || process.cwd();
15
- const port = options.port || 3000;
16
-
17
- logger.printHeader('DEV');
18
-
19
- try {
20
- const config = await loadConfig(root);
21
-
22
- // ── Step 1: Compile ──────────────────────────────────────────────────────
23
- logger.step(1, TOTAL_STEPS, 'Compiling');
24
- const { routes, outDir } = await compileProject(root);
25
- logger.stepDone('Compiling', `${routes.length} routes`);
26
-
27
- // ── Step 2: Layouts ──────────────────────────────────────────────────────
28
- logger.step(2, TOTAL_STEPS, 'Layouts');
29
- const layouts = await compileLayouts(root, outDir);
30
- const layoutCount = Object.keys(layouts).length;
31
- logger.stepDone('Layouts', layoutCount > 0 ? `${layoutCount} found` : 'none');
32
-
33
- // ── Step 3: Loading states ───────────────────────────────────────────────
34
- logger.step(3, TOTAL_STEPS, 'Loading states');
35
- const loadingComponents = await compileLoadingComponents(root, outDir);
36
- logger.stepDone('Loading states');
37
-
38
- // ── Step 4: Hydration analysis ───────────────────────────────────────────
39
- logger.step(4, TOTAL_STEPS, 'Hydration analysis');
40
- if (routes && routes.length > 0) {
41
- const analyzedRoutes = await analyzeRoutes(routes);
42
- logger.stepDone('Hydration analysis',
43
- `${analyzedRoutes.interactive.length} interactive · ${analyzedRoutes.static.length} static`);
44
- } else {
45
- logger.stepDone('Hydration analysis', 'no routes');
46
- }
47
-
48
- // ── Step 5: Middleware ───────────────────────────────────────────────────
49
- logger.step(5, TOTAL_STEPS, 'Middleware');
50
- const middlewareManager = new MiddlewareManager(root);
51
- await middlewareManager.load();
52
- middlewareManager.watch();
53
- logger.stepDone('Middleware');
54
-
55
- // ── Step 6: Dev server ───────────────────────────────────────────────────
56
- logger.step(6, TOTAL_STEPS, 'Starting server');
57
- await startDevServer({ root, port, middleware: middlewareManager, layouts, loadingComponents });
58
- logger.stepDone('Starting server', `http://localhost:${port}`);
59
-
60
- // ── Ready ────────────────────────────────────────────────────────────────
61
- process.stdout.write(`\n ${'\x1b[1m'}\x1b[32m▶ Ready on http://localhost:${port}\x1b[0m\n\n`);
62
-
63
- } catch (error) {
64
- logger.stepFail('Dev server', error.message);
65
- logger.error(error.stack || error.message);
66
- process.exit(1);
67
- }
68
- }