create-gardener 1.1.13 → 2.0.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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/starter.js +5 -2
  3. package/template/.env +0 -0
  4. package/template/buildHelper.js +3 -0
  5. package/template/jsconfig.json +27 -0
  6. package/template/package.json +6 -5
  7. package/template/src/backend/controllers/gardener/addComponent.ts +27 -0
  8. package/template/src/backend/controllers/gardener/addPage.ts +60 -0
  9. package/template/src/backend/controllers/gardener/createStatic.ts +84 -0
  10. package/template/src/backend/controllers/gardener/imageOptimiser.ts +67 -0
  11. package/template/src/backend/controllers/gardener/index.ts +4 -0
  12. package/template/src/backend/libs/generateWebp.ts +1 -0
  13. package/template/src/backend/routes/gardener.route.ts +15 -5
  14. package/template/src/backend/server.ts +8 -10
  15. package/template/src/frontend/assets/favicon.png +0 -0
  16. package/template/src/frontend/frontendtemplate.ejs +5 -17
  17. package/template/src/frontend/static/cache/favicon_500x500.webp +0 -0
  18. package/template/src/frontend/static/cache/favicon_50x50.webp +0 -0
  19. package/template/src/frontend/static/cache/gardener_50x50.webp +0 -0
  20. package/template/src/frontend/static/components/copybtn.js +86 -0
  21. package/template/src/frontend/static/components/nonui/api.js +33 -16
  22. package/template/src/frontend/static/components/nonui/navigation.js +59 -0
  23. package/template/src/frontend/static/components/secondtest.js +6 -0
  24. package/template/src/frontend/static/components/{emailsvg.js → testdd.js} +7 -7
  25. package/template/src/frontend/static/gardener.js +0 -388
  26. package/template/src/frontend/static/gardenerConfig.js +1 -0
  27. package/template/src/frontend/static/gardenerDev.js +408 -0
  28. package/template/src/frontend/static/global.js +2 -56
  29. package/template/src/frontend/static/pages/_.js +13 -0
  30. package/template/src/frontend/static/pages/_get-started.js +5 -0
  31. package/template/src/frontend/static/style.css +1039 -1
  32. package/template/src/frontend/static/style2.css +1 -1
  33. package/template/src/frontend/static/zod.js +8 -0
  34. package/template/src/frontend/views/_.ejs +96 -216
  35. package/template/src/frontend/views/_get-started.ejs +25 -0
  36. package/template/src/frontend/views/partials/icons/clipboard.ejs +1 -0
  37. package/template/src/frontend/views/partials/icons/clipboardok.ejs +1 -0
  38. package/template/tsconfig.json +1 -1
  39. package/template/src/backend/controllers/gardener.controller.ts +0 -193
  40. package/template/src/frontend/gardenerST.js +0 -431
  41. package/template/src/frontend/static/components/eyeoff.js +0 -50
  42. package/template/src/frontend/static/components/eyeon.js +0 -43
  43. package/template/src/frontend/static/components/passwordBox.js +0 -105
  44. package/template/src/frontend/views/_login.ejs +0 -75
  45. package/template/src/frontend/views/partials/loader.ejs +0 -3
