vaderjs 1.5.4 → 1.5.6

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/bundler/index.js CHANGED
@@ -38,9 +38,10 @@ await Bun.build({
38
38
  minify: false,
39
39
  root: process.cwd() + "/dist/",
40
40
  outdir: process.cwd() + "/dist/",
41
+
41
42
  format: "esm",
42
43
  ...(process.env.DEV ? { sourcemap: "inline" } : {}),
43
- external:['*.jsx', '*.js']
44
+ external:['*.jsx', '*.js', '*.ts']
44
45
  });
45
46
 
46
47
  let builtCode = fs.readFileSync(path.join(process.cwd(), 'dist', process.env.filePath), 'utf-8')
@@ -52,18 +53,25 @@ function handleReplacements(code) {
52
53
  if(hasImport && line.includes('from')){
53
54
  try {
54
55
  let url = line.includes("'") ? line.split("'")[1] : line.split('"')[1]
55
- let exactFile = path.resolve(url)
56
- // replace url with exact file path
57
- line = line.replace(url, exactFile)
56
+
57
+ line = line.replace(url, url.replace('.jsx', '.js'))
58
+ line = line.replace(url, url.replace('.ts', '.js'))
59
+ newLines.push(line)
58
60
  } catch (error) {
59
61
  continue;
60
62
  }
63
+ }else{
64
+ newLines.push(line)
61
65
  }
66
+
62
67
  }
63
- return lines.join("\n");
68
+ return newLines.join('\n')
64
69
  }
70
+ if(!process.env.isTs){
71
+
65
72
  builtCode = handleReplacements(builtCode)
66
73
  fs.writeFileSync(path.join(process.cwd(), 'dist', process.env.filePath), builtCode)
74
+ }
67
75
  let isClass = function (element) {
68
76
  return element.toString().startsWith("class");
69
77
  };
