neutronium 3.3.6 → 3.3.8
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/README.md +10 -6
- package/compiler/compiler.js +1 -2
- package/compiler/template.js +13 -0
- package/neutronium.ico +0 -0
- package/package.json +2 -7
- package/sandbox.mjs +1 -1
- package/ts-neutronium/index.d.ts +47 -43
package/README.md
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
# ⚛️ Neutronium v3.
|
|
1
|
+
# ⚛️ Neutronium v3.3.8
|
|
2
2
|
|
|
3
3
|
**Ultra-dense JavaScript framework – maximum performance, minimal overhead**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/neutronium)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://www.npmjs.com/package/neutronium)
|
|
8
|
-
|
|
8
|
+
[](https://neutronium-website.onrender.com)
|
|
9
|
+
[](https://neutronium-website.onrender.com/Playground/)
|
|
10
|
+
[](https://neutronium-website.onrender.com/Docuemntation/)
|
|
9
11
|
---
|
|
10
12
|
|
|
11
13
|
## 🎉 What's new?
|
|
12
14
|
- ⚡ Faster compilation for complex projects
|
|
13
15
|
- ✨ useState, and useEffect
|
|
14
16
|
- ⚛️ React like syntax for easier switching
|
|
15
|
-
|
|
17
|
+
- 🌐 browser-safe Neutronium code compilation using /sandbox.mjs
|
|
18
|
+
- 🖼️ Apply favicon to your site
|
|
16
19
|
---
|
|
17
20
|
|
|
18
21
|
## ℹ️ About
|
|
@@ -28,7 +31,7 @@
|
|
|
28
31
|
- ⚡️ **Blazing fast rendering**
|
|
29
32
|
- 🧠 **Simple component logic**
|
|
30
33
|
- 🔌 **No dependencies or virtual DOM**
|
|
31
|
-
- 📦 **Small size (~
|
|
34
|
+
- 📦 **Small size (~184kB unpacked)**
|
|
32
35
|
- 🛠️ **Works out of the box**
|
|
33
36
|
- 🔁 **Easy JSX-style structure**
|
|
34
37
|
|
|
@@ -78,8 +81,9 @@ createApp(App).mount('body');
|
|
|
78
81
|
|
|
79
82
|
## NPM Packages using Neutronium
|
|
80
83
|
### [@neuhq/alert](https://www.npmjs.com/package/@neuhq/alert)
|
|
84
|
+
### [neutronium-alert](https://npmjs.org/package/neutronium-alert)
|
|
81
85
|
|
|
82
86
|
---
|
|
83
87
|
|
|
84
88
|
## Found a bug or a problem?
|
|
85
|
-
### Report [here.](https://github.com/PFMCODES/neutronium/issues/new)
|
|
89
|
+
### Report [here.](https://github.com/PFMCODES/neutronium/issues/new)
|
package/compiler/compiler.js
CHANGED
|
@@ -7,7 +7,6 @@ const chokidar = require('chokidar');
|
|
|
7
7
|
const http = require('http');
|
|
8
8
|
const { default: Mime } = require('mime');
|
|
9
9
|
const WebSocket = require('ws');
|
|
10
|
-
const { default: open } = require('open');
|
|
11
10
|
const { execSync } = require('child_process');
|
|
12
11
|
|
|
13
12
|
async function compileProject(projectDir = process.cwd()) {
|
|
@@ -203,7 +202,7 @@ function serveProject(projectDir = process.cwd(), port = 3000) {
|
|
|
203
202
|
reqPath = reqPath.replace('/node_modules', '');
|
|
204
203
|
reqPath = "/node_modules/" + reqPath;
|
|
205
204
|
}
|
|
206
|
-
else if (!reqPath.startsWith('/dist/')) {
|
|
205
|
+
else if (!reqPath.startsWith('/dist/') && !reqPath.startsWith('node_modules')) {
|
|
207
206
|
reqPath = '/dist' + reqPath;
|
|
208
207
|
}
|
|
209
208
|
|
package/compiler/template.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
let favicon;
|
|
4
|
+
const faviconPath = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'))).favicon
|
|
5
|
+
|
|
6
|
+
if (faviconPath) {
|
|
7
|
+
favicon = `<link rel="icon" type="image/x-icon" href="${faviconPath}">`;
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
favicon = '';
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
function baseHtml(script) {
|
|
2
14
|
return `
|
|
3
15
|
<!DOCTYPE html>
|
|
@@ -5,6 +17,7 @@ function baseHtml(script) {
|
|
|
5
17
|
<head>
|
|
6
18
|
<meta charset="UTF-8">
|
|
7
19
|
<title>Neutronium App</title>
|
|
20
|
+
${favicon}
|
|
8
21
|
</head>
|
|
9
22
|
<body>
|
|
10
23
|
${script}
|
package/neutronium.ico
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neutronium",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.8",
|
|
4
4
|
"description": "Ultra-dense JavaScript framework – maximum performance, minimal overhead",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -31,16 +31,11 @@
|
|
|
31
31
|
"homepage": "https://github.com/pfmcodes/neutronium#readme",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@babel/core": "^7.28.
|
|
34
|
+
"@babel/core": "^7.28.6",
|
|
35
35
|
"@babel/plugin-transform-react-jsx": "^7.28.6",
|
|
36
|
-
"@babel/preset-env": "^7.28.0",
|
|
37
|
-
"@babel/preset-react": "^7.27.1",
|
|
38
|
-
"@babel/standalone": "^7.28.6",
|
|
39
|
-
"@pfmcodes/lexius-api": "^1.0.2",
|
|
40
36
|
"chokidar": "^4.0.3",
|
|
41
37
|
"inquirer": "^12.7.0",
|
|
42
38
|
"mime": "^4.0.7",
|
|
43
|
-
"open": "^10.2.0",
|
|
44
39
|
"ws": "^8.18.3"
|
|
45
40
|
}
|
|
46
41
|
}
|
package/sandbox.mjs
CHANGED
|
@@ -16,7 +16,7 @@ export function compileAndReturnOutput(source) {
|
|
|
16
16
|
]]
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
const CDN = "https://esm.sh/neutronium@3.
|
|
19
|
+
const CDN = "https://esm.sh/neutronium@3.3.8/es2022/neutronium.mjs";
|
|
20
20
|
let compiledCode = result.code
|
|
21
21
|
// import { x } from "neutronium"
|
|
22
22
|
.replace(
|
package/ts-neutronium/index.d.ts
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
3
|
+
type EffectFunction = () => void;
|
|
4
|
+
type StateGetter<T> = () => T;
|
|
5
|
+
type StateSetter<T> = (newVal: T) => void;
|
|
6
|
+
type StateEntry<T> = [StateGetter<T>, StateSetter<T>];
|
|
7
7
|
|
|
8
|
-
let globalState:
|
|
8
|
+
let globalState: StateEntry<any>[] = [];
|
|
9
9
|
let stateIndex = 0;
|
|
10
10
|
|
|
11
11
|
function resetStateIndex(): void {
|
|
12
12
|
stateIndex = 0;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
let currentEffect:
|
|
15
|
+
let currentEffect: EffectFunction | null = null;
|
|
16
16
|
|
|
17
|
-
function useEffect(fn:
|
|
17
|
+
function useEffect(fn: EffectFunction): void {
|
|
18
18
|
currentEffect = fn;
|
|
19
19
|
fn(); // run once to collect dependencies
|
|
20
20
|
currentEffect = null;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function useState<T>(initialValue: T):
|
|
23
|
+
function useState<T>(initialValue: T): StateEntry<T> {
|
|
24
24
|
const index = stateIndex;
|
|
25
25
|
|
|
26
26
|
if (!globalState[index]) {
|
|
27
27
|
let value = initialValue;
|
|
28
|
-
const subs = new Set<
|
|
28
|
+
const subs = new Set<EffectFunction>();
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
function get(): T {
|
|
31
31
|
if (currentEffect) subs.add(currentEffect);
|
|
32
32
|
return value;
|
|
33
|
-
}
|
|
33
|
+
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
function set(newVal: T): void {
|
|
36
36
|
if (value !== newVal) {
|
|
37
37
|
value = newVal;
|
|
38
38
|
subs.forEach(fn => fn()); // re-run effects
|
|
@@ -40,23 +40,34 @@ function useState<T>(initialValue: T): StateTuple<T> {
|
|
|
40
40
|
(window as any).__NEUTRONIUM_RENDER_FN__();
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
}
|
|
43
|
+
}
|
|
44
44
|
|
|
45
45
|
globalState[index] = [get, set];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const result = globalState[index] as
|
|
48
|
+
const result = globalState[index] as StateEntry<T>;
|
|
49
49
|
stateIndex++;
|
|
50
50
|
return result;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
type
|
|
53
|
+
type VNode = Node;
|
|
54
|
+
type Child = VNode | string | number | null | undefined;
|
|
55
|
+
type Children = Child | Child[];
|
|
56
|
+
|
|
57
|
+
interface Props {
|
|
58
|
+
children?: Children;
|
|
59
|
+
ref?: (el: HTMLElement) => void;
|
|
54
60
|
[key: string]: any;
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type ComponentFunction = (props: Props) => VNode;
|
|
64
|
+
type ElementType = string | ComponentFunction;
|
|
57
65
|
|
|
58
|
-
function h(type:
|
|
59
|
-
props
|
|
66
|
+
function h(type: ElementType, props: Props | null = {}, ...children: Child[]): VNode {
|
|
67
|
+
props = props || {};
|
|
68
|
+
props.children = (props.children ? (Array.isArray(props.children) ? props.children : [props.children]) : [])
|
|
69
|
+
.concat(children)
|
|
70
|
+
.flat();
|
|
60
71
|
|
|
61
72
|
if (typeof type === 'function') {
|
|
62
73
|
return type(props);
|
|
@@ -64,35 +75,36 @@ function h(type: string | ((props: Props) => Node), props: Props = {}, ...childr
|
|
|
64
75
|
|
|
65
76
|
const el = document.createElement(type);
|
|
66
77
|
|
|
67
|
-
for (const [key, value] of Object.entries(props)) {
|
|
68
|
-
if (key === 'children') continue;
|
|
78
|
+
for (const [key, value] of Object.entries(props || {})) {
|
|
79
|
+
if (key === 'children') continue; // skip
|
|
69
80
|
if (key.startsWith('on') && typeof value === 'function') {
|
|
70
81
|
el.addEventListener(key.slice(2).toLowerCase(), value);
|
|
71
82
|
} else if (key === 'ref' && typeof value === 'function') {
|
|
72
83
|
value(el);
|
|
73
84
|
} else {
|
|
74
|
-
el.setAttribute(key, value);
|
|
85
|
+
el.setAttribute(key, String(value));
|
|
75
86
|
}
|
|
76
87
|
}
|
|
77
88
|
|
|
78
|
-
|
|
89
|
+
props.children.forEach((child: Child) => {
|
|
79
90
|
if (typeof child === 'string' || typeof child === 'number') {
|
|
80
91
|
el.appendChild(document.createTextNode(String(child)));
|
|
81
92
|
} else if (child instanceof Node) {
|
|
82
93
|
el.appendChild(child);
|
|
83
94
|
}
|
|
84
|
-
}
|
|
95
|
+
});
|
|
85
96
|
|
|
86
97
|
return el;
|
|
87
98
|
}
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const root = typeof selector === 'string'
|
|
93
|
-
? document.querySelector(selector)
|
|
94
|
-
: selector;
|
|
100
|
+
interface App {
|
|
101
|
+
mount(selector: string | HTMLElement): HTMLElement | null;
|
|
102
|
+
}
|
|
95
103
|
|
|
104
|
+
function createApp(component: () => VNode): App {
|
|
105
|
+
return {
|
|
106
|
+
mount(selector: string | HTMLElement): HTMLElement | null {
|
|
107
|
+
const root = typeof selector === 'string' ? document.querySelector<HTMLElement>(selector) : selector;
|
|
96
108
|
if (!root) {
|
|
97
109
|
console.error(`❌ Root element '${selector}' not found`);
|
|
98
110
|
return null;
|
|
@@ -100,7 +112,7 @@ function createApp(component: () => Node) {
|
|
|
100
112
|
|
|
101
113
|
(window as any).__NEUTRONIUM_ROOT__ = root;
|
|
102
114
|
|
|
103
|
-
function render() {
|
|
115
|
+
function render(): void {
|
|
104
116
|
resetStateIndex();
|
|
105
117
|
const vnode = component();
|
|
106
118
|
root.innerHTML = '';
|
|
@@ -119,24 +131,16 @@ function Fragment(props: Props = {}): DocumentFragment {
|
|
|
119
131
|
const frag = document.createDocumentFragment();
|
|
120
132
|
const children = props.children || [];
|
|
121
133
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
for (const child of childArray) {
|
|
134
|
+
(Array.isArray(children) ? children : [children]).forEach((child: Child) => {
|
|
125
135
|
if (typeof child === 'string' || typeof child === 'number') {
|
|
126
136
|
frag.appendChild(document.createTextNode(String(child)));
|
|
127
137
|
} else if (child instanceof Node) {
|
|
128
138
|
frag.appendChild(child);
|
|
129
139
|
}
|
|
130
|
-
}
|
|
140
|
+
});
|
|
131
141
|
|
|
132
142
|
return frag;
|
|
133
143
|
}
|
|
134
144
|
|
|
135
|
-
export {
|
|
136
|
-
|
|
137
|
-
createApp,
|
|
138
|
-
Fragment,
|
|
139
|
-
useState,
|
|
140
|
-
useEffect,
|
|
141
|
-
resetStateIndex
|
|
142
|
-
};
|
|
145
|
+
export { h, createApp, Fragment, useState, useEffect, resetStateIndex };
|
|
146
|
+
export type { Props, VNode, Child, Children, ComponentFunction, ElementType, StateEntry, EffectFunction };
|