create-gardener 1.1.7 → 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.
@@ -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
- // pretty format (2 spaces)
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) {
@@ -1,7 +1,5 @@
1
1
  //Standalone gardener version for no backend environment
2
2
 
3
-
4
-
5
3
  const config = {
6
4
  mode: 'dev',
7
5
  hotreload: false
@@ -9,57 +7,6 @@ const config = {
9
7
 
10
8
  let hotReloadtimeout;
11
9
  const body = fetchElement('body');
12
- let hotReload = localStorage.getItem('hotreload');
13
-
14
- if (hotReload === null) hotReload = config.hotreload;
15
- else if (hotReload === 'true') hotReload = true
16
- else if (hotReload === 'false') hotReload = false
17
-
18
-
19
-
20
-
21
- appendElement(body, gardener({
22
- t: 'p',
23
- cn: ['bg-gray-200', 'fixed', 'bottom-0', 'z-100', 'right-0', 'border-b-1', 'p-2', 'rounded-md'],
24
- children: [
25
- {
26
- t: 'span',
27
- txt: 'Press '
28
- },
29
- {
30
- t: 'span',
31
- cn: ['text-green-500', 'font-bold'],
32
- txt: 'Ctrl+h'
33
- },
34
- {
35
- t: 'span',
36
- txt: ' to toggle Hot Reload'
37
- },
38
- {
39
- t: 'form',
40
- attr: {
41
- id: 'hrcheckbox',
42
- },
43
- events: {
44
- click: () => togglehotreload()
45
- },
46
- cn: ['p-2', 'bg-red-300'],
47
- children: [{
48
- t: 'label',
49
- txt: 'Hot Reload ',
50
- }
51
- , {
52
- t: 'input',
53
- cn: ['hrcheckbox'],
54
- attr: {
55
- type: 'checkbox'
56
- }
57
- }]
58
- }
59
- ]
60
- }))
61
-
62
- //appendElement(body, gardener())
63
10
 
64
11
 
65
12
  function applyHotReloadState() {
@@ -77,20 +24,79 @@ function applyHotReloadState() {
77
24
  }
78
25
  }
79
26
 
80
- applyHotReloadState();
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
+
81
95
 
82
96
  // togglehotreload();
83
97
 
84
98
 
85
99
 
86
- document.addEventListener('keydown', function(e) {
87
- // Detect Ctrl + H
88
- if (e.ctrlKey && e.key.toLowerCase() === 'h') {
89
- e.preventDefault(); // Stop browser from opening history
90
- // Your logic here...
91
- togglehotreload();
92
- }
93
- });
94
100
 
95
101
  //if (config.mode === 'dev') {
96
102
 
@@ -113,48 +119,83 @@ function togglehotreload() {
113
119
  }
114
120
  }
115
121
 
116
- export function parserWindow(input) {
117
-
118
-
119
- const parsed = JSON.parse(input);
120
- const text = JSON.stringify(parsed, null, 1);
122
+ function parserWindow(input) {
121
123
  if (config.mode !== 'dev') return;
122
124
 
125
+ let text;
126
+ try {
127
+ text = JSON.stringify(JSON.parse(input), null, 2);
128
+ } catch {
129
+ text = input;
130
+ }
123
131
 
124
132
  const result = gardener({
125
133
  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'],
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
+ },
127
151
  children: [
128
152
  {
129
153
  t: 'div',
130
- cn: ['bg-gray-200', 'h-15', 'text-black', 'rounded-t-lg', 'flex', 'items-center', 'justify-around'],
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
+ },
131
166
  children: [
132
- {
133
- t: 'h3',
134
- cn: ['font-bold'],
135
- txt: 'Parser Window'
136
- },
167
+ { t: 'h3', txt: 'Parser Window' },
137
168
  {
138
169
  t: 'button',
139
- cn: ['p-2', 'bg-red-300', 'rounded-lg', 'cursor-pointer'],
140
- txt: 'Add Component',
170
+ txt: 'Copy JSON',
141
171
  attr: {
142
- id: 'copybtn'
172
+ style: `
173
+ padding:6px 10px;
174
+ background:#f87171;
175
+ border-radius:6px;
176
+ cursor:pointer;
177
+ `
143
178
  },
144
179
  events: {
145
- click: (e) => { copyTextToClipboard(text) }
180
+ click: () => copyTextToClipboard(text)
146
181
  }
147
182
  }
148
183
  ]
149
184
  },
150
185
  {
151
186
  t: 'pre',
152
- cn: ['p-5', 'overflow-scroll', 'text-sm'],
153
- txt: text
187
+ txt: text,
188
+ attr: {
189
+ style: `
190
+ padding:12px;
191
+ overflow:auto;
192
+ font-size:12px;
193
+ white-space:pre-wrap;
194
+ `
195
+ }
154
196
  }
155
197
  ]
156
- })
157
-
198
+ });
158
199
 
159
200
  appendElement(body, result);
160
201
  }
