vaderjs 2.2.6 → 2.3.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/README.MD +61 -39
- package/cli.ts +186 -0
- package/index.ts +839 -688
- package/jsconfig.json +2 -2
- package/main.js +414 -600
- package/package.json +1 -1
- package/plugins/index.ts +63 -0
- package/plugins/tailwind.ts +2 -0
- package/README.md +0 -89
- package/bun.lockb +0 -0
- package/bundler/index.js +0 -295
- package/document/index.ts +0 -77
- package/examples/counter/index.jsx +0 -10
package/package.json
CHANGED
package/plugins/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// vaderPlugin.d.ts
|
|
2
|
+
|
|
3
|
+
/** The API object passed to plugin hooks */
|
|
4
|
+
export interface VaderAPI {
|
|
5
|
+
/** Run a shell command (string or string[]) and wait for it to finish */
|
|
6
|
+
runCommand(cmd: string | string[]): Promise<void>;
|
|
7
|
+
|
|
8
|
+
/** Inject arbitrary HTML into the <head> of generated index.html files */
|
|
9
|
+
injectHTML(content: string): void;
|
|
10
|
+
|
|
11
|
+
/** Log a message prefixed with [Vader Plugin] */
|
|
12
|
+
log(msg: string): void;
|
|
13
|
+
|
|
14
|
+
/** Get absolute path to the project root */
|
|
15
|
+
getProjectRoot(): string;
|
|
16
|
+
|
|
17
|
+
/** Get absolute path to the dist output directory */
|
|
18
|
+
getDistDir(): string;
|
|
19
|
+
|
|
20
|
+
/** Get absolute path to the public assets directory */
|
|
21
|
+
getPublicDir(): string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Supported plugin hook names */
|
|
25
|
+
export type PluginHookName =
|
|
26
|
+
| "onBuildStart"
|
|
27
|
+
| "onBuildFinish"
|
|
28
|
+
| "onWatchStart"
|
|
29
|
+
| "onWatchStop"
|
|
30
|
+
| "onServeStart"
|
|
31
|
+
| "onServeStop"
|
|
32
|
+
| "onFileChange";
|
|
33
|
+
|
|
34
|
+
/** Interface for a single plugin */
|
|
35
|
+
export interface VaderPlugin {
|
|
36
|
+
/** Called before build starts */
|
|
37
|
+
onBuildStart?(api: VaderAPI): Promise<void> | void;
|
|
38
|
+
|
|
39
|
+
/** Called after build finishes */
|
|
40
|
+
onBuildFinish?(api: VaderAPI): Promise<void> | void;
|
|
41
|
+
|
|
42
|
+
/** Called when watcher starts (dev mode) */
|
|
43
|
+
onWatchStart?(api: VaderAPI): Promise<void> | void;
|
|
44
|
+
|
|
45
|
+
/** Called when watcher stops (dev mode) */
|
|
46
|
+
onWatchStop?(api: VaderAPI): Promise<void> | void;
|
|
47
|
+
|
|
48
|
+
/** Called when dev server starts */
|
|
49
|
+
onServeStart?(api: VaderAPI): Promise<void> | void;
|
|
50
|
+
|
|
51
|
+
/** Called when dev server stops */
|
|
52
|
+
onServeStop?(api: VaderAPI): Promise<void> | void;
|
|
53
|
+
|
|
54
|
+
/** Called on file change during watch, with changed file path */
|
|
55
|
+
onFileChange?(api: VaderAPI, filePath: string): Promise<void> | void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** User config type */
|
|
59
|
+
export interface VaderConfig {
|
|
60
|
+
port?: number;
|
|
61
|
+
host_provider?: string;
|
|
62
|
+
plugins?: VaderPlugin[];
|
|
63
|
+
}
|
package/plugins/tailwind.ts
CHANGED
package/README.md
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<a href="https://vader-js.pages.dev">
|
|
3
|
-
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: dark)" srcset="/icon.jpeg">
|
|
5
|
-
<img src="https://github.com/Postr-Inc/Vader.js/blob/main/logo.png" height="128">
|
|
6
|
-
</picture>
|
|
7
|
-
<h1 align="center">Vader.js</h1>
|
|
8
|
-
</a>
|
|
9
|
-
</p>
|
|
10
|
-
|
|
11
|
-
# Vader.js A reactive framework for building fast and scalable web applications
|
|
12
|
-
|
|
13
|
-
[](https://github.com/Postr-Inc/Vader.js/blob/main/LICENSE) [](https://www.npmjs.com/package/vaderjs)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Installation
|
|
17
|
-
|
|
18
|
-
```js
|
|
19
|
-
bun install vaderjs @latest
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
```ts
|
|
23
|
-
import { useSate, e } from "vaderjs"
|
|
24
|
-
export default function(){
|
|
25
|
-
let [count, setCount] = useState(0)
|
|
26
|
-
return (
|
|
27
|
-
<div>
|
|
28
|
-
<p>Count is {count} </p>
|
|
29
|
-
<button onClick={()=>setCount(count++)}>
|
|
30
|
-
Increment +1
|
|
31
|
-
</button>
|
|
32
|
-
</div>
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
# Project Setup
|
|
38
|
-
Create a pages folder - which allows you to have nextjs page like routing via buns file based router
|
|
39
|
-
|
|
40
|
-
Tip: Each folder can be deep nested up to 4 levels!
|
|
41
|
-
|
|
42
|
-
```md
|
|
43
|
-
|
|
44
|
-
/pages/index.jsx = /
|
|
45
|
-
/pages/home/[page].jsx = /home/:page
|
|
46
|
-
/pages/path/index.jsx = /path/
|
|
47
|
-
/pages/test/[[...catchall]]/index.jsx = /path/test/*
|
|
48
|
-
/pages/route/[param1]/[param2].jsx = /path/route/:param1/:param2
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
Keyword folders - all files are passed from these folders to the build folder
|
|
52
|
-
|
|
53
|
-
```md
|
|
54
|
-
1. pages - used for jsx route files
|
|
55
|
-
2. src - used for your jsx components / javascript -typescript files
|
|
56
|
-
3. public - used for anything / css / json etc
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# Define your config
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
import { defineConfig } from "vaderjs/config";
|
|
64
|
-
import cloudflare from "vaderjs/plugins/cloudflare/functions"
|
|
65
|
-
import tailwindcss from "vaderjs/plugins/tailwindcss"
|
|
66
|
-
export default defineConfig({
|
|
67
|
-
target: "web",
|
|
68
|
-
host: {
|
|
69
|
-
hostname: "localhost",
|
|
70
|
-
provider:'cloudflare' // used for ssg or ssr
|
|
71
|
-
},
|
|
72
|
-
env: {
|
|
73
|
-
PORT: 3000,
|
|
74
|
-
SSR: true,
|
|
75
|
-
apiRoute: "https://api.example.com"
|
|
76
|
-
},
|
|
77
|
-
Router: {
|
|
78
|
-
tls: {
|
|
79
|
-
cert: "cert.pem",
|
|
80
|
-
key: "key.pem"
|
|
81
|
-
},
|
|
82
|
-
headers: {
|
|
83
|
-
"cache-control": "public, max-age=0, must-revalidate"
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
plugins: [cloudflare, tailwindcss],
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
```
|
package/bun.lockb
DELETED
|
Binary file
|
package/bundler/index.js
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
e,
|
|
4
|
-
useState,
|
|
5
|
-
useEffect,
|
|
6
|
-
useFetch,
|
|
7
|
-
useAsyncState,
|
|
8
|
-
Fragment,
|
|
9
|
-
} from "vaderjs";
|
|
10
|
-
import { document } from "vaderjs/document/index.ts";
|
|
11
|
-
import fs from "fs";
|
|
12
|
-
import ansiColors from "ansi-colors";
|
|
13
|
-
import path from "path";
|
|
14
|
-
let path2 = require("path");
|
|
15
|
-
globalThis.Fragment = Fragment;
|
|
16
|
-
|
|
17
|
-
globalThis.window = {
|
|
18
|
-
location: {
|
|
19
|
-
hash: "",
|
|
20
|
-
host: "",
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
globalThis.Component = Component;
|
|
24
|
-
globalThis.e = e;
|
|
25
|
-
globalThis.useFetch = useFetch;
|
|
26
|
-
globalThis.useEffect = useEffect;
|
|
27
|
-
globalThis.useAsyncState = useAsyncState;
|
|
28
|
-
globalThis.useState = useState;
|
|
29
|
-
globalThis.genKey = () => {
|
|
30
|
-
return crypto.randomUUID();
|
|
31
|
-
};
|
|
32
|
-
globalThis.document = {
|
|
33
|
-
createElement: (tag) => { },
|
|
34
|
-
getElementById: (id) => { },
|
|
35
|
-
querySelector: (query) => {
|
|
36
|
-
return Object.create({
|
|
37
|
-
addEventListener: (event, cb) => { },
|
|
38
|
-
removeEventListener: (event, cb) => { },
|
|
39
|
-
innerHTML: "",
|
|
40
|
-
appendChild: (child) => { },
|
|
41
|
-
removeChild: (child) => { },
|
|
42
|
-
src: "",
|
|
43
|
-
style: {},
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
querySelectorAll: (query) => {
|
|
47
|
-
return []
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
globalThis.window = {
|
|
51
|
-
addEventListener: (event, cb) => { },
|
|
52
|
-
removeEventListener: (event, cb) => { },
|
|
53
|
-
localStorage: {
|
|
54
|
-
setItem: (key, value) => { },
|
|
55
|
-
getItem: (key) => { },
|
|
56
|
-
},
|
|
57
|
-
sessionStorage: {
|
|
58
|
-
setItem: (key, value) => { },
|
|
59
|
-
getItem: (key) => { },
|
|
60
|
-
},
|
|
61
|
-
location: {
|
|
62
|
-
href: "",
|
|
63
|
-
pathname: "",
|
|
64
|
-
},
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
globalThis.localStorage = {
|
|
68
|
-
setItem: (key, value) => { },
|
|
69
|
-
getItem: (key) => { },
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
await Bun.build({
|
|
73
|
-
entrypoints: [process.env.ENTRYPOINT],
|
|
74
|
-
minify: false,
|
|
75
|
-
root: process.cwd() + "/dist/",
|
|
76
|
-
outdir: process.cwd() + "/dist/",
|
|
77
|
-
format: "esm",
|
|
78
|
-
...(JSON.parse(process.env.DEV) ? { sourcemap: "inline" } : {}),
|
|
79
|
-
packages: "bundle",
|
|
80
|
-
env: "inline",
|
|
81
|
-
external: ["vaderjs", "*.png", "*.jpg", "*.jpeg", "*.gif", "*.svg", "*.css"],
|
|
82
|
-
});
|
|
83
|
-
} catch (error) {
|
|
84
|
-
console.error(error)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
let builtCode = fs.readFileSync(path.join(process.cwd(), 'dist', process.env.filePath), 'utf-8')
|
|
89
|
-
|
|
90
|
-
const handleReplacements = (code) => {
|
|
91
|
-
let lines = code.split('\n')
|
|
92
|
-
let newLines = []
|
|
93
|
-
for (let line of lines) {
|
|
94
|
-
let hasImport = line.includes('import')
|
|
95
|
-
if (hasImport && line.includes('vaderjs')) {
|
|
96
|
-
line = line.replace('vaderjs', '/src/vader/index.js')
|
|
97
|
-
}
|
|
98
|
-
if (hasImport && line.includes('react')) {
|
|
99
|
-
line = line.replace('react', '/src/vader/index.js')
|
|
100
|
-
}
|
|
101
|
-
if(hasImport && line.includes('public') && line.includes('.png') ||
|
|
102
|
-
line.includes('.jpg') || line.includes('.jpeg') || line.includes('.gif') || line.includes('.svg')) {
|
|
103
|
-
let url = line.split('"')[1]
|
|
104
|
-
// replace ../../
|
|
105
|
-
var b4 = url
|
|
106
|
-
let filevariable = line.split("import")[1].split("from")[0].replace(" ", "").replace("{", "").replace("}","")
|
|
107
|
-
|
|
108
|
-
url = url.replace('../../', '').replace('../', '').replace('./', '')
|
|
109
|
-
line = `var ${filevariable} = "${url}"`
|
|
110
|
-
console.log(line)
|
|
111
|
-
}
|
|
112
|
-
if (hasImport && line.includes('.css')) {
|
|
113
|
-
try {
|
|
114
|
-
let isSmallColon = line.includes("'")
|
|
115
|
-
let url = isSmallColon ? line.split("'")[1] : line.split('"')[1]
|
|
116
|
-
// start from "/" not "/app"
|
|
117
|
-
// remvoe all ./ and ../
|
|
118
|
-
url = url.replaceAll('./', '/').replaceAll('../', '/')
|
|
119
|
-
|
|
120
|
-
let p = path.join(process.cwd(), '/', url)
|
|
121
|
-
line = '';
|
|
122
|
-
url = url.replace(process.cwd() + '/app', '')
|
|
123
|
-
url = url.replace(/\\/g, '/')
|
|
124
|
-
if (!bindes.includes(`<link rel="stylesheet" href="${url}">`)) {
|
|
125
|
-
bindes.push(`
|
|
126
|
-
<style>
|
|
127
|
-
${fs.readFileSync(p, 'utf-8')}
|
|
128
|
-
</style>
|
|
129
|
-
`)
|
|
130
|
-
}
|
|
131
|
-
} catch (error) {
|
|
132
|
-
console.error(error)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (line.toLowerCase().includes('genkey()')) {
|
|
136
|
-
line = line.toLowerCase().replace('genkey()', `this.key = "${crypto.randomUUID()}"`)
|
|
137
|
-
}
|
|
138
|
-
if (!hasImport && line.includes('useFetch')) {
|
|
139
|
-
line = line.replace('useFetch', 'this.useFetch')
|
|
140
|
-
}
|
|
141
|
-
if (!hasImport && line.match(/\buseState\d*\(/) && line.includes('[') && !line.includes("this")) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
let key = line.split(',')[0].split('[')[1].replace(' ', '');
|
|
145
|
-
|
|
146
|
-
let updatedLine = line.replace(/\buseState\d*\(/, `this.useState('${key}',`);
|
|
147
|
-
|
|
148
|
-
line = updatedLine;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (!hasImport && line.match(/\buseAsyncState\d*\(/) && line.includes('[') && !line.includes("this")) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let key = line.split(',')[0].split('[')[1].replace(' ', '');
|
|
155
|
-
|
|
156
|
-
let updatedLine = line.replace(/\buseAsyncState\d*\(/, `this.useAsyncState('${key}',`);
|
|
157
|
-
|
|
158
|
-
line = updatedLine;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (!hasImport && line.match(/\buseEffect\d*\(/) && !line.includes("this")) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
let updatedLine = line.replace(/\buseEffect\d*\(/, `this.useEffect(`);
|
|
165
|
-
|
|
166
|
-
line = updatedLine;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (!hasImport && line.match(/\buseRef\d*\(/) && line.includes('[') && !line.includes("this")) {
|
|
170
|
-
line = line.replace(' ', '')
|
|
171
|
-
let b4 = line
|
|
172
|
-
let key = line.split('=')[0].split(' ').filter(Boolean)[1]
|
|
173
|
-
console.log(key)
|
|
174
|
-
b4 = line.replace('useRef(', `this.useRef('${key}',`)
|
|
175
|
-
line = b4
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
newLines.push(line)
|
|
180
|
-
}
|
|
181
|
-
let c = newLines.join('\n')
|
|
182
|
-
return c
|
|
183
|
-
}
|
|
184
|
-
builtCode = handleReplacements(builtCode)
|
|
185
|
-
|
|
186
|
-
builtCode += `
|
|
187
|
-
var process = {
|
|
188
|
-
env: {
|
|
189
|
-
${Object.keys(process.env)
|
|
190
|
-
.filter((key) =>
|
|
191
|
-
!['bindes', 'ENTRYPOINT', 'ROOT', 'OUT', 'file', 'DEV',
|
|
192
|
-
'size', 'filePath', 'isAppFile', 'isJsx', 'INPUT'].includes(key)
|
|
193
|
-
)
|
|
194
|
-
.map((key) => `${key}: "${process.env[key]}"`)
|
|
195
|
-
.join(',\n')}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
`;
|
|
199
|
-
fs.writeFileSync(path.join(process.cwd(), 'dist', process.env.filePath), builtCode)
|
|
200
|
-
let isClass = function (element) {
|
|
201
|
-
return element && element.toString().startsWith("class");
|
|
202
|
-
};
|
|
203
|
-
const generatePage = async (
|
|
204
|
-
data = { path: process.env.INPUT, route: process.env.OUT }
|
|
205
|
-
) => {
|
|
206
|
-
const { path, route } = data;
|
|
207
|
-
if (path.includes("root.js")) return;
|
|
208
|
-
let html = await import(path).then((m) => m.default);
|
|
209
|
-
|
|
210
|
-
let { head } = await import(path).then((m) => m);
|
|
211
|
-
let isFunction = false;
|
|
212
|
-
globalThis.isServer = true;
|
|
213
|
-
if (!html) {
|
|
214
|
-
return
|
|
215
|
-
}
|
|
216
|
-
if (isClass(html)) {
|
|
217
|
-
html = new html();
|
|
218
|
-
html.Mounted = true;
|
|
219
|
-
html = html.render();
|
|
220
|
-
} else {
|
|
221
|
-
isFunction = true;
|
|
222
|
-
let instance = new Component();
|
|
223
|
-
html = html.bind(instance);
|
|
224
|
-
instance.render = html;
|
|
225
|
-
html = instance.render();
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
let h = document(html);
|
|
230
|
-
if(process.env.bindes.includes('<link rel="stylesheet" ')){
|
|
231
|
-
// turn stylesheet into inline style
|
|
232
|
-
let links = process.env.bindes.split('<link rel="stylesheet" ')
|
|
233
|
-
let styles = []
|
|
234
|
-
for(let link of links){
|
|
235
|
-
if(link.includes('href')){
|
|
236
|
-
let href = link.split('href=')[1].split('>')[0].replace('"', '').replace('"', '')
|
|
237
|
-
let file = fs.readFileSync(path2.join(process.cwd() + "/dist/", href), 'utf-8')
|
|
238
|
-
styles.push(file)
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
let style = styles.join('\n')
|
|
242
|
-
process.env.bindes = `
|
|
243
|
-
<style>
|
|
244
|
-
${style}
|
|
245
|
-
</style>
|
|
246
|
-
`
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (!fs.existsSync(process.cwd() + "/dist" + path2.dirname(route))) {
|
|
250
|
-
fs.mkdirSync(process.cwd() + "/dist" + path2.dirname(route), {
|
|
251
|
-
recursive: true,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
let headHtml = "";
|
|
255
|
-
if (head) {
|
|
256
|
-
headHtml = document(head());
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
await Bun.write(
|
|
263
|
-
process.cwd() + "/dist/" + route + "/index.html",
|
|
264
|
-
`<!DOCTYPE html>
|
|
265
|
-
<head>
|
|
266
|
-
<script defer type="module">
|
|
267
|
-
import c from '${process.env.filePath}'
|
|
268
|
-
import {render, e} from '/src/vader/index.js'
|
|
269
|
-
window.e = e
|
|
270
|
-
render(c, document.body)
|
|
271
|
-
</script>
|
|
272
|
-
|
|
273
|
-
${process.env.bindes}
|
|
274
|
-
</head>
|
|
275
|
-
${h}
|
|
276
|
-
|
|
277
|
-
`
|
|
278
|
-
);
|
|
279
|
-
console.log(
|
|
280
|
-
ansiColors.blue(
|
|
281
|
-
`${process.env.filePath.replace(".js", ".jsx")} - ${parseInt(
|
|
282
|
-
process.env.size
|
|
283
|
-
).toFixed(2)}kb`
|
|
284
|
-
)
|
|
285
|
-
);
|
|
286
|
-
process.exit(0);
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
if (process.env.isJsx == "true" && process.env.isAppFile == "true") {
|
|
291
|
-
generatePage({ path: process.env.INPUT, route: process.env.OUT })
|
|
292
|
-
}
|
|
293
|
-
} catch (error) {
|
|
294
|
-
console.log(ansiColors.red(error))
|
|
295
|
-
}
|
package/document/index.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
//@ts-nocheck
|
|
2
|
-
const acceptedAttributes = [
|
|
3
|
-
// Global attributes
|
|
4
|
-
'accesskey', 'class', 'className', 'idKey', 'contenteditable', 'contextmenu', 'data', 'dir', 'hidden',
|
|
5
|
-
'id', 'lang', 'style', 'tabindex', 'title', 'translate', 'xml:lang', 'xml:space',
|
|
6
|
-
|
|
7
|
-
// SVG-specific attributes
|
|
8
|
-
'xmlns', 'fill', 'viewBox', 'stroke-width', 'stroke', 'd', 'stroke-linecap', 'stroke-linejoin', 'content', 'name'
|
|
9
|
-
];
|
|
10
|
-
export const document = (element: any) => {
|
|
11
|
-
if(!element) return ``
|
|
12
|
-
let type = element.type;
|
|
13
|
-
let el = type === null ? `` : `<${type}`
|
|
14
|
-
let attributes = element.props;
|
|
15
|
-
let children = element.children;
|
|
16
|
-
if(type != null && type !== false && type !== true && type !== undefined){
|
|
17
|
-
for (let key in attributes) {
|
|
18
|
-
if (typeof attributes[key] !== "string" || !acceptedAttributes.includes(key)) {
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
if(key === "key"){
|
|
22
|
-
el += ` key="${attributes[key]}"`;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
if (key === "className") {
|
|
26
|
-
el += ` class="${attributes[key]}"`;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
if (key === "style") {
|
|
30
|
-
// convert style object to string
|
|
31
|
-
let styles = attributes[key];
|
|
32
|
-
let styleString = "";
|
|
33
|
-
// convert camelCase to kebab-case
|
|
34
|
-
for (let style in styles) {
|
|
35
|
-
let kebabStyle = style.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
|
|
36
|
-
styleString += `${kebabStyle}:${styles[style]};`;
|
|
37
|
-
}
|
|
38
|
-
el += ` style="${styleString}"`;
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
//@ts-ignore
|
|
42
|
-
if (key.startsWith("on")){
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
el += ` ${key}="${attributes[key]}"`;
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
el += type === null || type == false ? `` : `>`
|
|
50
|
-
if(children === null || children === undefined){
|
|
51
|
-
return el;
|
|
52
|
-
}
|
|
53
|
-
for (let i = 0;i < children.length; i++) {
|
|
54
|
-
let child = children[i];
|
|
55
|
-
if (Array.isArray(child)) {
|
|
56
|
-
child.forEach((c) => {
|
|
57
|
-
el += document(c);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
if(typeof child === "function"){
|
|
61
|
-
let out = document(child());
|
|
62
|
-
if(out !== null || out !== false || out !== undefined){
|
|
63
|
-
el += out;
|
|
64
|
-
}
|
|
65
|
-
}else
|
|
66
|
-
if (typeof child === "object") {
|
|
67
|
-
el += document(child);
|
|
68
|
-
}else{
|
|
69
|
-
if(child === null || child === false || child === undefined){
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
el += child;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
el += type === null ? `` : `</${type}>`
|
|
76
|
-
return el;
|
|
77
|
-
}
|