create-gardener 2.1.3 → 2.1.5
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 +108 -302
- package/package.json +1 -1
- package/template/.env +3 -0
- package/template/README.md +181 -0
- package/template/buildHelper.js +5 -0
- package/template/src/backend/controllers/gardener/hotReload.ts +34 -0
- package/template/src/backend/controllers/gardener/imageOptimiser.ts +114 -25
- package/template/src/backend/controllers/gardener/index.ts +1 -0
- package/template/src/backend/routes/gardener.route.ts +2 -1
- package/template/src/backend/server.ts +19 -1
- package/template/src/frontend/assets/remote/betterway.jpg +0 -0
- package/template/src/frontend/static/components/gardener/hotReloadbtn.js +25 -78
- package/template/src/frontend/static/gardenerDev.js +2 -18
- package/template/src/frontend/static/style.css +0 -77
- package/template/src/frontend/views/_.ejs +101 -89
- package/template/build/backend/controllers/gardener/addComponent.d.ts +0 -8
- package/template/build/backend/controllers/gardener/addComponent.d.ts.map +0 -1
- package/template/build/backend/controllers/gardener/addComponent.js +0 -19
- package/template/build/backend/controllers/gardener/addComponent.js.map +0 -1
- package/template/build/backend/controllers/gardener/addPage.d.ts +0 -3
- package/template/build/backend/controllers/gardener/addPage.d.ts.map +0 -1
- package/template/build/backend/controllers/gardener/addPage.js +0 -86
- package/template/build/backend/controllers/gardener/addPage.js.map +0 -1
- package/template/build/backend/controllers/gardener/createStatic.d.ts +0 -3
- package/template/build/backend/controllers/gardener/createStatic.d.ts.map +0 -1
- package/template/build/backend/controllers/gardener/createStatic.js +0 -63
- package/template/build/backend/controllers/gardener/createStatic.js.map +0 -1
- package/template/build/backend/controllers/gardener/imageOptimiser.d.ts +0 -3
- package/template/build/backend/controllers/gardener/imageOptimiser.d.ts.map +0 -1
- package/template/build/backend/controllers/gardener/imageOptimiser.js +0 -54
- package/template/build/backend/controllers/gardener/imageOptimiser.js.map +0 -1
- package/template/build/backend/controllers/gardener/index.d.ts +0 -6
- package/template/build/backend/controllers/gardener/index.d.ts.map +0 -1
- package/template/build/backend/controllers/gardener/index.js +0 -6
- package/template/build/backend/controllers/gardener/index.js.map +0 -1
- package/template/build/backend/controllers/gardener/saveTemplate.d.ts +0 -3
- package/template/build/backend/controllers/gardener/saveTemplate.d.ts.map +0 -1
- package/template/build/backend/controllers/gardener/saveTemplate.js +0 -36
- package/template/build/backend/controllers/gardener/saveTemplate.js.map +0 -1
- package/template/build/backend/libs/generateWebp.d.ts +0 -2
- package/template/build/backend/libs/generateWebp.d.ts.map +0 -1
- package/template/build/backend/libs/generateWebp.js +0 -16
- package/template/build/backend/libs/generateWebp.js.map +0 -1
- package/template/build/backend/routes/gardener.route.d.ts +0 -4
- package/template/build/backend/routes/gardener.route.d.ts.map +0 -1
- package/template/build/backend/routes/gardener.route.js +0 -18
- package/template/build/backend/routes/gardener.route.js.map +0 -1
- package/template/build/backend/server.d.ts +0 -2
- package/template/build/backend/server.d.ts.map +0 -1
- package/template/build/backend/server.js +0 -20
- package/template/build/backend/server.js.map +0 -1
- package/template/build/frontend/assets/favicon.png +0 -0
- package/template/build/frontend/assets/gardener.jpg +0 -0
- package/template/build/frontend/static/bundle/bundle._.js +0 -1
- package/template/build/frontend/static/bundle/bundle._about.js +0 -1
- package/template/build/frontend/static/bundle/bundle._kartik.js +0 -1
- package/template/build/frontend/static/bundle/bundle._new.js +0 -1
- package/template/build/frontend/static/bundle/bundle._ritish.js +0 -1
- package/template/build/frontend/static/cache/favicon_500x500.webp +0 -0
- package/template/build/frontend/static/cache/favicon_50x50.webp +0 -0
- package/template/build/frontend/static/cache/gardener_100x100.webp +0 -0
- package/template/build/frontend/static/cache/gardener_500x500.webp +0 -0
- package/template/build/frontend/static/cache/gardener_50x50.webp +0 -0
- package/template/build/frontend/static/components/copybtn.js +0 -99
- package/template/build/frontend/static/components/footer.js +0 -33
- package/template/build/frontend/static/components/gardener/errorBox.js +0 -47
- package/template/build/frontend/static/components/gardener/hotReloadbtn.js +0 -82
- package/template/build/frontend/static/components/gardener/pageOverlayBtn.js +0 -138
- package/template/build/frontend/static/components/gardener/parserWindow.js +0 -159
- package/template/build/frontend/static/components/nonui/api.js +0 -52
- package/template/build/frontend/static/components/nonui/navigation.js +0 -59
- package/template/build/frontend/static/components/notification.js +0 -67
- package/template/build/frontend/static/gardener.js +0 -160
- package/template/build/frontend/static/gardenerConfig.js +0 -1
- package/template/build/frontend/static/gardenerDev.js +0 -165
- package/template/build/frontend/static/global.js +0 -4
- package/template/build/frontend/static/pages/pages._.js +0 -25
- package/template/build/frontend/static/pages/pages._about.js +0 -2
- package/template/build/frontend/static/pages/pages._kartik.js +0 -2
- package/template/build/frontend/static/pages/pages._new.js +0 -2
- package/template/build/frontend/static/pages/pages._ritish.js +0 -2
- package/template/build/frontend/static/style.css +0 -2
- package/template/build/frontend/static/style2.css +0 -26
- package/template/build/frontend/style.css +0 -1045
- package/template/build/frontend/tailwind.css +0 -1
- package/template/build/frontend/views/_.ejs +0 -125
- package/template/build/frontend/views/_about.ejs +0 -126
- package/template/build/frontend/views/_kartik.ejs +0 -126
- package/template/build/frontend/views/_new.ejs +0 -126
- package/template/build/frontend/views/_ritish.ejs +0 -126
- package/template/build/frontend/views/partials/icons/clipboard.ejs +0 -1
- package/template/build/frontend/views/partials/icons/clipboardok.ejs +0 -1
- package/template/src/frontend/static/cache/favicon_500x500.webp +0 -0
- package/template/src/frontend/static/cache/favicon_50x50.webp +0 -0
- package/template/src/frontend/static/cache/gardener_100x100.webp +0 -0
- package/template/src/frontend/static/cache/gardener_500x500.webp +0 -0
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { gardener, fetchElement, appendElement } from '../../gardener.js'
|
|
2
|
-
import { gardenerError } from './errorBox.js';
|
|
3
|
-
|
|
4
|
-
const body = fetchElement('body');
|
|
5
|
-
|
|
6
|
-
const config = {
|
|
7
|
-
componentdir: 'static/components',
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
let result;
|
|
11
|
-
export function parserWindow(text) {
|
|
12
|
-
result = gardener({
|
|
13
|
-
t: 'div',
|
|
14
|
-
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'],
|
|
15
|
-
children: [
|
|
16
|
-
{
|
|
17
|
-
t: 'div',
|
|
18
|
-
cn: ['bg-gray-200', 'h-15', 'text-black', 'rounded-t-lg', 'flex', 'items-center', 'justify-around'],
|
|
19
|
-
children: [
|
|
20
|
-
{
|
|
21
|
-
t: 'h3',
|
|
22
|
-
cn: ['font-bold', 'p-5'],
|
|
23
|
-
txt: 'Parser Window'
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
t: 'div',
|
|
27
|
-
cn: ['flex', 'gap-3'],
|
|
28
|
-
children: [
|
|
29
|
-
{
|
|
30
|
-
t: 'button',
|
|
31
|
-
cn: ['p-2', 'bg-green-300', 'rounded-lg', 'cursor-pointer'],
|
|
32
|
-
txt: 'Copy Component',
|
|
33
|
-
attr: { id: 'copybtn' },
|
|
34
|
-
events: {
|
|
35
|
-
click: () => { navigator.clipboard.writeText(text); fetchElement('#copybtn').innerText = 'copied'; }
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
t: 'button',
|
|
40
|
-
cn: ['p-2', 'bg-red-300', 'rounded-lg', 'cursor-pointer'],
|
|
41
|
-
txt: 'Add Component',
|
|
42
|
-
events: {
|
|
43
|
-
click: () => addComponentForm(text)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
t: 'p',
|
|
52
|
-
cn: ['p-5', 'overflow-scroll'],
|
|
53
|
-
txt: text
|
|
54
|
-
},
|
|
55
|
-
]
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function addComponentForm(text) {
|
|
63
|
-
result.remove()
|
|
64
|
-
|
|
65
|
-
const compform = gardener({
|
|
66
|
-
t: 'form',
|
|
67
|
-
events: {
|
|
68
|
-
submit: (event) => {
|
|
69
|
-
event.preventDefault()
|
|
70
|
-
addComponent(text, `${fetchElement('.componentInp').value}`)
|
|
71
|
-
compform.remove();
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
cn: ['fixed', 'left-2/5', 'bg-gray-500', 'rounded-lg', 'block', 'top-2/5', 'p-2'],
|
|
75
|
-
children: [
|
|
76
|
-
{
|
|
77
|
-
t: 'input',
|
|
78
|
-
cn: ['bg-white', 'componentInp'],
|
|
79
|
-
attr: {
|
|
80
|
-
type: 'text',
|
|
81
|
-
placeholder: 'Component Name'
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
});
|
|
86
|
-
appendElement(body, compform);
|
|
87
|
-
|
|
88
|
-
fetchElement('.componentInp').focus();
|
|
89
|
-
//setTimeout(() => result.remove(), 500);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function addComponent(txt, path) {
|
|
93
|
-
try {
|
|
94
|
-
const res = await fetch('/addcomponent', {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
headers: {
|
|
97
|
-
"Content-Type": 'application/json'
|
|
98
|
-
},
|
|
99
|
-
body: JSON.stringify({ component: generateFile(txt, path), path: `${config.componentdir}/${path}.js` })
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
if (!res.ok) {
|
|
103
|
-
throw new Error(`Failed to add component: ${res.status} ${res.statusText}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const data = await res.json()
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
catch (err) {
|
|
110
|
-
console.error('Add Component Error:', err);
|
|
111
|
-
gardenerError(err.message || 'Failed to add component');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
function generateFile(obj, name) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const { cleanedString, extractedList } = cleanStringAndList(obj);
|
|
121
|
-
|
|
122
|
-
if (extractedList.length === 0) return `
|
|
123
|
-
import { gardener, fetchElement, replaceElement } from '../gardener.js'
|
|
124
|
-
|
|
125
|
-
export function ${name}() {
|
|
126
|
-
return gardener(${cleanedString})
|
|
127
|
-
}
|
|
128
|
-
`;
|
|
129
|
-
|
|
130
|
-
return `
|
|
131
|
-
import { gardener, fetchElement, replaceElement } from '../gardener.js'
|
|
132
|
-
|
|
133
|
-
export function ${name}({${extractedList}}) {
|
|
134
|
-
return gardener(${cleanedString})
|
|
135
|
-
}
|
|
136
|
-
`;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
function cleanStringAndList(input) {
|
|
141
|
-
const pattern = /\?"?(\w+)"?\?/g;
|
|
142
|
-
const vars = new Set();
|
|
143
|
-
let match;
|
|
144
|
-
|
|
145
|
-
while ((match = pattern.exec(input)) !== null) {
|
|
146
|
-
vars.add(match[1]);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Replace ?var? with "+var+" and clean up resulting empty strings or double quotes
|
|
150
|
-
const cleanedString = input
|
|
151
|
-
.replace(pattern, '"+$1+"')
|
|
152
|
-
.replace(/^""\+/, '')
|
|
153
|
-
.replace(/\+""$/, '');
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
cleanedString,
|
|
157
|
-
extractedList: [...vars].join(', ')
|
|
158
|
-
};
|
|
159
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
const baseName = '';
|
|
2
|
-
|
|
3
|
-
export async function Fetch(
|
|
4
|
-
path,
|
|
5
|
-
body,
|
|
6
|
-
method = 'POST'
|
|
7
|
-
) {
|
|
8
|
-
|
|
9
|
-
try {
|
|
10
|
-
|
|
11
|
-
const headers = {
|
|
12
|
-
"Content-Type": "application/json",
|
|
13
|
-
"ngrok-skip-browser-warning": 'true'
|
|
14
|
-
// "Authorization": 'Bearer ' + auth
|
|
15
|
-
}
|
|
16
|
-
let res;
|
|
17
|
-
if (method === 'GET' || method === 'DELETE')
|
|
18
|
-
res = await fetch(baseName + path, {
|
|
19
|
-
credentials: "include",
|
|
20
|
-
headers: headers,
|
|
21
|
-
method,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
else
|
|
25
|
-
res = await fetch(baseName + path, {
|
|
26
|
-
credentials: "include",
|
|
27
|
-
headers: headers,
|
|
28
|
-
method,
|
|
29
|
-
body: JSON.stringify(body),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
throw new Error(`HTTP error! status: ${res.status}`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return res
|
|
37
|
-
}
|
|
38
|
-
catch (err) {
|
|
39
|
-
console.error('Fetch Error:', err);
|
|
40
|
-
|
|
41
|
-
// Import and display error using gardenerError
|
|
42
|
-
import('../gardener/errorBox.js')
|
|
43
|
-
.then(({ gardenerError }) => {
|
|
44
|
-
gardenerError(err.message || 'Network request failed');
|
|
45
|
-
})
|
|
46
|
-
.catch(() => {
|
|
47
|
-
console.error('Error component not available:', err.message);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
throw err;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { gardener, fetchElement, appendElement } from "../../gardener.js";
|
|
2
|
-
import { mode } from "../../gardenerConfig.js";
|
|
3
|
-
|
|
4
|
-
const body = fetchElement('#main');
|
|
5
|
-
|
|
6
|
-
export function nextPagehandler() {
|
|
7
|
-
const anchor = document.querySelectorAll('a')
|
|
8
|
-
anchor.forEach(link => {
|
|
9
|
-
|
|
10
|
-
link.addEventListener('click', (e) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
e.preventDefault();
|
|
14
|
-
nextPage(link.href)
|
|
15
|
-
|
|
16
|
-
})
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
window.addEventListener('pagehide', () => {
|
|
22
|
-
setTimeout(() => {
|
|
23
|
-
body.style.transform = 'translateX(0px)';
|
|
24
|
-
setTimeout(() => {
|
|
25
|
-
try {
|
|
26
|
-
fetchElement('.tempnpdiv').remove()
|
|
27
|
-
}
|
|
28
|
-
catch (err) { }
|
|
29
|
-
|
|
30
|
-
}, 200)
|
|
31
|
-
}, 200);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function nextPage(link) {
|
|
37
|
-
|
|
38
|
-
appendElement(body, gardener({
|
|
39
|
-
t: 'div',
|
|
40
|
-
cn: ['tempnpdiv', 'top-0', 'left-[100vw]', 'fixed', 'h-screen', 'w-screen'],
|
|
41
|
-
}))
|
|
42
|
-
const width = window.innerWidth
|
|
43
|
-
console.log(width)
|
|
44
|
-
body.style.transition = '.2s';
|
|
45
|
-
body.style.transform = `translateX(-${width}px)`
|
|
46
|
-
setTimeout(() => {
|
|
47
|
-
window.location.href = link
|
|
48
|
-
}, 200)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function pageloader() {
|
|
52
|
-
const loader = fetchElement('.loader');
|
|
53
|
-
loader.style.transition = '.4s';
|
|
54
|
-
loader.style.opacity = '0';
|
|
55
|
-
if (mode !== 'dev')
|
|
56
|
-
setTimeout(() => loader.remove(), 400)
|
|
57
|
-
else
|
|
58
|
-
loader.remove();
|
|
59
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { gardener, replaceElement, fetchElement } from '../gardener.js';
|
|
2
|
-
|
|
3
|
-
export default function addNotification(noti) {
|
|
4
|
-
console.log('clicked');
|
|
5
|
-
replaceElement(fetchElement('.notification'), Notification(noti));
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function Notification(notification) {
|
|
9
|
-
if (!notification) return null;
|
|
10
|
-
|
|
11
|
-
const statusStyles = {
|
|
12
|
-
success: "bg-[#2e7d32]",
|
|
13
|
-
warning: "bg-[#ed6c02]",
|
|
14
|
-
failure: "bg-[#d32f2f]",
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return gardener({
|
|
19
|
-
"t": "div",
|
|
20
|
-
"cn": [
|
|
21
|
-
"notification",
|
|
22
|
-
"fixed",
|
|
23
|
-
"top-[-60px]",
|
|
24
|
-
"left-0",
|
|
25
|
-
"md:left-auto",
|
|
26
|
-
"md:right-[60px]",
|
|
27
|
-
"right-0",
|
|
28
|
-
"z-50",
|
|
29
|
-
"flex",
|
|
30
|
-
"justify-center",
|
|
31
|
-
"min-w-100",
|
|
32
|
-
"px-4",
|
|
33
|
-
"box-border"
|
|
34
|
-
],
|
|
35
|
-
"children": [
|
|
36
|
-
{
|
|
37
|
-
"t": "div",
|
|
38
|
-
"cn": [
|
|
39
|
-
"flex",
|
|
40
|
-
"items-center",
|
|
41
|
-
"w-full",
|
|
42
|
-
"max-w-sm",
|
|
43
|
-
"p-4",
|
|
44
|
-
"rounded-2xl",
|
|
45
|
-
"shadow-xl",
|
|
46
|
-
"text-white",
|
|
47
|
-
"backdrop-blur-md",
|
|
48
|
-
"bg-opacity-95",
|
|
49
|
-
statusStyles[notification.status]
|
|
50
|
-
],
|
|
51
|
-
"children": [
|
|
52
|
-
{
|
|
53
|
-
"t": "div",
|
|
54
|
-
"cn": [
|
|
55
|
-
"flex-1",
|
|
56
|
-
"text-sm",
|
|
57
|
-
"font-medium",
|
|
58
|
-
"tracking-wide"
|
|
59
|
-
],
|
|
60
|
-
"txt": notification.message
|
|
61
|
-
}
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { gardenerError } from "./components/gardener/errorBox.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export function fetchElement(param) {
|
|
5
|
-
const element = document.querySelector(param);
|
|
6
|
-
if (!element) {
|
|
7
|
-
console.warn(`Element not found: ${param}`);
|
|
8
|
-
}
|
|
9
|
-
return element;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function appendElement(parent, child) {
|
|
13
|
-
try {
|
|
14
|
-
if (typeof parent === 'string') {
|
|
15
|
-
parent = fetchElement(parent);
|
|
16
|
-
}
|
|
17
|
-
if (!parent) {
|
|
18
|
-
throw new Error('Parent element is null or undefined');
|
|
19
|
-
}
|
|
20
|
-
if (!child) {
|
|
21
|
-
throw new Error('Child element is null or undefined');
|
|
22
|
-
}
|
|
23
|
-
parent.appendChild(child);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
gardenerError(error);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function createElement(type, classname) {
|
|
30
|
-
try {
|
|
31
|
-
if (!type) {
|
|
32
|
-
throw new Error('Element type is required');
|
|
33
|
-
}
|
|
34
|
-
let element = document.createElement(type);
|
|
35
|
-
if (classname)
|
|
36
|
-
element.classList.add(...classname);
|
|
37
|
-
return element;
|
|
38
|
-
} catch (error) {
|
|
39
|
-
gardenerError(error);
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function insertText(element, text) {
|
|
45
|
-
if (!element) {
|
|
46
|
-
console.warn('insertText: Element is null or undefined');
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
element.textContent = text;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function replaceElement(original, New) {
|
|
53
|
-
try {
|
|
54
|
-
if (typeof original === 'string') {
|
|
55
|
-
original = fetchElement(original);
|
|
56
|
-
}
|
|
57
|
-
if (!original) {
|
|
58
|
-
throw new Error('Original element is null or undefined');
|
|
59
|
-
}
|
|
60
|
-
if (!New) {
|
|
61
|
-
throw new Error('New element is null or undefined');
|
|
62
|
-
}
|
|
63
|
-
original.replaceWith(New);
|
|
64
|
-
} catch (error) {
|
|
65
|
-
gardenerError(error);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function gardener(Dom) {
|
|
70
|
-
try {
|
|
71
|
-
if (!Dom) {
|
|
72
|
-
throw new Error('DOM configuration is null or undefined');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (Dom.nodeType === 1) return Dom;
|
|
76
|
-
|
|
77
|
-
if (!Dom.t) {
|
|
78
|
-
throw new Error('Element type (t) is required in DOM configuration');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// detect if this is an SVG element
|
|
82
|
-
const isSVG = [
|
|
83
|
-
'svg', 'path', 'circle', 'rect', 'line', 'polygon', 'polyline', 'g', 'defs', 'clipPath', 'use'
|
|
84
|
-
].includes(Dom.t);
|
|
85
|
-
|
|
86
|
-
// create element accordingly
|
|
87
|
-
let element;
|
|
88
|
-
|
|
89
|
-
if (isSVG) {
|
|
90
|
-
element = document.createElementNS('http://www.w3.org/2000/svg', Dom.t);
|
|
91
|
-
if (Dom.cn)
|
|
92
|
-
element.classList.add(...Dom.cn);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
element = createElement(Dom.t, Dom.cn);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (!element) {
|
|
99
|
-
throw new Error(`Failed to create element: ${Dom.t}`);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// text content (skip for SVG like <path>)
|
|
103
|
-
if (Dom.txt) {
|
|
104
|
-
insertText(element, Dom.txt);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// apply attributes safely
|
|
108
|
-
const propertyNames = new Set([
|
|
109
|
-
'value', 'selected', 'muted', 'disabled',
|
|
110
|
-
'selectedIndex', 'volume', // etc.
|
|
111
|
-
]);
|
|
112
|
-
|
|
113
|
-
if (Dom.attr) {
|
|
114
|
-
for (const [key, value] of Object.entries(Dom.attr)) {
|
|
115
|
-
try {
|
|
116
|
-
if (isSVG || key.startsWith('data-') || key.startsWith('aria-')) {
|
|
117
|
-
element.setAttribute(key, value);
|
|
118
|
-
} else if (key in element && !propertyNames.has(key)) {
|
|
119
|
-
// Prefer property for known safe cases
|
|
120
|
-
try { element[key] = value === '' ? true : value; } catch (e) { element.setAttribute(key, value); }
|
|
121
|
-
} else {
|
|
122
|
-
element.setAttribute(key, value);
|
|
123
|
-
}
|
|
124
|
-
} catch (attrError) {
|
|
125
|
-
console.warn(`Failed to set attribute ${key}:`, attrError);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (Dom.events) {
|
|
131
|
-
Object.entries(Dom.events).forEach(([eventName, handler]) => {
|
|
132
|
-
try {
|
|
133
|
-
if (typeof handler !== 'function') {
|
|
134
|
-
throw new Error(`Event handler for '${eventName}' must be a function`);
|
|
135
|
-
}
|
|
136
|
-
element.addEventListener(eventName, handler);
|
|
137
|
-
} catch (eventError) {
|
|
138
|
-
console.warn(`Failed to add event listener ${eventName}:`, eventError);
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// recursively handle children
|
|
144
|
-
if (Dom.children) {
|
|
145
|
-
Dom.children.forEach(child => {
|
|
146
|
-
try {
|
|
147
|
-
appendElement(element, gardener(child));
|
|
148
|
-
} catch (childError) {
|
|
149
|
-
console.warn('Failed to append child:', childError);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return element;
|
|
155
|
-
} catch (error) {
|
|
156
|
-
gardenerError(error);
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const mode = 'prod';
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { mode } from './gardenerConfig.js'
|
|
2
|
-
import { gardener, appendElement, fetchElement } from './gardener.js'
|
|
3
|
-
import { addPagebtn } from './components/gardener/pageOverlayBtn.js';
|
|
4
|
-
import { parserWindow as parserWindowComponent } from './components/gardener/parserWindow.js';
|
|
5
|
-
import { hotReloadBtn, togglehotreload } from './components/gardener/hotReloadbtn.js';
|
|
6
|
-
import { gardenerError } from './components/gardener/errorBox.js';
|
|
7
|
-
|
|
8
|
-
const body = fetchElement('body');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (mode === 'dev') {
|
|
22
|
-
appendElement(body, addPagebtn);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
appendElement(body, hotReloadBtn())
|
|
26
|
-
|
|
27
|
-
togglehotreload();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
document.addEventListener('keydown', function(e) {
|
|
34
|
-
// Detect Ctrl + H
|
|
35
|
-
if (e.altKey && e.key.toLowerCase() === 'h') {
|
|
36
|
-
e.preventDefault(); // Stop browser from opening history
|
|
37
|
-
// Your logic here...
|
|
38
|
-
togglehotreload();
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
export function parserWindow(text) {
|
|
48
|
-
if (mode !== 'dev') return;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const result = parserWindowComponent(text);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
appendElement(body, result);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
export function parser(element, isParent = true) {
|
|
61
|
-
try {
|
|
62
|
-
|
|
63
|
-
if (mode !== 'dev') return;
|
|
64
|
-
|
|
65
|
-
if (typeof element === 'string') {
|
|
66
|
-
element = fetchElement(element);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const obj = {
|
|
70
|
-
t: element.tagName.toLowerCase(),
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// add classes if present
|
|
74
|
-
if (element.classList.length) {
|
|
75
|
-
obj.cn = Array.from(element.classList);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// add attributes if present
|
|
79
|
-
const attrs = {};
|
|
80
|
-
for (const attr of element.attributes) {
|
|
81
|
-
if (attr.name !== 'class') attrs[attr.name] = attr.value;
|
|
82
|
-
}
|
|
83
|
-
if (Object.keys(attrs).length) obj.attr = attrs;
|
|
84
|
-
// add text content (only if no children)
|
|
85
|
-
if (element.childNodes.length === 1 && element.firstChild.nodeType === Node.TEXT_NODE) {
|
|
86
|
-
obj.txt = element.textContent.trim();
|
|
87
|
-
|
|
88
|
-
if (isParent) {
|
|
89
|
-
|
|
90
|
-
parserWindow(JSON.stringify(obj, null, 2))
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return obj;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const children = [];
|
|
98
|
-
for (const child of element.childNodes) {
|
|
99
|
-
if (child.nodeType === Node.COMMENT_NODE) continue;
|
|
100
|
-
|
|
101
|
-
if (child.nodeType === Node.TEXT_NODE && child.textContent.trim() === '') continue;
|
|
102
|
-
|
|
103
|
-
if (child.nodeType === Node.TEXT_NODE) {
|
|
104
|
-
children.push({ t: 'span', txt: child.textContent.trim() });
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
children.push(parser(child, false));
|
|
108
|
-
}
|
|
109
|
-
if (children.length) obj.children = children;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (isParent) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
parserWindow(JSON.stringify(obj, null, 2))
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return obj
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
//Let Browser do the migration from html to json and then use copy paste
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
gardenerError(`parserError: ${err}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function addEl(parent, event, fun) {
|
|
130
|
-
try {
|
|
131
|
-
if (typeof parent === 'string') {
|
|
132
|
-
parent = fetchElement(parent);
|
|
133
|
-
}
|
|
134
|
-
parent.addEventListener(event, fun)
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
catch (err) {
|
|
138
|
-
gardenerError(`addElError: ${err}`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
export class State {
|
|
144
|
-
constructor(value) {
|
|
145
|
-
this.value = value;
|
|
146
|
-
this.cb = [];
|
|
147
|
-
}
|
|
148
|
-
registerCb(cb) {
|
|
149
|
-
cb(this.value);
|
|
150
|
-
this.cb.push(cb);
|
|
151
|
-
}
|
|
152
|
-
unregisterCb(cb) {
|
|
153
|
-
this.cb = this.cb.filter(c => c !== cb);
|
|
154
|
-
}
|
|
155
|
-
setTo(val) {
|
|
156
|
-
this.value = val;
|
|
157
|
-
this.cb.forEach(cb => { cb(val) });
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
export function log(target) {
|
|
163
|
-
console.log(target)
|
|
164
|
-
}
|
|
165
|
-
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { copybtn } from "../components/copybtn.js";
|
|
2
|
-
import { pageloader } from "../components/nonui/navigation.js";
|
|
3
|
-
import addNotification from "../components/notification.js";
|
|
4
|
-
import { gardener, fetchElement, replaceElement, appendElement } from "../gardener.js";
|
|
5
|
-
import { log, parser, addEl, State } from "../gardenerDev.js"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// pageloader();
|
|
9
|
-
|
|
10
|
-
addEl('.copybtn', 'click', () => {
|
|
11
|
-
try {
|
|
12
|
-
navigator.clipboard.writeText(fetchElement('.initCommand').innerText)
|
|
13
|
-
replaceElement('.copybtn', copybtn());
|
|
14
|
-
addNotification({ status: 'success', message: 'Copied' })
|
|
15
|
-
}
|
|
16
|
-
catch (err) {
|
|
17
|
-
addNotification({
|
|
18
|
-
status: 'failure', message: "Couldn't Copy"
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// parser('body');
|