@@ -164,7 +205,7 @@ export function parserWindow(input) {
164
205
  async function copyTextToClipboard(txt) {
165
206
  try {
166
207
  await navigator.clipboard.writeText(txt);
167
- console.log('Component copied to clipboard');
208
+ alert('Component copied to clipboard');
168
209
  } catch (err) {
169
210
  console.error('Clipboard copy failed', err);
170
211
  }
@@ -178,9 +219,7 @@ export function fetchElement(param) {
178
219
  }
179
220
 
180
221
  export function appendElement(parent, child) {
181
- if (typeof parent === 'string') {
182
- parent = fetchElement(parent);
183
- }
222
+ if (typeof parent === 'string') parent = fetchElement(parent);
184
223
  parent.appendChild(child);
185
224
  }
186
225
 
@@ -196,9 +235,7 @@ export function insertText(element, text) {
196
235
  }
197
236
 
198
237
  export function replaceElement(original, New) {
199
- if (typeof original === 'string') {
200
- original = fetchElement(original);
201
- }
238
+ if (typeof original === 'string') original = fetchElement(original);
202
239
  original.replaceWith(New);
203
240
  }
204
241
 
@@ -260,12 +297,51 @@ export function gardener(Dom) {
260
297
  return element;
261
298
  }
262
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
+
263
339
  export function parser(element, isParent = true) {
264
340
  if (typeof element === 'string') {
265
341
  element = fetchElement(element);
266
- // If user passes raw HTML string
267
342
  }
268
343
 
344
+ console.log(element)
269
345
  const obj = {
270
346
  t: element.tagName.toLowerCase(),
271
347
  };
@@ -286,28 +362,43 @@ export function parser(element, isParent = true) {
286
362
  obj.txt = element.textContent.trim();
287
363
 
288
364
  if (isParent) {
289
- parserWindow(JSON.stringify(obj))
365
+
366
+ parserWindow(generateFile(obj))
290
367
  }
291
368
 
292
369
  return obj;
293
370
  }
294
371
 
372
+
295
373
  // add children recursively
296
374
  const children = [];
297
- for (const child of element.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
+ }
298
384
  children.push(parser(child, false));
299
385
  }
300
386
  if (children.length) obj.children = children;
301
387
 
302
388
 
303
389
  if (isParent) {
304
- parserWindow(JSON.stringify(obj))
390
+
391
+
392
+ parserWindow(generateFile(obj))
305
393
  }
306
394
 
307
395
  return obj
396
+
397
+
308
398
  //Let Browser do the migration from html to json and then use copy paste
309
399
  }
310
400
 
401
+
311
402
  export function addEL(parent, event, fun) {
312
403
  if (typeof parent === 'string') {
313
404
  parent = fetchElement(parent);
@@ -315,8 +406,6 @@ export function addEL(parent, event, fun) {
315
406
  parent.addEventListener(event, fun)
316
407
  }
317
408
 
318
-
319
-
320
409
  export function imagePreloader(images) {
321
410
  const body = fetchElement('body')
322
411
  images.forEach(entry => {
@@ -338,3 +427,4 @@ export function imagePreloader(images) {
338
427
  }
339
428
 
340
429
 
430
+
@@ -337,11 +337,56 @@ export function gardener(Dom) {
337
337
  return element;
338
338
  }
339
339
 
340
+
341
+ function cleanStringAndList(input) {
342
+ const pattern = /\?"?(\w+)"?\?/g;
343
+ const vars = new Set();
344
+ let match;
345
+
346
+ while ((match = pattern.exec(input)) !== null) {
347
+ vars.add(match[1]);
348
+ }
349
+
350
+ // Replace ?var? with "+var+" and clean up resulting empty strings or double quotes
351
+ const cleanedString = input
352
+ .replace(pattern, '"+$1+"')
353
+ .replace(/^""\+/, '')
354
+ .replace(/\+""$/, '');
355
+
356
+ return {
357
+ cleanedString,
358
+ extractedList: [...vars].join(', ')
359
+ };
360
+ }
361
+
362
+ function generateFile(obj) {
363
+
364
+
365
+ const formatted = JSON.stringify(obj, null, 2);
366
+ const { cleanedString, extractedList } = cleanStringAndList(formatted);
367
+
368
+ return `
369
+ import { gardener, fetchElement, replaceElement } from '../gardener.js'
370
+
371
+ export default function thisfun({${extractedList}}) {
372
+ return gardener(${cleanedString})
373
+ }
374
+ `;
375
+ }
376
+
377
+
378
+ // Example:
379
+ // const result = cleanStringAndList('hi "{ritish}" how are you');
380
+ // console.log(result.cleanedString); // "hi ritish how are you"
381
+ // console.log(result.extractedList); // ["ritish"]
382
+
383
+
340
384
  export function parser(element, isParent = true) {
341
385
  if (typeof element === 'string') {
342
386
  element = fetchElement(element);
343
387
  }
344
388
 
389
+ console.log(element)
345
390
  const obj = {
346
391
  t: element.tagName.toLowerCase(),
347
392
  };
@@ -362,25 +407,39 @@ export function parser(element, isParent = true) {
362
407
  obj.txt = element.textContent.trim();
363
408
 
364
409
  if (isParent) {
365
- parserWindow(JSON.stringify(obj))
410
+
411
+ parserWindow(generateFile(obj))
366
412
  }
367
413
 
368
414
  return obj;
369
415
  }
370
416
 
417
+
371
418
  // add children recursively
372
419
  const children = [];
373
- for (const child of element.children) {
420
+ for (const child of element.childNodes) {
421
+ if (child.nodeType === Node.COMMENT_NODE) continue;
422
+
423
+ if (child.nodeType === Node.TEXT_NODE && child.textContent.trim() === '') continue;
424
+
425
+ if (child.nodeType === Node.TEXT_NODE) {
426
+ children.push({ t: 'span', txt: child.textContent.trim() });
427
+ continue;
428
+ }
374
429
  children.push(parser(child, false));
375
430
  }
376
431
  if (children.length) obj.children = children;
377
432
 
378
433
 
379
434
  if (isParent) {
380
- parserWindow(JSON.stringify(obj))
435
+
436
+
437
+ parserWindow(generateFile(obj))
381
438
  }
382
439
 
383
440
  return obj
441
+
442
+
384
443
  //Let Browser do the migration from html to json and then use copy paste
385
444
  }
386
445