elegance-js 2.1.23 → 2.1.26
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/dist/client/effect.d.ts +27 -0
- package/dist/client/effect.js +37 -0
- package/dist/client/eventListener.d.ts +39 -0
- package/dist/client/eventListener.js +52 -0
- package/dist/client/loadHook.d.ts +34 -0
- package/dist/client/loadHook.js +52 -0
- package/dist/client/observer.d.ts +36 -0
- package/dist/client/observer.js +66 -0
- package/dist/client/runtime.d.ts +105 -0
- package/dist/client/runtime.js +620 -0
- package/dist/client/state.d.ts +40 -0
- package/dist/client/state.js +110 -0
- package/dist/compilation/compiler.d.ts +155 -0
- package/dist/compilation/compiler.js +1153 -0
- package/dist/components/ClientComponent.d.ts +22 -0
- package/dist/components/ClientComponent.js +55 -0
- package/dist/components/Link.d.ts +16 -1
- package/dist/components/Link.js +22 -0
- package/dist/components/Portal.d.ts +2 -0
- package/dist/components/Portal.js +2 -0
- package/dist/elements/element.d.ts +87 -0
- package/dist/elements/element.js +33 -0
- package/dist/elements/element_list.d.ts +7 -0
- package/dist/elements/element_list.js +65 -0
- package/dist/elements/raw.d.ts +14 -0
- package/dist/elements/raw.js +78 -0
- package/dist/elements/specific_props.d.ts +750 -0
- package/dist/global.d.ts +221 -327
- package/dist/index.d.ts +15 -3
- package/dist/index.js +11 -0
- package/dist/server/layout.d.ts +34 -3
- package/dist/server/layout.js +6 -0
- package/dist/server/log.d.ts +12 -0
- package/dist/server/log.js +64 -0
- package/dist/server/page.d.ts +32 -0
- package/dist/server/page.js +6 -0
- package/dist/server/runtime.d.ts +6 -0
- package/dist/server/runtime.js +72 -0
- package/dist/server/server.d.ts +103 -11
- package/dist/server/server.js +709 -0
- package/package.json +13 -13
- package/scripts/bootstrap.js +37 -273
- package/scripts/bootstrap_files/elegance.txt +40 -0
- package/scripts/bootstrap_files/index.txt +3 -0
- package/scripts/bootstrap_files/layout.txt +46 -0
- package/scripts/bootstrap_files/middleware.txt +18 -0
- package/scripts/bootstrap_files/page.txt +123 -0
- package/scripts/bootstrap_files/route.txt +6 -0
- package/scripts/elegance_dev.ts +40 -0
- package/scripts/elegance_prod.ts +40 -0
- package/scripts/elegance_static.ts +24 -0
- package/scripts/prod.js +9 -26
- package/scripts/run.js +13 -0
- package/scripts/static.js +13 -0
- package/dist/build.d.ts +0 -2
- package/dist/build.mjs +0 -202
- package/dist/client/client.d.ts +0 -1
- package/dist/client/client.mjs +0 -574
- package/dist/client/processPageElements.d.ts +0 -1
- package/dist/client/processPageElements.mjs +0 -117
- package/dist/client/render.d.ts +0 -1
- package/dist/client/render.mjs +0 -40
- package/dist/client/watcher.d.ts +0 -1
- package/dist/client/watcher.mjs +0 -26
- package/dist/compilation/compilation.d.ts +0 -139
- package/dist/compilation/compilation.mjs +0 -751
- package/dist/compilation/compiler_process.d.ts +0 -3
- package/dist/compilation/compiler_process.mjs +0 -102
- package/dist/compilation/dynamic_compiler.d.ts +0 -10
- package/dist/compilation/dynamic_compiler.mjs +0 -93
- package/dist/compile_docs.mjs +0 -34
- package/dist/components/Link.mjs +0 -65
- package/dist/global.mjs +0 -0
- package/dist/helpers/ObjectAttributeType.d.ts +0 -7
- package/dist/helpers/ObjectAttributeType.mjs +0 -11
- package/dist/helpers/camelToKebab.d.ts +0 -1
- package/dist/helpers/camelToKebab.mjs +0 -6
- package/dist/index.mjs +0 -3
- package/dist/internal/deprecate.d.ts +0 -1
- package/dist/internal/deprecate.mjs +0 -7
- package/dist/log.d.ts +0 -10
- package/dist/log.mjs +0 -38
- package/dist/server/generateHTMLTemplate.d.ts +0 -12
- package/dist/server/generateHTMLTemplate.mjs +0 -41
- package/dist/server/layout.mjs +0 -19
- package/dist/server/loadHook.d.ts +0 -30
- package/dist/server/loadHook.mjs +0 -50
- package/dist/server/observe.d.ts +0 -19
- package/dist/server/observe.mjs +0 -16
- package/dist/server/render.d.ts +0 -5
- package/dist/server/render.mjs +0 -61
- package/dist/server/server.mjs +0 -429
- package/dist/server/state.d.ts +0 -61
- package/dist/server/state.mjs +0 -146
- package/dist/shared/bindServerElements.mjs +0 -3
- package/dist/shared/serverElements.d.ts +0 -11
- package/dist/shared/serverElements.mjs +0 -164
- package/scripts/dev.js +0 -33
- package/scripts/export.js +0 -20
- package/scripts/ts-arc-dev.js +0 -9
- package/scripts/ts-arc-prod.js +0 -9
- /package/dist/{compile_docs.d.ts → elements/specific_props.js} +0 -0
- /package/dist/{shared/bindServerElements.d.ts → global.js} +0 -0
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elegance-js",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.26",
|
|
4
4
|
"description": "Web-Framework",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
6
8
|
"bin": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"run": "./scripts/run.js",
|
|
10
|
+
"static": "./scripts/static.js",
|
|
11
|
+
"prod": "./scripts/prod.js",
|
|
12
|
+
"bootstrap": "./scripts/bootstrap.js"
|
|
11
13
|
},
|
|
12
14
|
"scripts": {
|
|
13
|
-
"build": "
|
|
14
|
-
"compile-docs": "node ./dist/compile_docs.mjs --environment=development",
|
|
15
|
-
"compile-docs-bun": "bun run ./dist/compile_docs.mjs --environment=development",
|
|
15
|
+
"build": "npx tsc --project tsconfig.json --rootDir ./src --outDir ./dist && node ./build_scripts/fix_imports.js",
|
|
16
16
|
"prepare": "npm run build"
|
|
17
17
|
},
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
20
|
"types": "./dist/index.d.ts",
|
|
21
|
-
"import": "./dist/index.
|
|
22
|
-
"require": "./dist/index.
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"require": "./dist/index.js"
|
|
23
23
|
},
|
|
24
24
|
"./*": {
|
|
25
25
|
"types": "./dist/*.d.ts",
|
|
26
|
-
"import": "./dist/*.
|
|
27
|
-
"require": "./dist/*.
|
|
26
|
+
"import": "./dist/*.js",
|
|
27
|
+
"require": "./dist/*.js"
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"esbuild": "^0.25.9",
|
|
38
|
-
"ts-arc": "^1.1.
|
|
38
|
+
"ts-arc": "^1.1.29"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@tailwindcss/cli": "^4.0.3",
|
package/scripts/bootstrap.js
CHANGED
|
@@ -4,289 +4,38 @@ import fs from "fs";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
|
|
6
6
|
import { execSync } from "node:child_process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
7
8
|
|
|
8
|
-
execSync("npm install tailwindcss @tailwindcss/cli");
|
|
9
|
+
execSync("npm install tailwindcss @tailwindcss/cli && npm install --save-dev @types/node");
|
|
9
10
|
|
|
10
|
-
const
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const dirs = ["pages", "public", path.join("pages", "api"), path.join("pages", "api", "middleware")];
|
|
11
15
|
dirs.forEach((dir) => {
|
|
12
16
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
13
17
|
});
|
|
14
18
|
|
|
15
19
|
const pageTsPath = path.join("pages", "page.ts");
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const pageTsContent = `
|
|
21
|
-
import { observe, loadHook, eventListener, state } from "elegance-js";
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
This is state.
|
|
25
|
-
It uses a simple observer model in the browser (see the observer function)
|
|
26
|
-
|
|
27
|
-
You can update it's value using state.value, and when you want the observers
|
|
28
|
-
of said state to refresh, call state.signal().
|
|
29
|
-
|
|
30
|
-
You can update the state to whatever value you want it to be,
|
|
31
|
-
before the page is finished building.
|
|
32
|
-
|
|
33
|
-
Once the page is built, all state values are shipped to the browser as-is.
|
|
34
|
-
*/
|
|
35
|
-
const counter = state(0);
|
|
20
|
+
const layoutTsPath = path.join("pages", "layout.ts");
|
|
21
|
+
const middlewareTsPath = path.join("pages", "api", "middleware", "middleware.ts");
|
|
22
|
+
const routeTsPath = path.join("pages", "api", "route.ts");
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
does some preprocessing, and ships the loadhook to the browser.
|
|
40
|
-
The browser, after the page loads, runs the content of the function (the second paramater)
|
|
41
|
-
passed into the loadHook call.
|
|
42
|
-
|
|
43
|
-
Loadhook takes in as it's first parameter, a dependency list of state()'s that
|
|
44
|
-
the loadHook can then reference in the browser.
|
|
45
|
-
|
|
46
|
-
For newbies, note that the content of loadHook is *browser code*, and thus
|
|
47
|
-
cannot be trusted!
|
|
48
|
-
*/
|
|
49
|
-
loadHook(
|
|
50
|
-
[counter],
|
|
51
|
-
(_, counter) => {
|
|
52
|
-
const interval = setInterval(() => {
|
|
53
|
-
counter.value++;
|
|
54
|
-
counter.signal();
|
|
55
|
-
}, 1000);
|
|
56
|
-
|
|
57
|
-
return () => clearInterval(interval);
|
|
58
|
-
},
|
|
59
|
-
)
|
|
24
|
+
const indexTsPath = path.join("index.ts");
|
|
25
|
+
const eleganceTsPath = path.join("elegance.ts");
|
|
60
26
|
|
|
61
|
-
|
|
62
|
-
This variable lets you determine whether your page is:
|
|
63
|
-
1. Built at compile time (non dynamic page).
|
|
64
|
-
Meaning, the page is turned into HTML, CSS and JS *once*, and then served statically.
|
|
65
|
-
|
|
66
|
-
2. Built per-request (dynamic page).
|
|
67
|
-
Meaning the page is *transpiled into JS*, and then every time someone requests the page,
|
|
68
|
-
it is built and then served.
|
|
69
|
-
*/
|
|
70
|
-
export const isDynamicPage = true;
|
|
27
|
+
const bootstrapFilesDir = path.join(__dirname, "bootstrap_files");
|
|
71
28
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
If you end the request in the hook, the page won't be served.
|
|
79
|
-
|
|
80
|
-
export const requestHook = (req: http.IncomingMessage, res: http.ServerResponse) => {
|
|
81
|
-
res.statusCode = 403;
|
|
82
|
-
res.end();
|
|
83
|
-
};
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
/*
|
|
87
|
-
State can also be an array!
|
|
88
|
-
In which case, the reactiveMap() method is added onto the state.
|
|
89
|
-
This allows you to run client-side code, which dynamically changes
|
|
90
|
-
the page's HTML content based on the state of the array in the browser.
|
|
91
|
-
*/
|
|
92
|
-
const ReactiveMap = () => {
|
|
93
|
-
const arrayState = state([
|
|
94
|
-
"John","Mary","William","Kimberly",
|
|
95
|
-
]);
|
|
96
|
-
|
|
97
|
-
return arrayState.reactiveMap((item, index) => {
|
|
98
|
-
index += 1;
|
|
99
|
-
|
|
100
|
-
return div({
|
|
101
|
-
},
|
|
102
|
-
index + ". ", item,
|
|
103
|
-
)
|
|
104
|
-
})
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const SlowComponent = () => {
|
|
108
|
-
const myMessage = state<string | undefined>(undefined);
|
|
109
|
-
|
|
110
|
-
loadHook(
|
|
111
|
-
[myMessage],
|
|
112
|
-
(_, message) => {
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
message.value = "Hello World!";
|
|
115
|
-
message.signal()
|
|
116
|
-
}, 2000);
|
|
117
|
-
},
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
/*
|
|
121
|
-
This is a Barrier component.
|
|
122
|
-
|
|
123
|
-
You can use it to guard clause components in the browser.
|
|
124
|
-
|
|
125
|
-
This is useful for when you for example fetch data in the browser,
|
|
126
|
-
and are waiting for it to resolve.
|
|
127
|
-
|
|
128
|
-
Whilst you're waiting, you can display a loading component,
|
|
129
|
-
instead of blocking the entire page loading.
|
|
130
|
-
|
|
131
|
-
Whenever any value in the dependency array changes,
|
|
132
|
-
the component is re-evaluated.
|
|
133
|
-
*/
|
|
134
|
-
return Barrier(
|
|
135
|
-
[myMessage],
|
|
136
|
-
(message) => {
|
|
137
|
-
if (message === undefined) {
|
|
138
|
-
return div({
|
|
139
|
-
class: "animate-pulse",
|
|
140
|
-
},
|
|
141
|
-
"Loading..",
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return div({
|
|
146
|
-
class: "animate-bounce",
|
|
147
|
-
},
|
|
148
|
-
message
|
|
149
|
-
);
|
|
150
|
-
},
|
|
151
|
-
)
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
/*
|
|
155
|
-
This is the actual content of the page.
|
|
156
|
-
|
|
157
|
-
It does not *have* to be an async function.
|
|
158
|
-
Page can be any value, as long as it resolves into a Child (a built element, eg. string, a return value of an element creation call, etc)
|
|
159
|
-
*/
|
|
160
|
-
export const page: Page = async () => {
|
|
161
|
-
const pageName = state("Elegance.JS");
|
|
162
|
-
|
|
163
|
-
/*
|
|
164
|
-
The below is an element creation function.
|
|
165
|
-
The syntax is roughly similar to how HTML works.
|
|
166
|
-
|
|
167
|
-
A call like: h1("Hello World!")
|
|
168
|
-
|
|
169
|
-
Would generate the HTML: <h1>Hello World!</h1>
|
|
170
|
-
|
|
171
|
-
The first parameter to an element may be another element (child), or an options object.
|
|
172
|
-
|
|
173
|
-
Options objects are used to set things like classNames, style, ids. etc.
|
|
174
|
-
|
|
175
|
-
For example this call: h1({
|
|
176
|
-
id: "my-id",
|
|
177
|
-
},
|
|
178
|
-
"Hello World!"
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
Turns into this HTML: <h1 id="my-id">Hello World!</h1>
|
|
182
|
-
*/
|
|
183
|
-
return body ({
|
|
184
|
-
class: "text-white flex min-h-screen items-start sm:justify-center p-4 bg-black flex-col gap-4 max-w-[500px] w-full mx-auto",
|
|
185
|
-
},
|
|
186
|
-
h1 ({
|
|
187
|
-
class: "text-4xl font-inter font-semibold bg-clip-text text-transparent bg-gradient-to-tl from-[#EEB844] to-[#FF4FED] oveflow-clip",
|
|
188
|
-
},
|
|
189
|
-
\`Welcome to \${pageName.value}!\`,
|
|
190
|
-
),
|
|
191
|
-
|
|
192
|
-
ReactiveMap(),
|
|
193
|
-
|
|
194
|
-
p ({
|
|
195
|
-
},
|
|
196
|
-
"Edit page.ts to get started.",
|
|
197
|
-
),
|
|
198
|
-
|
|
199
|
-
div({
|
|
200
|
-
class: "flex items-start gap-4 mt-2",
|
|
201
|
-
},
|
|
202
|
-
a ({
|
|
203
|
-
class: "px-4 py-2 rounded-md bg-red-400 text-black font-semibold relative group hover:scale-[1.05] duration-200",
|
|
204
|
-
href: "https://elegance.js.org/",
|
|
205
|
-
target: "_blank",
|
|
206
|
-
},
|
|
207
|
-
"Documentation",
|
|
208
|
-
|
|
209
|
-
div ({
|
|
210
|
-
class: "blur-[50px] absolute group-hover:bg-red-400 inset-0 bg-transparent duration-200 pointer-events-none -z-10",
|
|
211
|
-
"aria-hidden": "true",
|
|
212
|
-
}),
|
|
213
|
-
),
|
|
214
|
-
|
|
215
|
-
button ({
|
|
216
|
-
class: "hover:cursor-pointer px-4 py-2 rounded-md bg-zinc-200 text-black font-semibold relative group hover:scale-[1.05] duration-200",
|
|
217
|
-
/*
|
|
218
|
-
Normally, element attributes can only be a string, number or boolean.
|
|
219
|
-
|
|
220
|
-
However, exceptions are made for *object attributes*.
|
|
221
|
-
These are special values that usually perform client-side actions.
|
|
222
|
-
|
|
223
|
-
Take the below for example.
|
|
224
|
-
The eventListener() takes in a dependency array, and a callback function.
|
|
225
|
-
|
|
226
|
-
It then returns an ObjectAttribute of type EVENT_LISTENER.
|
|
227
|
-
|
|
228
|
-
The elegance-compiler, when it sees this, packs up the callback function and state references,
|
|
229
|
-
and ships it to the page.
|
|
230
|
-
|
|
231
|
-
The page, when it loads, then binds the eventListener callback to the corresponding event (in this case, "onclick").
|
|
232
|
-
|
|
233
|
-
ObjectAttributes do not show up in HTML!
|
|
234
|
-
*/
|
|
235
|
-
onClick: eventListener(
|
|
236
|
-
[counter],
|
|
237
|
-
(_, counter) => {
|
|
238
|
-
counter.value++;
|
|
239
|
-
|
|
240
|
-
counter.signal();
|
|
241
|
-
},
|
|
242
|
-
),
|
|
243
|
-
|
|
244
|
-
/*
|
|
245
|
-
This is another ObjectAttribute, just like eventListener
|
|
246
|
-
It takes in an array of state it should watch,
|
|
247
|
-
and when that state calls its state.signal() method,
|
|
248
|
-
|
|
249
|
-
The observer calls it's callback function with the new values,
|
|
250
|
-
and whatever is returned, is the new value of the property.
|
|
251
|
-
|
|
252
|
-
So in this instance, whenever counter.signal() is called
|
|
253
|
-
this observer displays Counter: VALUE, and makes it the
|
|
254
|
-
innerText of this button.
|
|
255
|
-
*/
|
|
256
|
-
innerText: observe([counter], (counter) => \`Counter: \${counter}\`),
|
|
257
|
-
},
|
|
258
|
-
div ({
|
|
259
|
-
class: "blur-[50px] absolute group-hover:bg-zinc-200 inset-0 bg-transparent duration-200 pointer-events-none -z-10",
|
|
260
|
-
"aria-hidden": "true",
|
|
261
|
-
}),
|
|
262
|
-
),
|
|
263
|
-
)
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/*
|
|
268
|
-
This is the metadata of the page.
|
|
269
|
-
Aka the <head> element which gets served alongside the page content.
|
|
270
|
-
|
|
271
|
-
It *must* be a function that resolves into a head() result.
|
|
272
|
-
|
|
273
|
-
In it, you should do things like link your stylesheets,
|
|
274
|
-
set page titles, all that goodness.
|
|
275
|
-
*/
|
|
276
|
-
export const metadata: Metadata = (...children) => html ({
|
|
277
|
-
lang: "en",
|
|
278
|
-
},
|
|
279
|
-
link ({
|
|
280
|
-
rel: "stylesheet",
|
|
281
|
-
href: "/index.css",
|
|
282
|
-
}),
|
|
283
|
-
|
|
284
|
-
title ("Elegance.JS Demo"),
|
|
285
|
-
|
|
286
|
-
...children,
|
|
287
|
-
)
|
|
29
|
+
const pageTsContent = fs.readFileSync(path.join(bootstrapFilesDir, "page.txt"));
|
|
30
|
+
const layoutTsContent = fs.readFileSync(path.join(bootstrapFilesDir, "layout.txt"));
|
|
31
|
+
const middlewareTsContent = fs.readFileSync(path.join(bootstrapFilesDir, "middleware.txt"));
|
|
32
|
+
const routeTsContent = fs.readFileSync(path.join(bootstrapFilesDir, "route.txt"));
|
|
33
|
+
const indexTsContent = fs.readFileSync(path.join(bootstrapFilesDir, "index.txt"));
|
|
34
|
+
const eleganceTsContent = fs.readFileSync(path.join(bootstrapFilesDir, "elegance.txt"));
|
|
288
35
|
|
|
289
|
-
|
|
36
|
+
const indexCssPath = path.join("pages", "input.css");
|
|
37
|
+
const envDtsPath = "env.d.ts";
|
|
38
|
+
const tsconfigPath = "tsconfig.json";
|
|
290
39
|
|
|
291
40
|
const envDtsContent = `/// <reference types="elegance-js/global" />`;
|
|
292
41
|
|
|
@@ -323,9 +72,24 @@ const indexCssContent = `
|
|
|
323
72
|
`;
|
|
324
73
|
|
|
325
74
|
fs.writeFileSync(pageTsPath, pageTsContent, "utf8");
|
|
75
|
+
fs.writeFileSync(layoutTsPath, layoutTsContent, "utf8");
|
|
76
|
+
fs.writeFileSync(routeTsPath, routeTsContent, "utf8");
|
|
77
|
+
fs.writeFileSync(middlewareTsPath, middlewareTsContent, "utf8");
|
|
326
78
|
fs.writeFileSync(indexCssPath, indexCssContent, "utf8");
|
|
327
79
|
fs.writeFileSync(envDtsPath, envDtsContent, "utf8");
|
|
328
80
|
fs.writeFileSync(tsconfigPath, tsconfigContent, "utf8");
|
|
329
81
|
|
|
82
|
+
if (process.argv[2] === "--manual") {
|
|
83
|
+
console.log("--manual: Creating manual defaults..");
|
|
84
|
+
|
|
85
|
+
execSync("npm install ts-arc");
|
|
86
|
+
|
|
87
|
+
fs.writeFileSync(eleganceTsPath, eleganceTsContent, "utf8");
|
|
88
|
+
fs.writeFileSync(indexTsPath, indexTsContent, "utf8");
|
|
89
|
+
|
|
90
|
+
console.log("Run this project with: npx ts-arc index.ts");
|
|
91
|
+
} else {
|
|
92
|
+
console.log("Run this project with: npx run");
|
|
93
|
+
}
|
|
94
|
+
|
|
330
95
|
console.log("Bootstrapped new project!");
|
|
331
|
-
console.log("Run this project with: npx dev")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { serveProject, compileEntireProject, setCompilerOptions, } from "elegance-js";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
async function runtime() {
|
|
6
|
+
const pagesDirectory = path.resolve("./pages");
|
|
7
|
+
const publicDirectory = path.resolve("./public");
|
|
8
|
+
const outputDirectory = path.resolve(".elegance");
|
|
9
|
+
|
|
10
|
+
setCompilerOptions({
|
|
11
|
+
pagesDirectory: pagesDirectory,
|
|
12
|
+
publicDirectory: publicDirectory,
|
|
13
|
+
outputDirectory: outputDirectory,
|
|
14
|
+
environment: "development",
|
|
15
|
+
|
|
16
|
+
doHotReload: true,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const { allLayouts, allPages, allStatusCodePages, compiledStaticLayouts, compiledStaticPages, } = await compileEntireProject();
|
|
20
|
+
|
|
21
|
+
execSync(`npx @tailwindcss/cli -i ${path.join(pagesDirectory, "input.css")} -o ${path.join(outputDirectory, "DIST", "index.css")}`);
|
|
22
|
+
|
|
23
|
+
await serveProject({
|
|
24
|
+
port: 3000,
|
|
25
|
+
hostname: "0.0.0.0",
|
|
26
|
+
|
|
27
|
+
allowDynamic: true,
|
|
28
|
+
allowStatusCodePages: true,
|
|
29
|
+
serveAPI: true,
|
|
30
|
+
|
|
31
|
+
allLayouts,
|
|
32
|
+
allStatusCodePages,
|
|
33
|
+
allPages,
|
|
34
|
+
|
|
35
|
+
builtStaticPages: compiledStaticPages,
|
|
36
|
+
builtStaticLayouts: compiledStaticLayouts,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
runtime();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AnyElement, loadHook, observer, state } from "elegance-js";
|
|
2
|
+
|
|
3
|
+
function Header() {
|
|
4
|
+
const pathname = state("");
|
|
5
|
+
|
|
6
|
+
loadHook((pathname) => {
|
|
7
|
+
pathname.value = window.location.pathname;
|
|
8
|
+
|
|
9
|
+
const id = eleganceClient.onNavigate((newPathname) => {
|
|
10
|
+
pathname.value = newPathname;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return () => eleganceClient.removeNavigationCallback(id);
|
|
14
|
+
}, [pathname])
|
|
15
|
+
|
|
16
|
+
return div({
|
|
17
|
+
class: "px-4 py-2 w-max rounded-md bg-green-400 text-black"
|
|
18
|
+
},
|
|
19
|
+
"Currently visiting: ",
|
|
20
|
+
|
|
21
|
+
span({
|
|
22
|
+
innerText: observer(pathname)
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function layout(child: AnyElement) {
|
|
28
|
+
return html(
|
|
29
|
+
body({
|
|
30
|
+
class: "bg-black text-white h-screen w-screen grid grid-cols-1 p-4 gap-4 grid-rows-[auto_1fr]",
|
|
31
|
+
},
|
|
32
|
+
Header(),
|
|
33
|
+
|
|
34
|
+
child,
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function metadata() {
|
|
40
|
+
return [
|
|
41
|
+
link({
|
|
42
|
+
rel: "stylesheet",
|
|
43
|
+
href: "/index.css",
|
|
44
|
+
}),
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from "http";
|
|
2
|
+
|
|
3
|
+
async function middleware(req: IncomingMessage, res: ServerResponse, next: () => void) {
|
|
4
|
+
if (Math.random() > 0.3) {
|
|
5
|
+
res.statusCode = 401;
|
|
6
|
+
res.end("Sorry, you're not getting into this page, cause you're not logged in!");
|
|
7
|
+
|
|
8
|
+
next();
|
|
9
|
+
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
next();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
middleware,
|
|
18
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { ClientComponent, eventListener, loadHook, observer, state } from "elegance-js";
|
|
2
|
+
|
|
3
|
+
function Counter() {
|
|
4
|
+
const counter = state(0);
|
|
5
|
+
|
|
6
|
+
return div({
|
|
7
|
+
class: "flex flex-col"
|
|
8
|
+
},
|
|
9
|
+
div({
|
|
10
|
+
class: "flex gap-2"
|
|
11
|
+
},
|
|
12
|
+
button({
|
|
13
|
+
onClick: eventListener((_, counter) => {
|
|
14
|
+
counter.value--;
|
|
15
|
+
}, [counter]),
|
|
16
|
+
class: "w-max hover:scale-120 hover:duration-200 p-2 rounded-sm bg-gray-400 text-black"
|
|
17
|
+
},
|
|
18
|
+
"Less!",
|
|
19
|
+
),
|
|
20
|
+
button({
|
|
21
|
+
onClick: eventListener((_, counter) => {
|
|
22
|
+
counter.value++;
|
|
23
|
+
}, [counter]),
|
|
24
|
+
class: "w-max hover:scale-120 hover:duration-200 p-2 rounded-sm bg-gray-400 text-black"
|
|
25
|
+
},
|
|
26
|
+
"More!",
|
|
27
|
+
),
|
|
28
|
+
),
|
|
29
|
+
|
|
30
|
+
div(
|
|
31
|
+
"The counter is at: ",
|
|
32
|
+
span({ innerText: observer(counter), })
|
|
33
|
+
),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function NameList() {
|
|
38
|
+
const names = state(["Lisa", "John", "Mary", "Mike"]);
|
|
39
|
+
|
|
40
|
+
loadHook((names) => {
|
|
41
|
+
const intervalId = setInterval(() => {
|
|
42
|
+
names.value.sort(() => Math.random() - 0.5);
|
|
43
|
+
names.triggerObservers();
|
|
44
|
+
}, 1000);
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
clearInterval(intervalId);
|
|
48
|
+
};
|
|
49
|
+
}, [names]);
|
|
50
|
+
|
|
51
|
+
return div(
|
|
52
|
+
h3({
|
|
53
|
+
class: "font-semibold"
|
|
54
|
+
},
|
|
55
|
+
"My favourite people:",
|
|
56
|
+
),
|
|
57
|
+
div({
|
|
58
|
+
class: "grid grid-rows-2 grid-cols-2 w-max gap-2 font-mono",
|
|
59
|
+
},
|
|
60
|
+
names.reactiveMap((name) => p(name))
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function SlowComponent() {
|
|
66
|
+
const slowData = state<undefined | number>(undefined);
|
|
67
|
+
|
|
68
|
+
loadHook((slowData) => {
|
|
69
|
+
const id = Date.now().toString();
|
|
70
|
+
|
|
71
|
+
let timeoutId: NodeJS.Timeout;
|
|
72
|
+
|
|
73
|
+
slowData.observe(id, (value) => {
|
|
74
|
+
if (value !== undefined) return;
|
|
75
|
+
|
|
76
|
+
timeoutId = setTimeout(() => {
|
|
77
|
+
slowData.value = Math.random() * 100;
|
|
78
|
+
}, Math.random() * 1000 * 2 + 1);
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
clearTimeout(timeoutId);
|
|
83
|
+
}
|
|
84
|
+
}, [slowData]);
|
|
85
|
+
|
|
86
|
+
return div(
|
|
87
|
+
|
|
88
|
+
button({
|
|
89
|
+
disabled: observer((s) => s === undefined ? true : false, [slowData]),
|
|
90
|
+
class: "disabled:opacity-30",
|
|
91
|
+
onClick: eventListener((_, slowData) => {
|
|
92
|
+
slowData.value = undefined;
|
|
93
|
+
}, [slowData]),
|
|
94
|
+
}, "Refresh"),
|
|
95
|
+
|
|
96
|
+
ClientComponent((slowData) => {
|
|
97
|
+
if (!slowData.value) {
|
|
98
|
+
return div("Waiting for slow data..");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return div("Slow Component gave result: ", slowData.value);
|
|
102
|
+
}, [slowData]),
|
|
103
|
+
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function page() {
|
|
108
|
+
return div({
|
|
109
|
+
class: "bg-gray-950 border-2 border-gray-900 p-4 flex flex-col gap-8"
|
|
110
|
+
},
|
|
111
|
+
Counter(),
|
|
112
|
+
|
|
113
|
+
NameList(),
|
|
114
|
+
|
|
115
|
+
SlowComponent(),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function metadata() {
|
|
120
|
+
return [
|
|
121
|
+
title("This is a demo page!"),
|
|
122
|
+
]
|
|
123
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { serveProject, compileEntireProject, setCompilerOptions, } from "elegance-js";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
async function runtime() {
|
|
6
|
+
const pagesDirectory = path.resolve("./pages");
|
|
7
|
+
const publicDirectory = path.resolve("./public");
|
|
8
|
+
const outputDirectory = path.resolve(".elegance");
|
|
9
|
+
|
|
10
|
+
setCompilerOptions({
|
|
11
|
+
pagesDirectory: pagesDirectory,
|
|
12
|
+
publicDirectory: publicDirectory,
|
|
13
|
+
outputDirectory: outputDirectory,
|
|
14
|
+
environment: "development",
|
|
15
|
+
|
|
16
|
+
doHotReload: true,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const { allLayouts, allPages, allStatusCodePages, compiledStaticLayouts, compiledStaticPages, } = await compileEntireProject();
|
|
20
|
+
|
|
21
|
+
execSync(`npx @tailwindcss/cli -i ${path.join(pagesDirectory, "input.css")} -o ${path.join(outputDirectory, "DIST", "index.css")}`);
|
|
22
|
+
|
|
23
|
+
await serveProject({
|
|
24
|
+
port: 3000,
|
|
25
|
+
hostname: "0.0.0.0",
|
|
26
|
+
|
|
27
|
+
allowDynamic: true,
|
|
28
|
+
allowStatusCodePages: true,
|
|
29
|
+
serveAPI: true,
|
|
30
|
+
|
|
31
|
+
allLayouts,
|
|
32
|
+
allStatusCodePages,
|
|
33
|
+
allPages,
|
|
34
|
+
|
|
35
|
+
builtStaticPages: compiledStaticPages,
|
|
36
|
+
builtStaticLayouts: compiledStaticLayouts,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
runtime();
|