@@ -0,0 +1,408 @@
1
+ import { mode } from '/static/gardenerConfig.js'
2
+ import { gardener, appendElement, fetchElement } from '/static/gardener.js'
3
+
4
+ const body = fetchElement('body');
5
+ let hotReloadtimeout;
6
+
7
+ const config = {
8
+ componentdir: 'static/components',
9
+ hotreload: false
10
+ }
11
+
12
+
13
+
14
+ let hotReload;
15
+ const localStore = localStorage.getItem('hotreload');
16
+
17
+ if (localStore === null) hotReload = config.hotreload;
18
+ else if (localStore === 'true') hotReload = true
19
+ else if (localStore === 'false') hotReload = false
20
+
21
+
22
+
23
+ const addPagebtn = gardener({
24
+ t: 'button',
25
+ cn: ['pb-1.5', 'flex', 'items-center', 'justify-center', 'h-15', 'w-15', 'bg-green-300', 'fixed', 'bottom-22', 'right-2', 'rounded-full', 'text-5xl'],
26
+ children: [{ t: 'span', txt: '+' }],
27
+ events: {
28
+ click: opnPagedialog
29
+ }
30
+ });
31
+
32
+ if (mode === 'dev') {
33
+ appendElement(body, addPagebtn);
34
+
35
+
36
+ appendElement(body, gardener({
37
+ t: 'p',
38
+ cn: ['bg-gray-200', 'fixed', 'bottom-0', 'z-100', 'right-0', 'border-b-1', 'p-2', 'rounded-md'],
39
+ children: [
40
+ {
41
+ t: 'span',
42
+ txt: 'Press '
43
+ },
44
+ {
45
+ t: 'span',
46
+ cn: ['text-green-500', 'font-bold'],
47
+ txt: 'Alt+h'
48
+ },
49
+ {
50
+ t: 'span',
51
+ txt: ' to toggle Hot Reload'
52
+ },
53
+ {
54
+ t: 'form',
55
+ attr: {
56
+ id: 'hrcheckbox',
57
+ },
58
+ events: {
59
+ click: () => togglehotreload()
60
+ },
61
+ cn: ['p-2', 'bg-red-300'],
62
+ children: [{
63
+ t: 'label',
64
+ txt: 'Hot Reload ',
65
+ }
66
+ , {
67
+ t: 'input',
68
+ cn: ['hrcheckbox'],
69
+ attr: {
70
+ type: 'checkbox'
71
+ }
72
+ }]
73
+ }
74
+ ]
75
+ }))
76
+ }
77
+
78
+ //appendElement(body, gardener())
79
+
80
+
81
+ togglehotreload();
82
+
83
+ document.addEventListener('keydown', function(e) {
84
+ // Detect Ctrl + H
85
+ if (e.altKey && e.key.toLowerCase() === 'h') {
86
+ e.preventDefault(); // Stop browser from opening history
87
+ // Your logic here...
88
+ togglehotreload();
89
+ }
90
+ });
91
+
92
+
93
+
94
+ function togglehotreload() {
95
+ const hr = hotReload;
96
+ const hrcheck = fetchElement('#hrcheckbox');
97
+
98
+ localStorage.setItem('hotreload', hr);
99
+
100
+ hotReload = !hotReload;
101
+
102
+ if (hr) {
103
+ hrcheck.style.background = '#66e666';
104
+ fetchElement('.hrcheckbox').checked = true;
105
+ localStorage.setItem('hotreload', 'true');
106
+ hotReloadtimeout = setTimeout(() => window.location.reload(), 1000);
107
+ }
108
+ else {
109
+ hrcheck.style.background = 'red';
110
+ fetchElement('.hrcheckbox').checked = false;
111
+ localStorage.setItem('hotreload', 'false');
112
+ clearTimeout(hotReloadtimeout);
113
+ }
114
+
115
+ //localStorage.setItem('hotreload', hotReload);
116
+ }
117
+
118
+
119
+
120
+ export function parserWindow(text) {
121
+ if (mode !== 'dev') return;
122
+
123
+
124
+ const result = gardener({
125
+ t: 'div',
126
+ cn: ['fixed', 'border-2', 'border-black', 'bg-gray-500', 'text-white', 'rounded-lg', 'z-90', 'w-2/4', 'h-2/4', 'left-1/4', 'flex', 'flex-col', 'justify-between', 'top-1/4'],
127
+ children: [
128
+ {
129
+ t: 'div',
130
+ cn: ['bg-gray-200', 'h-15', 'text-black', 'rounded-t-lg', 'flex', 'items-center', 'justify-around'],
131
+ children: [
132
+ {
133
+ t: 'h3',
134
+ cn: ['font-bold'],
135
+ txt: 'Parser Window'
136
+ },
137
+ {
138
+ t: 'div',
139
+ cn: ['flex', 'gap-3'],
140
+ children: [
141
+ {
142
+ t: 'button',
143
+ cn: ['p-2', 'bg-green-300', 'rounded-lg', 'cursor-pointer'],
144
+ txt: 'Copy Component',
145
+ attr: { id: 'copybtn' },
146
+ events: {
147
+ click: () => { navigator.clipboard.writeText(text); fetchElement('#copybtn').innerText = 'copied'; }
148
+ }
149
+ },
150
+ {
151
+ t: 'button',
152
+ cn: ['p-2', 'bg-red-300', 'rounded-lg', 'cursor-pointer'],
153
+ txt: 'Add Component',
154
+ events: {
155
+ click: addComponentForm
156
+ }
157
+ }
158
+ ]
159
+ }
160
+ ]
161
+ },
162
+ {
163
+ t: 'p',
164
+ cn: ['p-5', 'overflow-scroll'],
165
+ txt: text
166
+ },
167
+ ]
168
+ })
169
+
170
+ function addComponentForm() {
171
+ result.remove()
172
+
173
+ const compform = gardener({
174
+ t: 'form',
175
+ events: {
176
+ submit: (event) => {
177
+ event.preventDefault()
178
+ addComponent(text, `${fetchElement('.componentInp').value}`)
179
+ compform.remove();
180
+ }
181
+ },
182
+ cn: ['fixed', 'left-2/5', 'bg-gray-500', 'rounded-lg', 'block', 'top-2/5', 'p-2'],
183
+ children: [
184
+ {
185
+ t: 'input',
186
+ cn: ['bg-white', 'componentInp'],
187
+ attr: {
188
+ type: 'text',
189
+ placeholder: 'Component Name'
190
+ }
191
+ }
192
+ ]
193
+ });
194
+ appendElement(body, compform);
195
+
196
+ fetchElement('.componentInp').focus();
197
+ //setTimeout(() => result.remove(), 500);
198
+ }
199
+
200
+ appendElement(body, result);
201
+ }
202
+
203
+
204
+
205
+ async function addComponent(txt, path) {
206
+ // await navigator.clipboard.writeText(txt);
207
+ try {
208
+ const res = await fetch('/addcomponent', {
209
+ method: 'POST',
210
+ headers: {
211
+ "Content-Type": 'application/json'
212
+ },
213
+ body: JSON.stringify({ component: generateFile(txt, path), path: `${config.componentdir}/${path}.js` })
214
+ })
215
+
216
+ if (!res.ok) console.error('wrong');
217
+
218
+ const data = await res.json()
219
+ console.log(data);
220
+
221
+ }
222
+ catch (err) {
223
+ console.error(err);
224
+ }
225
+
226
+ }
227
+
228
+ function opnPagedialog(btn = true) {
229
+ if (btn) {
230
+ const dialog = gardener({
231
+ t: 'form', cn: ['addpageform', 'fixed', 'left-2/5', 'bg-gray-200', 'rounded-lg', 'block', 'top-2/5', 'p-2', 'flex', 'flex-col', 'p-5', 'gap-2'], events: {
232
+ submit: async (e) => {
233
+ try {
234
+ e.preventDefault()
235
+ const data = new FormData(e.target);
236
+ const input = Object.fromEntries(data.entries());
237
+ console.log(input)
238
+
239
+ const response = await fetch('/addpage', {
240
+ method: 'POST',
241
+ headers: {
242
+ "Content-Type": 'application/json'
243
+ },
244
+ body: JSON.stringify(input)
245
+ }).then(res => res.json())
246
+ console.log(response)
247
+ opnPagedialog(false)
248
+ window.location.href = `${input.page}`
249
+ }
250
+ catch (err) {
251
+ console.log(err)
252
+ }
253
+
254
+ }
255
+ }, children: [{
256
+ t: 'label',
257
+ txt: 'ENTER PATH FOR NEW PAGE'
258
+ }, { t: 'input', attr: { name: 'page' }, cn: ['pathinput'] }]
259
+
260
+ })
261
+
262
+ console.log('test')
263
+ appendElement(body, dialog);
264
+ fetchElement('.pathinput').focus();
265
+ }
266
+ else {
267
+ console.log('removed')
268
+ fetchElement('.addpageform').remove();
269
+ }
270
+ }
271
+
272
+
273
+ function cleanStringAndList(input) {
274
+ const pattern = /\?"?(\w+)"?\?/g;
275
+ const vars = new Set();
276
+ let match;
277
+
278
+ while ((match = pattern.exec(input)) !== null) {
279
+ vars.add(match[1]);
280
+ }
281
+
282
+ // Replace ?var? with "+var+" and clean up resulting empty strings or double quotes
283
+ const cleanedString = input
284
+ .replace(pattern, '"+$1+"')
285
+ .replace(/^""\+/, '')
286
+ .replace(/\+""$/, '');
287
+
288
+ return {
289
+ cleanedString,
290
+ extractedList: [...vars].join(', ')
291
+ };
292
+ }
293
+
294
+ function generateFile(obj, name) {
295
+
296
+
297
+ const { cleanedString, extractedList } = cleanStringAndList(obj);
298
+
299
+ if (extractedList.length === 0) return `
300
+ import { gardener, fetchElement, replaceElement } from '../gardener.js'
301
+
302
+ export function ${name}() {
303
+ return gardener(${cleanedString})
304
+ }
305
+ `;
306
+
307
+ return `
308
+ import { gardener, fetchElement, replaceElement } from '../gardener.js'
309
+
310
+ export function ${name}({${extractedList}}) {
311
+ return gardener(${cleanedString})
312
+ }
313
+ `;
314
+ }
315
+
316
+
317
+ // console.log(result.extractedList); // ["ritish"]
318
+
319
+
320
+ export function parser(element, isParent = true) {
321
+ if (typeof element === 'string') {
322
+ element = fetchElement(element);
323
+ }
324
+
325
+ console.log(element)
326
+ const obj = {
327
+ t: element.tagName.toLowerCase(),
328
+ };
329
+
330
+ // add classes if present
331
+ if (element.classList.length) {
332
+ obj.cn = Array.from(element.classList);
333
+ }
334
+
335
+ // add attributes if present
336
+ const attrs = {};
337
+ for (const attr of element.attributes) {
338
+ if (attr.name !== 'class') attrs[attr.name] = attr.value;
339
+ }
340
+ if (Object.keys(attrs).length) obj.attr = attrs;
341
+ // add text content (only if no children)
342
+ if (element.childNodes.length === 1 && element.firstChild.nodeType === Node.TEXT_NODE) {
343
+ obj.txt = element.textContent.trim();
344
+
345
+ if (isParent) {
346
+
347
+ parserWindow(JSON.stringify(obj, null, 2))
348
+ }
349
+
350
+ return obj;
351
+ }
352
+
353
+
354
+ // add children recursively
355
+ const children = [];
356
+ for (const child of element.childNodes) {
357
+ if (child.nodeType === Node.COMMENT_NODE) continue;
358
+
359
+ if (child.nodeType === Node.TEXT_NODE && child.textContent.trim() === '') continue;
360
+
361
+ if (child.nodeType === Node.TEXT_NODE) {
362
+ children.push({ t: 'span', txt: child.textContent.trim() });
363
+ continue;
364
+ }
365
+ children.push(parser(child, false));
366
+ }
367
+ if (children.length) obj.children = children;
368
+
369
+
370
+ if (isParent) {
371
+
372
+
373
+ parserWindow(JSON.stringify(obj, null, 2))
374
+ }
375
+
376
+ return obj
377
+
378
+
379
+ //Let Browser do the migration from html to json and then use copy paste
380
+ }
381
+
382
+ export function addEl(parent, event, fun) {
383
+ if (typeof parent === 'string') {
384
+ parent = fetchElement(parent);
385
+ }
386
+ parent.addEventListener(event, fun)
387
+ }
388
+
389
+ export class State {
390
+ constructor(value) {
391
+ this.value = value;
392
+ this.cb = [];
393
+ }
394
+ registerCb(cb) {
395
+ cb(this.value);
396
+ this.cb.push(cb);
397
+ }
398
+ setTo(val) {
399
+ this.value = val;
400
+ this.cb.forEach(cb => { cb(val) });
401
+ }
402
+ }
403
+
404
+
405
+ export function log(target) {
406
+ console.log(target)
407
+ }
408
+
@@ -1,58 +1,4 @@
1
- import { parser, fetchElement, replaceElement, gardener, appendElement } from './gardener.js'
1
+ import { nextPagehandler, pageloader } from '/static/components/nonui/navigation.js';
2
2
 
