elit 1.0.0 ā 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.
- package/LICENSE +21 -0
- package/README.md +552 -19
- package/dist/build.d.mts +11 -0
- package/dist/build.d.ts +11 -0
- package/dist/build.js +1 -0
- package/dist/build.mjs +1 -0
- package/dist/cli.js +2307 -0
- package/dist/client.d.mts +9 -0
- package/dist/client.d.ts +9 -0
- package/dist/client.js +1 -0
- package/dist/client.mjs +1 -0
- package/dist/dom.d.mts +80 -0
- package/dist/dom.d.ts +80 -0
- package/dist/dom.js +1 -0
- package/dist/dom.mjs +1 -0
- package/dist/el.d.mts +227 -0
- package/dist/el.d.ts +227 -0
- package/dist/el.js +1 -0
- package/dist/el.mjs +1 -0
- package/dist/hmr.d.mts +38 -0
- package/dist/hmr.d.ts +38 -0
- package/dist/hmr.js +1 -0
- package/dist/hmr.mjs +1 -0
- package/dist/index.d.mts +38 -490
- package/dist/index.d.ts +38 -490
- package/dist/index.js +1 -2266
- package/dist/index.mjs +1 -2039
- package/dist/router.d.mts +45 -0
- package/dist/router.d.ts +45 -0
- package/dist/router.js +1 -0
- package/dist/router.mjs +1 -0
- package/dist/server.d.mts +3 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +1 -0
- package/dist/server.mjs +1 -0
- package/dist/state.d.mts +109 -0
- package/dist/state.d.ts +109 -0
- package/dist/state.js +1 -0
- package/dist/state.mjs +1 -0
- package/dist/style.d.mts +113 -0
- package/dist/style.d.ts +113 -0
- package/dist/style.js +1 -0
- package/dist/style.mjs +1 -0
- package/dist/types-DOAdFFJB.d.mts +330 -0
- package/dist/types-DOAdFFJB.d.ts +330 -0
- package/dist/types.d.mts +3 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +1 -0
- package/dist/types.mjs +0 -0
- package/package.json +77 -7
- package/dist/index.global.js +0 -2064
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Elit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
# Elit
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
ā” A full-stack TypeScript framework (~10KB gzipped) with built-in dev server, HMR, build tool, and REST API. Zero dependencies, maximum productivity.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/elit)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://bundlephobia.com/package/elit)
|
|
8
|
+
|
|
9
|
+
> **Quick Links:** [Installation](#installation) | [Features](#features) | [Quick Start](#quick-start) | [CLI Tools](#cli-tools) | [API](#api) | [Deployment](#deployment)
|
|
7
10
|
|
|
8
11
|
## Why Elit?
|
|
9
12
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
13
|
+
- **šÆ Tiny Bundle Size**: Only ~10KB gzipped (30KB minified) - no framework bloat
|
|
14
|
+
- **š¦ Zero Dependencies**: Pure TypeScript, no external dependencies
|
|
15
|
+
- **ā” Lightning Fast**: Direct DOM manipulation - no virtual DOM overhead
|
|
16
|
+
- **š· TypeScript First**: Full type safety and IntelliSense out of the box
|
|
17
|
+
- **š Reactive State**: Simple but powerful reactive state management
|
|
18
|
+
- **š² Tree-Shakeable**: Import only what you need for optimal bundle size
|
|
19
|
+
- **š Full-Stack Ready**: Built-in dev server, HMR, build tool, and REST API
|
|
20
|
+
- **š„ Hot Module Replacement**: Instant development feedback with automatic HMR
|
|
21
|
+
- **šļø Build System**: Integrated esbuild with automatic client/server separation
|
|
22
|
+
- **š REST API Router**: Built-in server-side routing with middleware stack
|
|
23
|
+
- **š WebSocket Support**: Real-time state synchronization out of the box
|
|
24
|
+
- **šØ Developer Experience**: CLI tools, zero config, and excellent tooling support
|
|
16
25
|
|
|
17
26
|
## Installation
|
|
18
27
|
|
|
@@ -20,33 +29,175 @@ A lightweight, zero-dependency library for building reactive web applications wi
|
|
|
20
29
|
npm install elit
|
|
21
30
|
```
|
|
22
31
|
|
|
32
|
+
## CLI Tools
|
|
33
|
+
|
|
34
|
+
Elit includes a powerful CLI for development and production:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Development server with HMR
|
|
38
|
+
npx elit dev
|
|
39
|
+
|
|
40
|
+
# Production build
|
|
41
|
+
npx elit build
|
|
42
|
+
|
|
43
|
+
# Preview production build
|
|
44
|
+
npx elit preview
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Configuration
|
|
48
|
+
|
|
49
|
+
Create `elit.config.mjs` (or .ts, .js, .json) in your project root:
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
import { defineConfig } from 'elit';
|
|
53
|
+
import { resolve } from 'path';
|
|
54
|
+
|
|
55
|
+
export default defineConfig({
|
|
56
|
+
dev: {
|
|
57
|
+
port: 3000,
|
|
58
|
+
host: 'localhost',
|
|
59
|
+
root: './src',
|
|
60
|
+
basePath: '/',
|
|
61
|
+
open: true
|
|
62
|
+
},
|
|
63
|
+
build: {
|
|
64
|
+
entry: './src/main.ts',
|
|
65
|
+
outDir: './dist',
|
|
66
|
+
format: 'esm',
|
|
67
|
+
minify: true,
|
|
68
|
+
platform: 'browser',
|
|
69
|
+
basePath: '/app',
|
|
70
|
+
copy: [
|
|
71
|
+
{
|
|
72
|
+
from: 'index.html',
|
|
73
|
+
to: 'index.html',
|
|
74
|
+
transform: (content, config) => {
|
|
75
|
+
// Inject base tag from basePath
|
|
76
|
+
return content;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
preview: {
|
|
82
|
+
port: 4173,
|
|
83
|
+
root: './dist',
|
|
84
|
+
basePath: '/app'
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
23
89
|
## Features
|
|
24
90
|
|
|
25
|
-
|
|
91
|
+
### Frontend Framework
|
|
92
|
+
|
|
93
|
+
- šÆ **Ultra Lightweight**: Just 30KB minified, ~10KB gzipped
|
|
26
94
|
- ā” **Reactive State**: Built-in reactive state management with `createState`
|
|
27
95
|
- š **Computed Values**: Automatic dependency tracking with `computed`
|
|
28
96
|
- šØ **CSS-in-JS**: Type-safe styling with `CreateStyle`
|
|
29
97
|
- š£ļø **Client-Side Router**: Hash and history mode routing with dynamic parameters
|
|
30
98
|
- š± **Virtual Scrolling**: Handle 100k+ items efficiently
|
|
31
|
-
- š„ļø **SSR Support**:
|
|
32
|
-
- š **SVG & MathML**:
|
|
33
|
-
- š§ **Utilities**: Throttle, debounce,
|
|
34
|
-
- š¦ **Tree-
|
|
99
|
+
- š„ļø **SSR Support**: Full server-side rendering capabilities
|
|
100
|
+
- š **SVG & MathML**: Complete support for all elements
|
|
101
|
+
- š§ **Performance Utilities**: Throttle, debounce, batch rendering
|
|
102
|
+
- š¦ **Tree-Shakeable**: Import only what you need
|
|
103
|
+
- š® **DOM Utilities**: Convenient helper functions
|
|
104
|
+
|
|
105
|
+
### Full-Stack Tools
|
|
106
|
+
|
|
107
|
+
- š„ **Hot Module Replacement**: Instant development feedback
|
|
108
|
+
- šļø **Build System**: esbuild integration with automatic client/server separation
|
|
109
|
+
- š **REST API Router**: Server-side routing with middleware stack
|
|
110
|
+
- š§ **Middleware**: CORS, logging, error handling, rate limiting, compression, security
|
|
111
|
+
- š **Shared State**: Real-time WebSocket state synchronization
|
|
112
|
+
- š **WebSocket Support**: Built-in WebSocket server
|
|
113
|
+
- š **Static File Server**: Gzip compression and cache headers
|
|
114
|
+
- šÆ **Zero Config**: Works out of the box with sensible defaults
|
|
115
|
+
- š **Environment Variables**: Support for .env files with VITE_ prefix
|
|
35
116
|
|
|
36
117
|
## Quick Start
|
|
37
118
|
|
|
119
|
+
### 1. Create Your Project
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Create a new directory
|
|
123
|
+
mkdir my-elit-app
|
|
124
|
+
cd my-elit-app
|
|
125
|
+
|
|
126
|
+
# Initialize package.json
|
|
127
|
+
npm init -y
|
|
128
|
+
|
|
129
|
+
# Install Elit
|
|
130
|
+
npm install elit
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 2. Create Your App
|
|
134
|
+
|
|
135
|
+
Create `src/main.ts`:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { div, h1, button, createState, reactive, domNode } from 'elit';
|
|
139
|
+
|
|
140
|
+
const count = createState(0);
|
|
141
|
+
|
|
142
|
+
const app = div({ className: 'app' },
|
|
143
|
+
h1('Hello Elit! š'),
|
|
144
|
+
reactive(count, (value) =>
|
|
145
|
+
button({
|
|
146
|
+
onclick: () => count.value++,
|
|
147
|
+
className: 'btn'
|
|
148
|
+
}, `Count: ${value}`)
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
domNode.render('#app', app);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Create `index.html`:
|
|
156
|
+
|
|
157
|
+
```html
|
|
158
|
+
<!DOCTYPE html>
|
|
159
|
+
<html lang="en">
|
|
160
|
+
<head>
|
|
161
|
+
<meta charset="UTF-8">
|
|
162
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
163
|
+
<title>Elit App</title>
|
|
164
|
+
</head>
|
|
165
|
+
<body>
|
|
166
|
+
<div id="app"></div>
|
|
167
|
+
<script type="module" src="src/main.ts"></script>
|
|
168
|
+
</body>
|
|
169
|
+
</html>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 3. Start Development Server
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx elit dev
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Your app will automatically reload when you make changes with HMR!
|
|
179
|
+
|
|
180
|
+
### NPM Installation
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npm install elit
|
|
184
|
+
```
|
|
185
|
+
|
|
38
186
|
```typescript
|
|
39
187
|
import { div, h1, p, button, createState, reactive, domNode } from 'elit';
|
|
40
188
|
|
|
41
189
|
// Create reactive state
|
|
42
190
|
const count = createState(0);
|
|
43
191
|
|
|
44
|
-
// Create elements
|
|
192
|
+
// Create elements with reactive updates
|
|
45
193
|
const app = div({ className: 'app' },
|
|
46
|
-
h1('Hello Elit!'),
|
|
47
|
-
p('A lightweight DOM library'),
|
|
194
|
+
h1('Hello Elit! š'),
|
|
195
|
+
p('A lightweight, reactive DOM library'),
|
|
48
196
|
reactive(count, (value) =>
|
|
49
|
-
button({
|
|
197
|
+
button({
|
|
198
|
+
onclick: () => count.value++,
|
|
199
|
+
className: 'btn-primary'
|
|
200
|
+
}, `Count: ${value}`)
|
|
50
201
|
)
|
|
51
202
|
);
|
|
52
203
|
|
|
@@ -54,6 +205,33 @@ const app = div({ className: 'app' },
|
|
|
54
205
|
domNode.render('#app', app);
|
|
55
206
|
```
|
|
56
207
|
|
|
208
|
+
### CDN Usage
|
|
209
|
+
|
|
210
|
+
```html
|
|
211
|
+
<!DOCTYPE html>
|
|
212
|
+
<html>
|
|
213
|
+
<head>
|
|
214
|
+
<script src="https://unpkg.com/elit@latest/dist/index.global.js"></script>
|
|
215
|
+
</head>
|
|
216
|
+
<body>
|
|
217
|
+
<div id="app"></div>
|
|
218
|
+
<script>
|
|
219
|
+
const { div, h1, button, createState, reactive, domNode } = window;
|
|
220
|
+
|
|
221
|
+
const count = createState(0);
|
|
222
|
+
const app = div(
|
|
223
|
+
h1('Hello from CDN!'),
|
|
224
|
+
reactive(count, value =>
|
|
225
|
+
button({ onclick: () => count.value++ }, `Count: ${value}`)
|
|
226
|
+
)
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
domNode.render('#app', app);
|
|
230
|
+
</script>
|
|
231
|
+
</body>
|
|
232
|
+
</html>
|
|
233
|
+
```
|
|
234
|
+
|
|
57
235
|
## API
|
|
58
236
|
|
|
59
237
|
### Element Factories
|
|
@@ -105,6 +283,134 @@ const label = text(message);
|
|
|
105
283
|
const inputEl = input({ type: 'text', ...bindValue(message) });
|
|
106
284
|
```
|
|
107
285
|
|
|
286
|
+
### Shared State (Real-time Sync)
|
|
287
|
+
|
|
288
|
+
**Requires `elit-server`** - Shared state syncs automatically between backend and frontend via WebSocket:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { createSharedState, reactive } from 'elit';
|
|
292
|
+
|
|
293
|
+
// Create shared state (auto-connects to elit-server)
|
|
294
|
+
const counter = createSharedState('counter', 0);
|
|
295
|
+
const todos = createSharedState('todos', []);
|
|
296
|
+
|
|
297
|
+
// Use with reactive rendering
|
|
298
|
+
const app = div(
|
|
299
|
+
reactive(counter.state, value =>
|
|
300
|
+
div(`Counter: ${value}`)
|
|
301
|
+
),
|
|
302
|
+
button({ onclick: () => counter.value++ }, 'Increment')
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// Listen to changes
|
|
306
|
+
counter.onChange((newValue, oldValue) => {
|
|
307
|
+
console.log(`${oldValue} ā ${newValue}`);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Update from any client - syncs to all
|
|
311
|
+
counter.value++;
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Backend (Node.js with elit-server):**
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
const { createDevServer } = require('elit-server');
|
|
318
|
+
|
|
319
|
+
const server = createDevServer({ port: 3000 });
|
|
320
|
+
|
|
321
|
+
// Create matching shared states
|
|
322
|
+
const counter = server.state.create('counter', { initial: 0 });
|
|
323
|
+
const todos = server.state.create('todos', { initial: [] });
|
|
324
|
+
|
|
325
|
+
// Listen to changes
|
|
326
|
+
counter.onChange((newValue, oldValue) => {
|
|
327
|
+
console.log(`Counter: ${oldValue} ā ${newValue}`);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Update from backend - syncs to all clients
|
|
331
|
+
counter.value++;
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### elit-server - Development Server
|
|
335
|
+
|
|
336
|
+
Full-featured development server with HMR, REST API, and real-time features:
|
|
337
|
+
|
|
338
|
+
```javascript
|
|
339
|
+
const { createDevServer, Router, cors, logger } = require('elit-server');
|
|
340
|
+
|
|
341
|
+
// Create REST API router
|
|
342
|
+
const api = new Router();
|
|
343
|
+
|
|
344
|
+
// Add middleware
|
|
345
|
+
api.use(cors());
|
|
346
|
+
api.use(logger());
|
|
347
|
+
|
|
348
|
+
// Define routes
|
|
349
|
+
api.get('/api/users', (ctx) => {
|
|
350
|
+
return { success: true, users: [...] };
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
api.post('/api/users', (ctx) => {
|
|
354
|
+
const user = ctx.body;
|
|
355
|
+
return { success: true, user };
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Create server with API
|
|
359
|
+
const server = createDevServer({
|
|
360
|
+
port: 3000,
|
|
361
|
+
root: __dirname,
|
|
362
|
+
api,
|
|
363
|
+
logging: true
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// Access shared state
|
|
367
|
+
const counter = server.state.create('counter', {
|
|
368
|
+
initial: 0,
|
|
369
|
+
validate: (value) => typeof value === 'number'
|
|
370
|
+
});
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**CLI Usage:**
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Start dev server
|
|
377
|
+
npx elit-dev
|
|
378
|
+
|
|
379
|
+
# Custom port
|
|
380
|
+
npx elit-dev --port 8080
|
|
381
|
+
|
|
382
|
+
# Custom root directory
|
|
383
|
+
npx elit-dev --root ./public
|
|
384
|
+
|
|
385
|
+
# Disable auto-open browser
|
|
386
|
+
npx elit-dev --no-open
|
|
387
|
+
|
|
388
|
+
# Silent mode
|
|
389
|
+
npx elit-dev --silent
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Middleware:**
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
const {
|
|
396
|
+
cors, // CORS headers
|
|
397
|
+
logger, // Request logging
|
|
398
|
+
errorHandler, // Error handling
|
|
399
|
+
rateLimit, // Rate limiting
|
|
400
|
+
bodyLimit, // Request body size limit
|
|
401
|
+
cacheControl, // Cache headers
|
|
402
|
+
compress, // Gzip compression
|
|
403
|
+
security // Security headers
|
|
404
|
+
} = require('elit-server');
|
|
405
|
+
|
|
406
|
+
api.use(cors({ origin: '*' }));
|
|
407
|
+
api.use(logger());
|
|
408
|
+
api.use(rateLimit({ max: 100, window: 60000 }));
|
|
409
|
+
api.use(bodyLimit(1024 * 1024)); // 1MB
|
|
410
|
+
api.use(compress());
|
|
411
|
+
api.use(security());
|
|
412
|
+
```
|
|
413
|
+
|
|
108
414
|
### Server-Side Rendering
|
|
109
415
|
|
|
110
416
|
```typescript
|
|
@@ -232,6 +538,27 @@ addLink({ rel: 'stylesheet', href: '/styles.css' });
|
|
|
232
538
|
addStyle('body { margin: 0; }');
|
|
233
539
|
```
|
|
234
540
|
|
|
541
|
+
### DOM Utilities
|
|
542
|
+
|
|
543
|
+
Elit provides convenient DOM utility functions for common operations:
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
import { doc, el, els, createEl, elId, elClass, fragment } from 'elit';
|
|
547
|
+
|
|
548
|
+
// Query selectors (bound to document)
|
|
549
|
+
const element = el('.my-class'); // querySelector
|
|
550
|
+
const elements = els('.my-class'); // querySelectorAll
|
|
551
|
+
const byId = elId('my-id'); // getElementById
|
|
552
|
+
const byClass = elClass('my-class'); // getElementsByClassName
|
|
553
|
+
|
|
554
|
+
// Create elements
|
|
555
|
+
const div = createEl('div'); // createElement
|
|
556
|
+
const frag = fragment(); // createDocumentFragment
|
|
557
|
+
|
|
558
|
+
// Access document object
|
|
559
|
+
doc.title = 'New Title';
|
|
560
|
+
```
|
|
561
|
+
|
|
235
562
|
## Available Elements
|
|
236
563
|
|
|
237
564
|
### HTML Elements (100+)
|
|
@@ -265,6 +592,25 @@ All MathML elements are prefixed with `math`:
|
|
|
265
592
|
|
|
266
593
|
`mathMath`, `mathMi`, `mathMn`, `mathMo`, `mathMfrac`, `mathMsqrt`, `mathMroot`, `mathMsup`, `mathMsub`, `mathMsubsup`, `mathMover`, `mathMunder`, `mathMunderover`, and more.
|
|
267
594
|
|
|
595
|
+
## Bundle Size & Performance
|
|
596
|
+
|
|
597
|
+
Elit is designed to be extremely lightweight while providing powerful features:
|
|
598
|
+
|
|
599
|
+
| Format | Size (Minified) | Size (Gzipped) |
|
|
600
|
+
|--------|----------------|----------------|
|
|
601
|
+
| ESM | 29KB | ~10KB |
|
|
602
|
+
| CJS | 30KB | ~10KB |
|
|
603
|
+
| IIFE | 30KB | ~10KB |
|
|
604
|
+
|
|
605
|
+
**Tree-shaking**: When using ES modules, only the features you import will be included in your bundle.
|
|
606
|
+
|
|
607
|
+
**Performance Optimizations**:
|
|
608
|
+
- Direct DOM manipulation (no virtual DOM diffing)
|
|
609
|
+
- Optimized rendering with RAF batching
|
|
610
|
+
- Smart children rendering with automatic fragment usage
|
|
611
|
+
- Efficient attribute updates using charCode checks
|
|
612
|
+
- Minimal function closures and memory allocation
|
|
613
|
+
|
|
268
614
|
## Browser Usage
|
|
269
615
|
|
|
270
616
|
When loaded via script tag, all exports are available on the `window` object:
|
|
@@ -273,7 +619,7 @@ When loaded via script tag, all exports are available on the `window` object:
|
|
|
273
619
|
<script src="https://unpkg.com/elit@latest/dist/index.global.js"></script>
|
|
274
620
|
<script>
|
|
275
621
|
const { div, span, createState, domNode } = window;
|
|
276
|
-
// or use DomLib global
|
|
622
|
+
// or use DomLib global namespace
|
|
277
623
|
const app = DomLib.div('Hello');
|
|
278
624
|
</script>
|
|
279
625
|
```
|
|
@@ -335,14 +681,201 @@ const Counter = div(
|
|
|
335
681
|
);
|
|
336
682
|
```
|
|
337
683
|
|
|
684
|
+
## TypeScript Support
|
|
685
|
+
|
|
686
|
+
Elit is written in TypeScript and provides excellent type safety:
|
|
687
|
+
|
|
688
|
+
```typescript
|
|
689
|
+
import { VNode, State, Props } from 'elit';
|
|
690
|
+
|
|
691
|
+
// Type-safe element creation
|
|
692
|
+
const props: Props = {
|
|
693
|
+
className: 'container',
|
|
694
|
+
onclick: (e: MouseEvent) => console.log(e)
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
// Type-safe state
|
|
698
|
+
const count: State<number> = createState(0);
|
|
699
|
+
const users: State<User[]> = createState([]);
|
|
700
|
+
|
|
701
|
+
// Full IntelliSense support for all 100+ HTML elements
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
## Deployment
|
|
705
|
+
|
|
706
|
+
Deploy your Elit application to production:
|
|
707
|
+
|
|
708
|
+
### Build for Production
|
|
709
|
+
|
|
710
|
+
```bash
|
|
711
|
+
# Build your app
|
|
712
|
+
npx elit build
|
|
713
|
+
|
|
714
|
+
# Preview production build
|
|
715
|
+
npx elit preview
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### Deploy to Vercel
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
npm i -g vercel
|
|
722
|
+
npm run build
|
|
723
|
+
vercel --prod
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
### Deploy to Netlify
|
|
727
|
+
|
|
728
|
+
```bash
|
|
729
|
+
npm i -g netlify-cli
|
|
730
|
+
npm run build
|
|
731
|
+
netlify deploy --prod --dir=dist
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
### Deploy to GitHub Pages
|
|
735
|
+
|
|
736
|
+
Create `.github/workflows/deploy.yml`:
|
|
737
|
+
|
|
738
|
+
```yaml
|
|
739
|
+
name: Deploy to GitHub Pages
|
|
740
|
+
|
|
741
|
+
on:
|
|
742
|
+
push:
|
|
743
|
+
branches: [main]
|
|
744
|
+
|
|
745
|
+
jobs:
|
|
746
|
+
deploy:
|
|
747
|
+
runs-on: ubuntu-latest
|
|
748
|
+
steps:
|
|
749
|
+
- uses: actions/checkout@v3
|
|
750
|
+
- uses: actions/setup-node@v3
|
|
751
|
+
with:
|
|
752
|
+
node-version: 18
|
|
753
|
+
- run: npm install
|
|
754
|
+
- run: npm run build
|
|
755
|
+
- uses: peaceiris/actions-gh-pages@v3
|
|
756
|
+
with:
|
|
757
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
758
|
+
publish_dir: ./dist
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### Docker Deployment
|
|
762
|
+
|
|
763
|
+
```dockerfile
|
|
764
|
+
FROM node:18-alpine AS builder
|
|
765
|
+
WORKDIR /app
|
|
766
|
+
COPY package*.json ./
|
|
767
|
+
RUN npm install
|
|
768
|
+
COPY . .
|
|
769
|
+
RUN npm run build
|
|
770
|
+
|
|
771
|
+
FROM nginx:alpine
|
|
772
|
+
COPY --from=builder /app/dist /usr/share/nginx/html
|
|
773
|
+
EXPOSE 80
|
|
774
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
### Environment Variables
|
|
778
|
+
|
|
779
|
+
Create `.env.production`:
|
|
780
|
+
|
|
781
|
+
```env
|
|
782
|
+
VITE_API_URL=https://api.example.com
|
|
783
|
+
VITE_ENV=production
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
Access in your code:
|
|
787
|
+
|
|
788
|
+
```typescript
|
|
789
|
+
const apiUrl = import.meta.env.VITE_API_URL;
|
|
790
|
+
const isProd = import.meta.env.PROD;
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
## Comparison with Other Frameworks
|
|
794
|
+
|
|
795
|
+
| Feature | Elit | Vite + React | Next.js | SvelteKit |
|
|
796
|
+
|---------|----------|--------------|---------|-----------|
|
|
797
|
+
| Bundle Size | 30KB | ~140KB+ | ~200KB+ | ~15KB* |
|
|
798
|
+
| Zero Dependencies | ā
| ā | ā | ā |
|
|
799
|
+
| Dev Server | ā
Built-in | ā
Vite | ā
Built-in | ā
Built-in |
|
|
800
|
+
| HMR | ā
| ā
| ā
| ā
|
|
|
801
|
+
| Build Tool | ā
Built-in | ā
Vite | ā
Built-in | ā
Built-in |
|
|
802
|
+
| REST API | ā
Built-in | ā | ā
| ā
|
|
|
803
|
+
| TypeScript | ā
| ā
| ā
| ā
|
|
|
804
|
+
| SSR | ā
| ā | ā
| ā
|
|
|
805
|
+
| Learning Curve | Easy | Medium | Medium | Easy |
|
|
806
|
+
|
|
807
|
+
*Svelte requires compilation
|
|
808
|
+
|
|
338
809
|
## Documentation
|
|
339
810
|
|
|
340
|
-
|
|
811
|
+
- š [Full Documentation](https://github.com/oangsa/elit/docs)
|
|
812
|
+
- ā” [Quick Start Guide](./docs/QUICK_START.md)
|
|
813
|
+
- š [API Reference](./docs/API.md)
|
|
814
|
+
- š [Migration Guide](./docs/MIGRATION.md)
|
|
815
|
+
- š¤ [Contributing Guide](./CONTRIBUTING.md)
|
|
816
|
+
|
|
817
|
+
## Changelog
|
|
818
|
+
|
|
819
|
+
### Elit - Full-Stack Framework
|
|
820
|
+
|
|
821
|
+
**Major Changes:**
|
|
822
|
+
- š **Integrated Build System**: Built-in esbuild with automatic client/server code separation
|
|
823
|
+
- š„ **CLI Tools**: New commands - `npx elit dev`, `npx elit build`, `npx elit preview`
|
|
824
|
+
- šļø **Zero Config**: Works out of the box with optional `elit.config.mjs`
|
|
825
|
+
- š **REST API Router**: Server-side routing with full middleware stack
|
|
826
|
+
- š **Shared State**: Real-time WebSocket state synchronization
|
|
827
|
+
- šÆ **basePath Support**: Configure base paths for subdirectory deployments
|
|
828
|
+
- š **Environment Variables**: .env file support with VITE_ prefix
|
|
829
|
+
- š¦ **Gzip Compression**: Automatic compression for production builds
|
|
830
|
+
- š¾ **Cache Headers**: Smart caching for static assets
|
|
831
|
+
- ā” **Hot Module Replacement**: Instant development feedback
|
|
832
|
+
|
|
833
|
+
**Core Library:**
|
|
834
|
+
- šÆ Ultra lightweight (~10KB gzipped)
|
|
835
|
+
- ā” Reactive state management
|
|
836
|
+
- šØ CSS-in-JS with CreateStyle
|
|
837
|
+
- š£ļø Client-side router
|
|
838
|
+
- š± Virtual scrolling
|
|
839
|
+
- š„ļø SSR support
|
|
840
|
+
- š 100+ HTML, SVG, and MathML elements
|
|
841
|
+
- š§ Performance utilities
|
|
842
|
+
- š¦ Tree-shakeable ES modules
|
|
843
|
+
|
|
844
|
+
## Examples
|
|
845
|
+
|
|
846
|
+
Example applications demonstrating Elit features:
|
|
847
|
+
|
|
848
|
+
- š **[Documentation Site](./docs)** - Full-featured docs site with i18n and blog
|
|
849
|
+
- šÆ **[Counter App](./examples/counter)** - Simple reactive counter
|
|
850
|
+
- ā
**[Todo App](./examples/todo)** - Todo list with state management
|
|
851
|
+
- šØ **[Styled Components](./examples/styled)** - CSS-in-JS examples
|
|
852
|
+
|
|
853
|
+
[View all examples ā](./examples)
|
|
854
|
+
|
|
855
|
+
## Links
|
|
856
|
+
|
|
857
|
+
- š¦ [npm - elit](https://www.npmjs.com/package/elit)
|
|
858
|
+
- š¦ [npm - elit-server](https://www.npmjs.com/package/elit-server)
|
|
859
|
+
- š [GitHub Repository](https://github.com/oangsa/elit)
|
|
860
|
+
- š Documentation (coming soon)
|
|
861
|
+
- š¬ Discord Community (coming soon)
|
|
341
862
|
|
|
342
863
|
## Contributing
|
|
343
864
|
|
|
344
865
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
345
866
|
|
|
867
|
+
1. Fork the repository
|
|
868
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
869
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
870
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
871
|
+
5. Open a Pull Request
|
|
872
|
+
|
|
346
873
|
## License
|
|
347
874
|
|
|
348
|
-
MIT
|
|
875
|
+
MIT License - see [LICENSE](./LICENSE) for details
|
|
876
|
+
|
|
877
|
+
---
|
|
878
|
+
|
|
879
|
+
**Built with ā¤ļø for modern web development**
|
|
880
|
+
|
|
881
|
+
*Elit - Lightweight, Reactive, Powerful* š
|
package/dist/build.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { B as BuildOptions, q as BuildResult } from './types-DOAdFFJB.mjs';
|
|
2
|
+
import 'http';
|
|
3
|
+
import 'ws';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build module for bundling applications
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
declare function build(options: BuildOptions): Promise<BuildResult>;
|
|
10
|
+
|
|
11
|
+
export { BuildOptions, BuildResult, build };
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { B as BuildOptions, q as BuildResult } from './types-DOAdFFJB.js';
|
|
2
|
+
import 'http';
|
|
3
|
+
import 'ws';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build module for bundling applications
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
declare function build(options: BuildOptions): Promise<BuildResult>;
|
|
10
|
+
|
|
11
|
+
export { BuildOptions, BuildResult, build };
|
package/dist/build.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("esbuild"),t=require("fs"),o=require("path"),n={outDir:"dist",minify:!0,sourcemap:!1,target:"es2020",format:"esm",treeshake:!0,logging:!0,external:[]};function i(e){if(0===e)return"0 B";let t=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,t)).toFixed(2))+" "+["B","KB","MB","GB"][t]}exports.build=async function(r){let l={...n,...r},s=Date.now();if(!l.entry)throw new Error("Entry file is required");let a=o.resolve(l.entry),c=o.resolve(l.outDir),g=l.outFile;if(!g){g=o.basename(l.entry,o.extname(l.entry))+("cjs"===l.format?".cjs":".js")}let f=o.join(c,g);try{t.mkdirSync(c,{recursive:!0})}catch{}l.logging&&(console.log("\nšØ Building..."),console.log(` Entry: ${l.entry}`),console.log(` Output: ${f}`),console.log(` Format: ${l.format}`),console.log(` Target: ${l.target}`));let u={name:"browser-only",setup(e){e.onResolve({filter:/^(node:.*|fs|path|http|https|url|os|child_process|net|tls|crypto|stream|util|events|buffer|zlib|readline|process|assert|constants|dns|domain|punycode|querystring|repl|string_decoder|sys|timers|tty|v8|vm)$/},()=>({path:"node-builtin",external:!0,sideEffects:!1})),e.onResolve({filter:/^(chokidar|esbuild|mime-types|open|ws|fs\/promises)$/},()=>({path:"server-dep",external:!0,sideEffects:!1})),e.onLoad({filter:/[\\/](server|config|cli)\.ts$/},()=>({contents:"export {}",loader:"js"}))}};try{let n=l.platform||("cjs"===l.format?"node":"browser"),r="browser"===n?[u]:[],g={};l.env&&(Object.entries(l.env).forEach(([e,t])=>{e.startsWith("VITE_")&&(g[`import.meta.env.${e}`]=JSON.stringify(t))}),l.env.MODE&&(g["import.meta.env.MODE"]=JSON.stringify(l.env.MODE)),g["import.meta.env.DEV"]=JSON.stringify("production"!==l.env.MODE),g["import.meta.env.PROD"]=JSON.stringify("production"===l.env.MODE));let m=await e.build({entryPoints:[a],bundle:!0,outfile:f,format:l.format,target:l.target,minify:l.minify,sourcemap:l.sourcemap,external:l.external,treeShaking:l.treeshake,globalName:l.globalName,platform:n,plugins:r,define:g,logLevel:l.logging?"info":"silent",metafile:!0,...l.minify&&{minifyWhitespace:!0,minifyIdentifiers:!0,minifySyntax:!0,legalComments:"none",mangleProps:/^_/,keepNames:!1}}),p=Date.now()-s,y=t.statSync(f).size;if(l.logging&&(console.log("\nā
Build successful!"),console.log(` Time: ${p}ms`),console.log(` Size: ${i(y)}`),m.metafile)){let e=Object.keys(m.metafile.inputs).length;console.log(` Files: ${e} input(s)`);let t=Object.keys(m.metafile.outputs);if(t.length>0){let e=m.metafile.outputs[t[0]];if(e&&e.inputs){let t=Object.entries(e.inputs).sort(([,e],[,t])=>t.bytesInOutput-e.bytesInOutput).slice(0,5);t.length>0&&(console.log("\n š Top 5 largest modules:"),t.forEach(([e,t])=>{let o=e.split(/[/\\]/).pop()||e;console.log(` ${o.padEnd(30)} ${i(t.bytesInOutput)}`)}))}}}let d={outputPath:f,buildTime:p,size:y};if(l.copy&&l.copy.length>0){l.logging&&console.log("\nš¦ Copying files...");for(let e of l.copy){let n=o.resolve(e.from),i=o.resolve(c,e.to),r=o.dirname(i);if(t.existsSync(r)||t.mkdirSync(r,{recursive:!0}),t.existsSync(n)){if(e.transform){let o=t.readFileSync(n,"utf-8"),r=e.transform(o,l);t.writeFileSync(i,r)}else t.copyFileSync(n,i);l.logging&&console.log(` ā ${e.from} ā ${e.to}`)}else l.logging&&console.warn(` ā File not found: ${e.from}`)}}return l.onBuildEnd&&await l.onBuildEnd(d),l.logging&&console.log(""),d}catch(e){throw l.logging&&(console.error("\nā Build failed:"),console.error(e)),e}};
|