create-gardener 1.1.6 → 1.1.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 +2 -313
- package/package.json +1 -1
- package/template/package.json +11 -12
- package/template/pnpm-lock.yaml +1545 -0
- package/template/src/backend/controllers/gardener.controller.ts +7 -32
- package/template/src/backend/routes/gardener.route.ts +2 -1
- package/template/src/backend/server.ts +1 -1
- package/template/src/frontend/frontendtemplate.ejs +4 -4
- package/template/src/frontend/gardenerST.js +430 -0
- package/template/src/frontend/static/components/emailsvg.js +55 -0
- package/template/src/frontend/{components → static/components}/eyeoff.js +1 -1
- package/template/src/frontend/static/components/eyeon.js +43 -0
- package/template/src/frontend/{components → static/components}/notification.js +1 -1
- package/template/src/frontend/{components → static/components}/passwordBox.js +3 -3
- package/template/src/frontend/static/components/test.js +54 -0
- package/template/src/frontend/{gardener.js → static/gardener.js} +76 -4
- package/template/src/frontend/static/style.css +1048 -0
- package/template/src/frontend/style.css +148 -350
- package/template/src/frontend/views/_.ejs +17 -8
- package/template/src/frontend/views/_login.ejs +8 -8
- package/template/tsconfig.json +1 -1
- package/.direnv/bin/nix-direnv-reload +0 -19
- package/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc +0 -2140
- package/.envrc +0 -1
- package/template/Readme.md +0 -349
- package/template/src/frontend/components/emailsvg.js +0 -55
- package/template/src/frontend/components/eyeon.js +0 -44
- package/template/src/frontend/components/test.js +0 -54
- /package/template/src/{backend → frontend/static}/cache/gardener_500x500.webp +0 -0
- /package/template/src/frontend/{components → static/components}/nonui/api.js +0 -0
- /package/template/src/frontend/{global.js → static/global.js} +0 -0
- /package/template/src/frontend/{style2.css → static/style2.css} +0 -0
|
@@ -19,20 +19,8 @@ interface AddComponentBody {
|
|
|
19
19
|
export function addComponent(req: Request<{}, {}, AddComponentBody>, res: Response) {
|
|
20
20
|
try {
|
|
21
21
|
const { path: filePath, component } = req.body;
|
|
22
|
-
const parsed = JSON.parse(component);
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
const formatted = JSON.stringify(parsed, null, 2);
|
|
26
|
-
|
|
27
|
-
const filecontent = `
|
|
28
|
-
import { gardener, fetchElement, replaceElement } from '../gardener.js'
|
|
29
|
-
|
|
30
|
-
export default function thisfun() {
|
|
31
|
-
return gardener(${formatted})
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
fs.writeFileSync(`./src/frontend/${filePath}`, filecontent, "utf8");
|
|
23
|
+
fs.writeFileSync(`./src/frontend/${filePath}`, component, "utf8");
|
|
36
24
|
|
|
37
25
|
res.json({ success: true });
|
|
38
26
|
} catch (err) {
|
|
@@ -46,7 +34,7 @@ export async function imageOptimiser(req: Request, res: Response) {
|
|
|
46
34
|
try {
|
|
47
35
|
const { name } = req.params;
|
|
48
36
|
|
|
49
|
-
if (
|
|
37
|
+
if (typeof name !== 'string') return;
|
|
50
38
|
// name format: test_500x300.webp
|
|
51
39
|
const match = name.match(/^(.+?)_(\d+)x(\d+)\.webp$/);
|
|
52
40
|
|
|
@@ -60,7 +48,7 @@ export async function imageOptimiser(req: Request, res: Response) {
|
|
|
60
48
|
const width = parseInt(widthStr, 10);
|
|
61
49
|
const height = parseInt(heightStr, 10);
|
|
62
50
|
|
|
63
|
-
const cacheDir = path.join(__dirname, "
|
|
51
|
+
const cacheDir = path.join(__dirname, "../../frontend/static/cache");
|
|
64
52
|
await fsp.mkdir(cacheDir, { recursive: true });
|
|
65
53
|
|
|
66
54
|
const outputPath = path.join(cacheDir, name);
|
|
@@ -129,22 +117,13 @@ export async function createStatic(req: Request, res: Response) {
|
|
|
129
117
|
const outDir = path.resolve("src/tempfrontend");
|
|
130
118
|
const finalOut = path.resolve("src/frontendStatic");
|
|
131
119
|
|
|
132
|
-
const otherAssets = path.resolve("src/frontend");
|
|
133
120
|
await fsp.mkdir(outDir, { recursive: true });
|
|
121
|
+
await fsp.mkdir(finalOut, { recursive: true });
|
|
134
122
|
|
|
135
|
-
const entries2 = await fsp.readdir(otherAssets, { withFileTypes: true });
|
|
136
123
|
const entries = await fsp.readdir(viewsDir, { withFileTypes: true });
|
|
137
124
|
|
|
138
125
|
const rendered: string[] = [];
|
|
139
126
|
|
|
140
|
-
for (const entry of entries2) {
|
|
141
|
-
if (!entry.isFile()) continue;
|
|
142
|
-
const srcPath = path.join(otherAssets, entry.name);
|
|
143
|
-
const outputPath = path.join(finalOut, entry.name);
|
|
144
|
-
|
|
145
|
-
await fsp.copyFile(srcPath, outputPath);
|
|
146
|
-
|
|
147
|
-
}
|
|
148
127
|
|
|
149
128
|
for (const entry of entries) {
|
|
150
129
|
// skip folders (partials, layouts, etc.)
|
|
@@ -190,15 +169,11 @@ export async function createStatic(req: Request, res: Response) {
|
|
|
190
169
|
}
|
|
191
170
|
await fsp.rm(outDir, { recursive: true, force: true });
|
|
192
171
|
await fsp.cp(
|
|
193
|
-
path.resolve("src/frontend/
|
|
194
|
-
path.join(finalOut, '
|
|
195
|
-
{ recursive: true }
|
|
196
|
-
);
|
|
197
|
-
await fsp.cp(
|
|
198
|
-
path.resolve("src/backend/cache"),
|
|
199
|
-
path.join(finalOut, 'cache'),
|
|
172
|
+
path.resolve("src/frontend/static"),
|
|
173
|
+
path.join(finalOut, 'static'),
|
|
200
174
|
{ recursive: true }
|
|
201
175
|
);
|
|
176
|
+
|
|
202
177
|
return res.json({
|
|
203
178
|
success: true,
|
|
204
179
|
generated: rendered,
|
|
@@ -7,7 +7,7 @@ export default router;
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
router.route("/cache/:name").get(imageOptimiser);
|
|
10
|
+
router.route("/static/cache/:name").get(imageOptimiser);
|
|
11
11
|
router.route("/createstatic").get(createStatic);
|
|
12
12
|
router.route('/addcomponent').post(addComponent);
|
|
13
13
|
router.route('/addpage').post(addPage);
|
|
@@ -18,3 +18,4 @@ router.route('/addpage').post(addPage);
|
|
|
18
18
|
|
|
19
19
|
router.route('/').get((req, res) => res.render('_'));
|
|
20
20
|
router.route('/login').get((req, res) => res.render('_login'));
|
|
21
|
+
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
<link href="/static/style.css" rel="stylesheet"/>
|
|
7
|
+
<link href="/static/style2.css" rel="stylesheet"/>
|
|
8
8
|
<title>Redvent:Login</title>
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
<img src="/cache/w_500x500.webp" alt="logo" class="w-500">
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
|
-
<script src='/global.js' type="module"></script>
|
|
27
|
+
<script src='/static/global.js' type="module"></script>
|
|
28
28
|
<script type="module">
|
|
29
29
|
|
|
30
|
-
import { parser, fetchElement, replaceElement, appendElement } from "/gardener.js";
|
|
30
|
+
import { parser, fetchElement, replaceElement, appendElement } from "/static/gardener.js";
|
|
31
31
|
</script>
|
|
32
32
|
</body>
|
|
33
33
|
</html>
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
//Standalone gardener version for no backend environment
|
|
2
|
+
|
|
3
|
+
const config = {
|
|
4
|
+
mode: 'dev',
|
|
5
|
+
hotreload: false
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let hotReloadtimeout;
|
|
9
|
+
const body = fetchElement('body');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
function applyHotReloadState() {
|
|
13
|
+
const hrcheck = fetchElement('#hrcheckbox');
|
|
14
|
+
const checkbox = fetchElement('.hrcheckbox');
|
|
15
|
+
|
|
16
|
+
if (hotReload) {
|
|
17
|
+
hrcheck.style.background = '#66e666';
|
|
18
|
+
checkbox.checked = true;
|
|
19
|
+
hotReloadtimeout = setTimeout(() => window.location.reload(), 1000);
|
|
20
|
+
} else {
|
|
21
|
+
hrcheck.style.background = 'red';
|
|
22
|
+
checkbox.checked = false;
|
|
23
|
+
clearTimeout(hotReloadtimeout);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let hotReload = localStorage.getItem('hotreload');
|
|
28
|
+
if (hotReload === null) hotReload = config.hotreload;
|
|
29
|
+
else if (hotReload === 'true') hotReload = true
|
|
30
|
+
else if (hotReload === 'false') hotReload = false
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if (config.mode === 'dev') {
|
|
36
|
+
appendElement(body, gardener({
|
|
37
|
+
t: 'p',
|
|
38
|
+
attr: {
|
|
39
|
+
style: `
|
|
40
|
+
position:fixed;
|
|
41
|
+
bottom:0;
|
|
42
|
+
right:0;
|
|
43
|
+
z-index:100;
|
|
44
|
+
background:#e5e7eb;
|
|
45
|
+
padding:8px;
|
|
46
|
+
border-radius:6px;
|
|
47
|
+
font-family:sans-serif;
|
|
48
|
+
color:black;
|
|
49
|
+
font-size:14px;
|
|
50
|
+
`
|
|
51
|
+
},
|
|
52
|
+
children: [
|
|
53
|
+
{ t: 'span', txt: 'Press ' },
|
|
54
|
+
{
|
|
55
|
+
t: 'span',
|
|
56
|
+
attr: { style: 'color:#22c55e;font-weight:bold;' },
|
|
57
|
+
txt: 'Ctrl+h'
|
|
58
|
+
},
|
|
59
|
+
{ t: 'span', txt: ' to toggle Hot Reload' },
|
|
60
|
+
{
|
|
61
|
+
t: 'form',
|
|
62
|
+
attr: {
|
|
63
|
+
id: 'hrcheckbox',
|
|
64
|
+
style: 'margin-top:6px;padding:6px;background:red;border-radius:4px;cursor:pointer;'
|
|
65
|
+
},
|
|
66
|
+
events: { click: togglehotreload },
|
|
67
|
+
children: [
|
|
68
|
+
{ t: 'label', txt: 'Hot Reload ' },
|
|
69
|
+
{
|
|
70
|
+
t: 'input',
|
|
71
|
+
cn: ['hrcheckbox'],
|
|
72
|
+
attr: { type: 'checkbox' }
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
applyHotReloadState();
|
|
80
|
+
|
|
81
|
+
document.addEventListener('keydown', function(e) {
|
|
82
|
+
// Detect Ctrl + H
|
|
83
|
+
if (e.ctrlKey && e.key.toLowerCase() === 'h') {
|
|
84
|
+
e.preventDefault(); // Stop browser from opening history
|
|
85
|
+
// Your logic here...
|
|
86
|
+
togglehotreload();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//appendElement(body, gardener())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
// togglehotreload();
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
//if (config.mode === 'dev') {
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
function togglehotreload() {
|
|
105
|
+
hotReload = !hotReload;
|
|
106
|
+
localStorage.setItem('hotreload', String(hotReload));
|
|
107
|
+
|
|
108
|
+
const hrcheck = fetchElement('#hrcheckbox');
|
|
109
|
+
const checkbox = fetchElement('.hrcheckbox');
|
|
110
|
+
|
|
111
|
+
if (hotReload) {
|
|
112
|
+
hrcheck.style.background = '#66e666';
|
|
113
|
+
checkbox.checked = true;
|
|
114
|
+
hotReloadtimeout = setTimeout(() => window.location.reload(), 1000);
|
|
115
|
+
} else {
|
|
116
|
+
hrcheck.style.background = 'red';
|
|
117
|
+
checkbox.checked = false;
|
|
118
|
+
clearTimeout(hotReloadtimeout);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function parserWindow(input) {
|
|
123
|
+
if (config.mode !== 'dev') return;
|
|
124
|
+
|
|
125
|
+
let text;
|
|
126
|
+
try {
|
|
127
|
+
text = JSON.stringify(JSON.parse(input), null, 2);
|
|
128
|
+
} catch {
|
|
129
|
+
text = input;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const result = gardener({
|
|
133
|
+
t: 'div',
|
|
134
|
+
attr: {
|
|
135
|
+
style: `
|
|
136
|
+
position:fixed;
|
|
137
|
+
top:25%;
|
|
138
|
+
left:25%;
|
|
139
|
+
width:50%;
|
|
140
|
+
height:50%;
|
|
141
|
+
background:#6b7280;
|
|
142
|
+
color:white;
|
|
143
|
+
border:2px solid black;
|
|
144
|
+
border-radius:8px;
|
|
145
|
+
z-index:90;
|
|
146
|
+
display:flex;
|
|
147
|
+
flex-direction:column;
|
|
148
|
+
justify-content:space-between;
|
|
149
|
+
`
|
|
150
|
+
},
|
|
151
|
+
children: [
|
|
152
|
+
{
|
|
153
|
+
t: 'div',
|
|
154
|
+
attr: {
|
|
155
|
+
style: `
|
|
156
|
+
background:#e5e7eb;
|
|
157
|
+
color:black;
|
|
158
|
+
padding:10px;
|
|
159
|
+
display:flex;
|
|
160
|
+
justify-content:space-between;
|
|
161
|
+
align-items:center;
|
|
162
|
+
border-top-left-radius:8px;
|
|
163
|
+
border-top-right-radius:8px;
|
|
164
|
+
`
|
|
165
|
+
},
|
|
166
|
+
children: [
|
|
167
|
+
{ t: 'h3', txt: 'Parser Window' },
|
|
168
|
+
{
|
|
169
|
+
t: 'button',
|
|
170
|
+
txt: 'Copy JSON',
|
|
171
|
+
attr: {
|
|
172
|
+
style: `
|
|
173
|
+
padding:6px 10px;
|
|
174
|
+
background:#f87171;
|
|
175
|
+
border-radius:6px;
|
|
176
|
+
cursor:pointer;
|
|
177
|
+
`
|
|
178
|
+
},
|
|
179
|
+
events: {
|
|
180
|
+
click: () => copyTextToClipboard(text)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
t: 'pre',
|
|
187
|
+
txt: text,
|
|
188
|
+
attr: {
|
|
189
|
+
style: `
|
|
190
|
+
padding:12px;
|
|
191
|
+
overflow:auto;
|
|
192
|
+
font-size:12px;
|
|
193
|
+
white-space:pre-wrap;
|
|
194
|
+
`
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
appendElement(body, result);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
async function copyTextToClipboard(txt) {
|
|
206
|
+
try {
|
|
207
|
+
await navigator.clipboard.writeText(txt);
|
|
208
|
+
alert('Component copied to clipboard');
|
|
209
|
+
} catch (err) {
|
|
210
|
+
console.error('Clipboard copy failed', err);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
export function fetchElement(param) {
|
|
218
|
+
return document.querySelector(param);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function appendElement(parent, child) {
|
|
222
|
+
if (typeof parent === 'string') parent = fetchElement(parent);
|
|
223
|
+
parent.appendChild(child);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function createElement(type, classname) {
|
|
227
|
+
let element = document.createElement(type);
|
|
228
|
+
if (classname)
|
|
229
|
+
element.classList.add(...classname);
|
|
230
|
+
return element;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function insertText(element, text) {
|
|
234
|
+
element.innerText = text;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function replaceElement(original, New) {
|
|
238
|
+
if (typeof original === 'string') original = fetchElement(original);
|
|
239
|
+
original.replaceWith(New);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function gardener(Dom) {
|
|
243
|
+
|
|
244
|
+
if (Dom.nodeType === 1) return Dom;
|
|
245
|
+
// detect if this is an SVG element
|
|
246
|
+
const isSVG = [
|
|
247
|
+
'svg', 'path', 'circle', 'rect', 'line', 'polygon', 'polyline', 'g', 'defs', 'clipPath', 'use'
|
|
248
|
+
].includes(Dom.t);
|
|
249
|
+
|
|
250
|
+
// create element accordingly
|
|
251
|
+
let element;
|
|
252
|
+
|
|
253
|
+
if (isSVG) {
|
|
254
|
+
element = document.createElementNS('http://www.w3.org/2000/svg', Dom.t);
|
|
255
|
+
if (Dom.cn)
|
|
256
|
+
element.classList.add(...Dom.cn);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
element = createElement(Dom.t, Dom.cn);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// text content (skip for SVG like <path>)
|
|
263
|
+
if (Dom.txt) {
|
|
264
|
+
insertText(element, Dom.txt);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// apply attributes safely
|
|
268
|
+
const propertyNames = new Set([
|
|
269
|
+
'value', 'selected', 'muted', 'disabled',
|
|
270
|
+
'selectedIndex', 'volume', // etc.
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
if (Dom.attr) {
|
|
274
|
+
for (const [key, value] of Object.entries(Dom.attr)) {
|
|
275
|
+
if (isSVG || key.startsWith('data-') || key.startsWith('aria-')) {
|
|
276
|
+
element.setAttribute(key, value);
|
|
277
|
+
} else if (key in element && !propertyNames.has(key)) {
|
|
278
|
+
// Prefer property for known safe cases
|
|
279
|
+
try { element[key] = value === '' ? true : value; } catch (e) { element.setAttribute(key, value); }
|
|
280
|
+
} else {
|
|
281
|
+
element.setAttribute(key, value);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (Dom.events) {
|
|
287
|
+
Object.entries(Dom.events).forEach(([eventName, handler]) => {
|
|
288
|
+
element.addEventListener(eventName, handler);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// recursively handle children
|
|
293
|
+
if (Dom.children) {
|
|
294
|
+
Dom.children.forEach(child => appendElement(element, gardener(child)));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return element;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function cleanStringAndList(input) {
|
|
301
|
+
const pattern = /\?"?(\w+)"?\?/g;
|
|
302
|
+
const vars = new Set();
|
|
303
|
+
let match;
|
|
304
|
+
|
|
305
|
+
while ((match = pattern.exec(input)) !== null) {
|
|
306
|
+
vars.add(match[1]);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Replace ?var? with "+var+" and clean up resulting empty strings or double quotes
|
|
310
|
+
const cleanedString = input
|
|
311
|
+
.replace(pattern, '"+$1+"')
|
|
312
|
+
.replace(/^""\+/, '')
|
|
313
|
+
.replace(/\+""$/, '');
|
|
314
|
+
|
|
315
|
+
return {
|
|
316
|
+
cleanedString,
|
|
317
|
+
extractedList: [...vars].join(', ')
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function generateFile(obj) {
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
const formatted = JSON.stringify(obj, null, 2);
|
|
325
|
+
const { cleanedString, extractedList } = cleanStringAndList(formatted);
|
|
326
|
+
|
|
327
|
+
return `
|
|
328
|
+
import { gardener, fetchElement, replaceElement } from '../gardener.js'
|
|
329
|
+
|
|
330
|
+
export default function thisfun({${extractedList}}) {
|
|
331
|
+
return gardener(${cleanedString})
|
|
332
|
+
}
|
|
333
|
+
`;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
export function parser(element, isParent = true) {
|
|
340
|
+
if (typeof element === 'string') {
|
|
341
|
+
element = fetchElement(element);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
console.log(element)
|
|
345
|
+
const obj = {
|
|
346
|
+
t: element.tagName.toLowerCase(),
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// add classes if present
|
|
350
|
+
if (element.classList.length) {
|
|
351
|
+
obj.cn = Array.from(element.classList);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// add attributes if present
|
|
355
|
+
const attrs = {};
|
|
356
|
+
for (const attr of element.attributes) {
|
|
357
|
+
if (attr.name !== 'class') attrs[attr.name] = attr.value;
|
|
358
|
+
}
|
|
359
|
+
if (Object.keys(attrs).length) obj.attr = attrs;
|
|
360
|
+
// add text content (only if no children)
|
|
361
|
+
if (element.childNodes.length === 1 && element.firstChild.nodeType === Node.TEXT_NODE) {
|
|
362
|
+
obj.txt = element.textContent.trim();
|
|
363
|
+
|
|
364
|
+
if (isParent) {
|
|
365
|
+
|
|
366
|
+
parserWindow(generateFile(obj))
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return obj;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
// add children recursively
|
|
374
|
+
const children = [];
|
|
375
|
+
for (const child of element.childNodes) {
|
|
376
|
+
if (child.nodeType === Node.COMMENT_NODE) continue;
|
|
377
|
+
|
|
378
|
+
if (child.nodeType === Node.TEXT_NODE && child.textContent.trim() === '') continue;
|
|
379
|
+
|
|
380
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
381
|
+
children.push({ t: 'span', txt: child.textContent.trim() });
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
children.push(parser(child, false));
|
|
385
|
+
}
|
|
386
|
+
if (children.length) obj.children = children;
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
if (isParent) {
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
parserWindow(generateFile(obj))
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return obj
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
//Let Browser do the migration from html to json and then use copy paste
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
export function addEL(parent, event, fun) {
|
|
403
|
+
if (typeof parent === 'string') {
|
|
404
|
+
parent = fetchElement(parent);
|
|
405
|
+
}
|
|
406
|
+
parent.addEventListener(event, fun)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export function imagePreloader(images) {
|
|
410
|
+
const body = fetchElement('body')
|
|
411
|
+
images.forEach(entry => {
|
|
412
|
+
appendElement(body, gardener({
|
|
413
|
+
t: 'img',
|
|
414
|
+
cn: ['preloaderimage'],
|
|
415
|
+
attr: {
|
|
416
|
+
src: entry,
|
|
417
|
+
alt: entry
|
|
418
|
+
}
|
|
419
|
+
}));
|
|
420
|
+
|
|
421
|
+
setTimeout(() => {
|
|
422
|
+
const images = document.querySelectorAll('.preloaderimage');
|
|
423
|
+
images.forEach(entry => { entry.style.display = 'none' });
|
|
424
|
+
}, 0)
|
|
425
|
+
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
import { gardener, fetchElement, replaceElement } from '/static/gardener.js'
|
|
3
|
+
|
|
4
|
+
export default function thisfun() {
|
|
5
|
+
return gardener({
|
|
6
|
+
"t": "span",
|
|
7
|
+
"cn": [
|
|
8
|
+
"emailsvg"
|
|
9
|
+
],
|
|
10
|
+
"children": [
|
|
11
|
+
{
|
|
12
|
+
"t": "svg",
|
|
13
|
+
"cn": [
|
|
14
|
+
"icon",
|
|
15
|
+
"icon-tabler",
|
|
16
|
+
"icons-tabler-outline",
|
|
17
|
+
"icon-tabler-mail"
|
|
18
|
+
],
|
|
19
|
+
"attr": {
|
|
20
|
+
"xmlns": "http://www.w3.org/2000/svg",
|
|
21
|
+
"width": "24",
|
|
22
|
+
"height": "24",
|
|
23
|
+
"viewBox": "0 0 24 24",
|
|
24
|
+
"fill": "none",
|
|
25
|
+
"stroke": "currentColor",
|
|
26
|
+
"stroke-width": "2",
|
|
27
|
+
"stroke-linecap": "round",
|
|
28
|
+
"stroke-linejoin": "round"
|
|
29
|
+
},
|
|
30
|
+
"children": [
|
|
31
|
+
{
|
|
32
|
+
"t": "path",
|
|
33
|
+
"attr": {
|
|
34
|
+
"stroke": "none",
|
|
35
|
+
"d": "M0 0h24v24H0z",
|
|
36
|
+
"fill": "none"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"t": "path",
|
|
41
|
+
"attr": {
|
|
42
|
+
"d": "M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-10"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"t": "path",
|
|
47
|
+
"attr": {
|
|
48
|
+
"d": "M3 7l9 6l9 -6"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
})
|
|
55
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
import { gardener } from '/static/gardener.js'
|
|
3
|
+
export default function() {
|
|
4
|
+
return gardener({
|
|
5
|
+
"t": "svg",
|
|
6
|
+
"cn": [
|
|
7
|
+
"eye"
|
|
8
|
+
],
|
|
9
|
+
"attr": {
|
|
10
|
+
"xmlns": "http://www.w3.org/2000/svg",
|
|
11
|
+
"width": "24",
|
|
12
|
+
"height": "24",
|
|
13
|
+
"viewBox": "0 0 24 24",
|
|
14
|
+
"fill": "none",
|
|
15
|
+
"stroke": "currentColor",
|
|
16
|
+
"stroke-width": "2",
|
|
17
|
+
"stroke-linecap": "round",
|
|
18
|
+
"stroke-linejoin": "round"
|
|
19
|
+
},
|
|
20
|
+
"children": [
|
|
21
|
+
{
|
|
22
|
+
"t": "path",
|
|
23
|
+
"attr": {
|
|
24
|
+
"stroke": "none",
|
|
25
|
+
"d": "M0 0h24v24H0z",
|
|
26
|
+
"fill": "none"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"t": "path",
|
|
31
|
+
"attr": {
|
|
32
|
+
"d": "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"t": "path",
|
|
37
|
+
"attr": {
|
|
38
|
+
"d": "M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
})
|
|
43
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { gardener, replaceElement, fetchElement } from '/gardener.js'
|
|
2
|
-
import eyeoff from '/components/eyeoff.js'
|
|
3
|
-
import eyeon from '/components/eyeon.js'
|
|
1
|
+
import { gardener, replaceElement, fetchElement } from '/static/gardener.js'
|
|
2
|
+
import eyeoff from '/static/components/eyeoff.js'
|
|
3
|
+
import eyeon from '/static/components/eyeon.js'
|
|
4
4
|
export default function thisfun(visible) {
|
|
5
5
|
|
|
6
6
|
const svg = visible ? eyeoff() : eyeon();
|