3
- const body = fetchElement('#body')
4
-
5
- nextPagehandler();
6
3
  pageloader();
7
-
8
-
9
- function nextPagehandler() {
10
- const anchor = document.querySelectorAll('a')
11
- anchor.forEach(link => {
12
-
13
- link.addEventListener('click', (e) => {
14
-
15
- //event delegation
16
- const link = e.target.closest('a');
17
- if (!link) return;
18
- if (link.target === '_blank') return;
19
- //event delegation
20
-
21
- e.preventDefault();
22
- appendElement(body, gardener({
23
- t: 'div',
24
- cn: ['tempnpdiv', 'top-0', 'left-[100vw]', 'absolute', 'h-screen', 'w-screen', 'shadow-[30px_0_60px_15px_rgb(0,0,0)]'],
25
- }))
26
- const width = window.innerWidth
27
- console.log(width)
28
- body.style.transition = '.2s';
29
- body.style.transform = `translateX(-${width}px)`
30
- setTimeout(() => {
31
- window.location.href = link.href
32
- }, 200)
33
- })
34
- })
35
-
36
- window.addEventListener('pagehide', () => {
37
- setTimeout(() => {
38
- body.style.transform = 'translateX(0px)';
39
- setTimeout(() => {
40
- fetchElement('.tempnpdiv').remove()
41
-
42
- }, 200)
43
- }, 200);
44
- });
45
-
46
- }
47
-
48
- function pageloader() {
49
- const loader = fetchElement('.loader');
50
- loader.style.transition = '.4s';
51
- loader.style.opacity = '0';
52
- setTimeout(() => loader.remove(), 400)
53
-
54
- }
55
-
56
- //console.log('hellooo');
57
- //parser(fetchElement('.hero'));
58
- //parser(fetchElement('nav'));
4
+ nextPagehandler();
@@ -0,0 +1,13 @@
1
+ import { copybtn } from "../components/copybtn.js";
2
+ import addNotification from "../components/notification.js";
3
+ import { gardener, fetchElement, replaceElement, appendElement } from "/static/gardener.js";
4
+ import { log, parser, addEl, State } from "/static/gardenerDev.js"
5
+
6
+ addEl('.copybtn', 'click', () => {
7
+ navigator.clipboard.writeText(fetchElement('.initCommand').innerText)
8
+ replaceElement('.copybtn', copybtn());
9
+ addNotification({ status: 'success', message: 'Copied' })
10
+ })
11
+
12
+
13
+
@@ -0,0 +1,5 @@
1
+ import { gardener, fetchElement, replaceElement, appendElement } from "/static/gardener.js";
2
+ import { log, parser, addEl, State } from "/static/gardenerDev.js"
3
+
4
+
5
+