@@ -104,11 +112,15 @@ const generatePage = async (
104
112
  `<!DOCTYPE html>
105
113
  <head>
106
114
  ${headHtml}
115
+ ${process.env.bindes}
116
+ <meta charset="UTF-8">
117
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
107
118
  </head>
108
119
  ${h}
109
120
  <script type="module">
110
121
  import c from '${process.env.filePath}'
111
- import {render} from '/src/vader/index.js'
122
+ import {render, e} from '/src/vader/index.js'
123
+ window.e = e
112
124
  render(c, document.body.firstChild)
113
125
  </script>
114
126
  `
@@ -123,7 +135,11 @@ const generatePage = async (
123
135
  process.exit(0);
124
136
  };
125
137
  try {
126
- process.env.isImport == undefined && generatePage({ path: process.env.INPUT, route: process.env.OUT });
138
+ if(process.env.isTs == undefined && process.env.isImport) {
139
+ generatePage({ path: process.env.INPUT, route: process.env.OUT })
140
+ }else if(process.env.isTs == undefined){
141
+ generatePage({ path: process.env.INPUT, route: process.env.OUT })
142
+ }
127
143
  } catch (error) {
128
144
  console.log(ansiColors.red(error))
129
145
  }
package/document/index.ts CHANGED
@@ -1,39 +1,43 @@
1
- export const document = (element: any) => {
1
+ export const document = (element: any) => {
2
2
  let type = element.type;
3
- let el = `<${type}`;
3
+ let el = type === null ? `` : `<${type}`
4
+ console.log(el)
4
5
  let attributes = element.props;
5
6
  let children = element.children;
6
- for (let key in attributes) {
7
- if(key === "key"){
8
- el += ` key="${attributes[key]}"`;
9
- continue;
10
- }
11
- if (key === "className") {
12
- el += ` class="${attributes[key]}"`;
13
- continue;
14
- }
15
- if (key === "style") {
16
- // convert style object to string
17
- let styles = attributes[key];
18
- let styleString = "";
19
- // convert camelCase to kebab-case
20
- for (let style in styles) {
21
- let kebabStyle = style.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
22
- styleString += `${kebabStyle}:${styles[style]};`;
7
+ if(type != null){
8
+ for (let key in attributes) {
9
+ if(key === "key"){
10
+ el += ` key="${attributes[key]}"`;
11
+ continue;
23
12
  }
24
- el += ` style="${styleString}"`;
25
- continue;
26
- }
27
- //@ts-ignore
28
- if (key.startsWith("on")){
29
- continue;
30
- }
31
- el += ` ${key}="${attributes[key]}"`;
32
-
33
- }
34
- el += ">";
13
+ if (key === "className") {
14
+ el += ` class="${attributes[key]}"`;
15
+ continue;
16
+ }
17
+ if (key === "style") {
18
+ // convert style object to string
19
+ let styles = attributes[key];
20
+ let styleString = "";
21
+ // convert camelCase to kebab-case
22
+ for (let style in styles) {
23
+ let kebabStyle = style.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
24
+ styleString += `${kebabStyle}:${styles[style]};`;
25
+ }
26
+ el += ` style="${styleString}"`;
27
+ continue;
28
+ }
29
+ //@ts-ignore
30
+ if (key.startsWith("on")){
31
+ continue;
32
+ }
33
+ el += ` ${key}="${attributes[key]}"`;
34
+
35
+ }
36
+ }
37
+ el += type === null ? `` : `>`
35
38
  for (let i = 0;i < children.length; i++) {
36
39
  let child = children[i];
40
+ console.log(child)
37
41
  if (Array.isArray(child)) {
38
42
  child.forEach((c) => {
39
43
  el += document(c);
@@ -48,6 +52,6 @@ export const document = (element: any) => {
48
52
  el += child;
49
53
  }
50
54
  }
51
- el += `</${type}>`;
55
+ el += type === null ? `` : `</${type}>`
52
56
  return el;
53
57
  }
package/index.ts CHANGED
@@ -74,10 +74,10 @@ export const useEffect = (callback:any, dependencies: any[]) => {
74
74
 
75
75
 
76
76
 
77
- export const Fragment = (props: any, children: any) => {
77
+ export const Fragment = (props: any, children: any) => {
78
78
  return {
79
- type: "div",
80
- props: props || {},
79
+ type: isServer ? null : "div",
80
+ props:{},
81
81
  children: children || [],
82
82
  }
83
83
  }
@@ -91,7 +91,7 @@ globalThis.Fragment = Fragment;
91
91
  * @param children
92
92
  * @returns
93
93
  */
94
- export const e = (element, props, ...children) => {
94
+ export const e = (element, props, ...children) => {
95
95
  let instance;
96
96
  switch (true) {
97
97
  case isClassComponent(element):
@@ -102,10 +102,10 @@ export const e = (element, props, ...children) => {
102
102
  case typeof element === "function":
103
103
  instance = new Component;
104
104
  instance.render = element;
105
- let firstEl = instance.render({key: instance.key, children: children, ...props});
105
+ let firstEl = instance.render({key: instance.key, children: children, ...props}, children);
106
106
  instance.children = children;
107
- if (!firstEl) firstEl = {type: "div", props: {key: instance.key, children: [], ...props}, children: []};
108
- firstEl.props = {key: instance.key, children: children, ...props};
107
+ if (!firstEl) firstEl = {type: "div", props: {key: instance.key, ...props}, children: children};
108
+ firstEl.props = { key: instance.key, ...firstEl.props, ...props };
109
109
  return firstEl;
110
110
  default:
111
111
  return { type: element, props: props || {}, children: children || [] };
@@ -127,7 +127,7 @@ export function Switch({ children }) {
127
127
  return child;
128
128
  }
129
129
  }
130
- return null;
130
+ return { type: "div", props: {}, children: [] };
131
131
  }
132
132
 
133
133
  /**
@@ -136,7 +136,7 @@ export function Switch({ children }) {
136
136
  * @returns
137
137
  */
138
138
  export function Match({ when, children }) {
139
- return when ? children : null;
139
+ return when ? children : { type: "div", props: {}, children: [] };
140
140
  }
141
141
  /**
142
142
  * @description - Manage state and forceupdate specific affected elements
@@ -148,7 +148,11 @@ export const useState = <T>(initialState: T) => {
148
148
  const setState = (newState: T) => {
149
149
  initialState = newState;
150
150
  }
151
- return [initialState, setState];
151
+ const getVal = () => {
152
+ return initialState;
153
+ }
154
+
155
+ return [getVal, setState];
152
156
  }
153
157
 
154
158
  /**
@@ -201,7 +205,8 @@ export class Component {
201
205
  if (typeof window === "undefined")
202
206
  return [defaultValue, () => {
203
207
  }];
204
- let value = sessionStorage.getItem("state_" + key) ? JSON.parse(sessionStorage.getItem("state_" + key)).value : defaultValue;
208
+ let value = sessionStorage.getItem("state_" + key) ? JSON.parse(sessionStorage.getItem("state_" + key)).value : defaultValue;
209
+
205
210
  if (typeof value === "string") {
206
211
  try {
207
212
  value = JSON.parse(value);
@@ -215,11 +220,14 @@ export class Component {
215
220
  });
216
221
  }
217
222
  const setValue = (newValue) => {
218
- value = newValue;
219
- sessionStorage.setItem("state_" + key, JSON.stringify({ type: typeof newValue, value: newValue }));
223
+ console.log("setting value", newValue);
224
+ sessionStorage.setItem("state_" + key, JSON.stringify({ value: newValue }));
220
225
  this.forceUpdate(this.key);
221
226
  };
222
- return [value, setValue];
227
+ const getVal = () => {
228
+ return sessionStorage.getItem("state_" + key) ? JSON.parse(sessionStorage.getItem("state_" + key)).value : defaultValue;
229
+ }
230
+ return [getVal, setValue];
223
231
  }
224
232
  useFetch(url, options) {
225
233
  const loadingKey = "loading_" + url;
@@ -247,19 +255,18 @@ export class Component {
247
255
  let newl = this.toElement();
248
256
  if (newl.key !== key) {
249
257
  newl = Array.from(newl.children).filter((el2) => el2.key === key)[0];
250
- }
258
+ }
251
259
  this.Reconciler.update(el, newl);
252
260
  }
253
261
  Reconciler = {
254
262
  update: (oldElement, newElement) => {
255
- if (!oldElement || !newElement)
256
- return;
257
- if (this.Reconciler.shouldUpdate(oldElement, newElement) && oldElement.tagName == newElement.tagName) {
263
+
264
+ if (this.Reconciler.shouldUpdate(oldElement, newElement)) {
265
+ console.log("should update");
258
266
  oldElement.replaceWith(newElement);
259
267
  } else {
260
- let children = oldElement.childNodes;
261
- for (let i = 0;i < children.length; i++) {
262
- this.Reconciler.update(children[i], newElement.childNodes[i]);
268
+ for (let i = 0; i < newElement.childNodes.length; i++) {
269
+ this.Reconciler.update(oldElement.childNodes[i], newElement.childNodes[i]);
263
270
  }
264
271
  }
265
272
  },
@@ -273,6 +280,9 @@ export class Component {
273
280
  if (oldElement.nodeName !== newElement.nodeName) {
274
281
  return true;
275
282
  }
283
+ if (oldElement.innerHTML !== newElement.innerHTML) {
284
+ return true;
285
+ }
276
286
  if (oldElement.childNodes.length !== newElement.childNodes.length) {
277
287
  return true;
278
288
  }
@@ -280,18 +290,19 @@ export class Component {
280
290
  }
281
291
  };
282
292
  parseToElement = (element) => {
283
- if (!element)
284
- return document.createElement("div");
285
- let el = document.createElement(element.type);
293
+ if (!element) return document.createElement("div");
294
+ // create either a element or svg element
295
+ let svg = ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "ellipse", "g"];
296
+ let el = svg.includes(element.type) ? document.createElementNS("http://www.w3.org/2000/svg", element.type) : document.createElement(element.type);
286
297
  let isText = typeof element === "string" || typeof element === "number" || typeof element === "boolean";
287
298
  if (isText) {
288
- el.textContent = element;
299
+ el.innerHTML = element;
289
300
  } else {
290
301
  let attributes = element.props;
291
302
  let children = element.children;
292
303
  for (let key in attributes) {
293
- if (key === "key") {
294
- el.key = attributes[key];
304
+ if (key === "key") {
305
+ el.key = attributes[key];
295
306
  continue;
296
307
  }
297
308
  if (key === "className") {
@@ -299,8 +310,12 @@ export class Component {
299
310
  continue;
300
311
  }
301
312
  if (key === "style") {
302
- for (let styleKey in attributes[key]) {
303
- el.style[styleKey] = attributes[key][styleKey];
313
+ try {
314
+ for (let styleKey in attributes[key]) {
315
+ el.style[styleKey] = attributes[key][styleKey];
316
+ }
317
+ } catch (error) {
318
+
304
319
  }
305
320
  continue;
306
321
  }
@@ -309,22 +324,23 @@ export class Component {
309
324
  continue;
310
325
  }
311
326
  el.setAttribute(key, attributes[key]);
312
- }
313
- if(children === undefined) return el;
314
- for (let i = 0;i < children.length; i++) {
327
+ }
328
+ if (children === undefined)
329
+ return el;
330
+ for (let i = 0;i < children.length; i++) {
315
331
  let child = children[i];
316
332
  if (Array.isArray(child)) {
317
333
  child.forEach((c) => {
318
334
  el.appendChild(this.parseToElement(c));
319
335
  });
320
336
  }
321
- if (typeof child === "function") {
337
+ if (typeof child === "function") {
322
338
  console.log("child is function");
323
339
  let comp = memoizeClassComponent(Component);
324
340
  comp.Mounted = true;
325
341
  comp.render = child;
326
342
  let el2 = comp.toElement();
327
- el2.setAttribute("key", comp.key);
343
+ el2.key = comp.key;
328
344
  el.appendChild(el2);
329
345
  } else if (typeof child === "object") {
330
346
  el.appendChild(this.parseToElement(child));
@@ -345,9 +361,7 @@ export class Component {
345
361
  }
346
362
  toElement() {
347
363
  let children = this.render();
348
- if (children.props["key"]) {
349
- this.key = children.props["key"];
350
- }
364
+
351
365
  let el = this.parseToElement(children);
352
366
  el.key = this.key;
353
367
  return el;
package/main.js CHANGED
@@ -12,6 +12,18 @@ if (!fs.existsSync(process.cwd() + '/app')) {
12
12
  if (!fs.existsSync(process.cwd() + '/public')) {
13
13
  fs.mkdirSync(process.cwd() + '/public')
14
14
  }
15
+ if(!fs.existsSync(process.cwd() + '/src')){
16
+ fs.mkdirSync(process.cwd() + '/src')
17
+ }
18
+ if(!fs.existsSync(process.cwd() + '/vader.config.ts')){
19
+ fs.writeFileSync(process.cwd() + '/vader.config.ts',
20
+ `
21
+ import defineConfig from 'vaderjs/config'
22
+ export default defineConfig({
23
+ port: 8080,
24
+ host_provider: 'apache'
25
+ })`)
26
+ }
15
27
  const mode = args.includes('dev') ? 'development' : args.includes('prod') || args.includes('build') ? 'production' : null
16
28
  if (!mode) {
17
29
  console.log(`
@@ -47,9 +59,9 @@ if (!fs.existsSync(process.cwd() + '/jsconfig.json')) {
47
59
  await Bun.write(process.cwd() + '/jsconfig.json', JSON.stringify(json, null, 4))
48
60
  }
49
61
 
50
- const bindes = []
62
+ var bindes = []
51
63
 
52
- const handleReplacements = (code, file) => {
64
+ const handleReplacements = (code ) => {
53
65
  let lines = code.split('\n')
54
66
  let newLines = []
55
67
  for (let line of lines) {
@@ -57,14 +69,23 @@ const handleReplacements = (code, file) => {
57
69
 
58
70
  if (hasImport && line.includes('.css')) {
59
71
  try {
60
- let url = path.join('/' + line.split("'")[1])
61
- let css = fs.readFileSync(process.cwd() + url, 'utf-8')
62
- line = '';
63
- if (!bindes.includes(`<link rel="stylesheet" href="${url}">`)) {
64
- bindes.push(`<link rel="stylesheet" href="${url}">`)
65
- }
66
- fs.mkdirSync(process.cwd() + '/dist' + path.dirname(url), { recursive: true })
67
- fs.writeFileSync(process.cwd() + '/dist' + url, css)
72
+ let isSmallColon = line.includes("'")
73
+ let url = isSmallColon ? line.split("'")[1] : line.split('"')[1]
74
+ // start from "/" not "/app"
75
+ // remvoe all ./ and ../
76
+ url = url.replaceAll('./', '/').replaceAll('../', '/')
77
+
78
+ let p = path.join(process.cwd() , '/', url)
79
+ line = '';
80
+ url = url.replace(process.cwd() + '/app', '')
81
+ url = url.replace(/\\/g, '/')
82
+ if (!bindes.includes(`<link rel="stylesheet" href="${url}">`)) {
83
+ bindes.push(`
84
+ <style>
85
+ ${fs.readFileSync(p, 'utf-8')}
86
+ </style>
87
+ `)
88
+ }
68
89
  } catch (error) {
69
90
  console.error(error)
70
91
  }
@@ -114,7 +135,7 @@ async function generateApp() {
114
135
  }
115
136
  return new Promise(async (resolve, reject) => {
116
137
  let routes = new Bun.FileSystemRouter({
117
- dir: process.cwd() + '/app',
138
+ dir: path.join(process.cwd(), '/app'),
118
139
  style: 'nextjs'
119
140
  })
120
141
  routes.reload()
@@ -132,7 +153,7 @@ async function generateApp() {
132
153
  let route = window.location.pathname.split('/').filter(v => v !== '')
133
154
  let params = {
134
155
  ${Object.keys(routes.match(route).params || {}).length > 0 ? Object.keys(routes.match(route).params || {}).map(p => {
135
- return `${p}: route[${Object.keys(routes.match(route).params).indexOf(p)}]`
156
+ return `${p}: route[${Object.keys(routes.match(route).params).indexOf(p) + Object.keys(routes.match(route).params).length}]`
136
157
  }).join(',') : ""}
137
158
  }
138
159
  \n${code}
@@ -160,11 +181,13 @@ async function generateApp() {
160
181
  file: process.cwd() + '/dist/' + path.dirname(r) + '/' + path.basename(r),
161
182
  DEV: mode === 'development',
162
183
  size,
184
+ bindes: bindes.join('\n'),
163
185
  filePath: r,
164
186
  INPUT: `../app/${r.replace('.js', '.jsx')}`,
165
187
  },
166
188
  onExit({ exitCode: code }) {
167
189
  if (code === 0) {
190
+ bindes = []
168
191
  console.log(`Built ${r} in ${Date.now() - start}ms`)
169
192
  resolve()
170
193
  } else {
@@ -222,7 +245,7 @@ function handleFiles() {
222
245
  }
223
246
  let glob2 = new Glob('src/**/*')
224
247
  for await (var i of glob2.scan()) {
225
- var file = i
248
+ var file = i
226
249
  fs.mkdirSync(path.join(process.cwd() + '/dist', path.dirname(file)), { recursive: true })
227
250
  // turn jsx to js
228
251
  if (file.includes('.jsx')) {
@@ -253,6 +276,34 @@ function handleFiles() {
253
276
  }
254
277
  }
255
278
  })
279
+ }else if(file.includes('.ts')){
280
+ let code = await Bun.file(file).text()
281
+ code = handleReplacements(code)
282
+ file = file.replace('.ts', '.js')
283
+ fs.writeFileSync(path.join(process.cwd() + '/dist', file.replace('.ts', '.js')), code)
284
+ await Bun.spawn({
285
+ cmd: ['bun', 'run', './dev/bundler.js'],
286
+ cwd: process.cwd(),
287
+ stdout: 'inherit',
288
+ env: {
289
+ ENTRYPOINT: path.join(process.cwd() + '/dist/' + file.replace('.ts', '.js')),
290
+ ROOT: process.cwd() + '/app/',
291
+ OUT: path.dirname(file),
292
+ file: process.cwd() + '/dist/' + file.replace('.ts', '.js'),
293
+ DEV: mode === 'development',
294
+ isTS: true,
295
+ size: code.length / 1024,
296
+ filePath: file.replace('.ts', '.js'),
297
+ INPUT: path.join(process.cwd() , file.replace('.js', '.jsx')),
298
+ },
299
+ onExit({ exitCode: code }) {
300
+ if (code === 0) {
301
+ resolve()
302
+ } else {
303
+ reject()
304
+ }
305
+ }
306
+ })
256
307
  }
257
308
 
258
309
  }
@@ -275,7 +326,8 @@ if (mode === 'development') {
275
326
 
276
327
  // Function to handle file changes with debounce
277
328
  const handleFileChangeDebounced = async (change, file) => {
278
- if(file.endsWith('.tsx') || file.endsWith('.jsx')){
329
+ if(file.endsWith('.tsx') || file.endsWith('.jsx') || file.endsWith('.css') || file.endsWith('.ts') ) {
330
+ if(file.includes('dist')) return
279
331
  clearTimeout(debounceTimeout);
280
332
  debounceTimeout = setTimeout(async () => {
281
333
  if (!isBuilding) { // Check if not already building
@@ -283,9 +335,12 @@ if (mode === 'development') {
283
335
  try {
284
336
  await generateApp();
285
337
  await handleFiles();
286
- clients.forEach(c => {
287
- c.send('reload');
288
- });
338
+ let t = setTimeout(() => {
339
+ clients.forEach(c => {
340
+ c.send('reload');
341
+ });
342
+ clearTimeout(t)
343
+ }, 1000)
289
344
  } catch (error) {
290
345
  console.error(error);
291
346
  } finally {
@@ -322,10 +377,12 @@ if (mode === 'development') {
322
377
  let p = url.pathname.replaceAll("%5B", "[").replaceAll("%5D", "]")
323
378
  let file = await Bun.file(path.join(process.cwd() + '/dist' + p))
324
379
  if (!await file.exists()) return new Response('Not found', { status: 404 })
325
- return new Response(await file.text(), {
380
+ let imageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp', 'image/tiff', 'image/bmp', 'image/ico', 'image/cur', 'image/jxr', 'image/jpg']
381
+
382
+ return new Response(imageTypes.includes(file.type) ? await file.arrayBuffer() : await file.text(), {
326
383
  headers: {
327
384
  'Content-Type': file.type,
328
- 'Cache-Control': 'no-cache',
385
+ 'Cache-Control': imageTypes.includes(file.type) ? 'max-age=31536000' : 'no-cache',
329
386
  'Access-Control-Allow-Origin': '*'
330
387
  }
331
388
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vaderjs",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "A simple and powerful JavaScript library for building modern web applications.",
5
5
  "bin": {
6
6
  "vaderjs": "./main.js"