create-gardener 1.1.12 → 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.
- package/package.json +1 -1
- package/starter.js +5 -2
- package/template/.env +0 -0
- package/template/buildHelper.js +3 -0
- package/template/jsconfig.json +27 -0
- package/template/package.json +6 -5
- package/template/src/backend/controllers/gardener/addComponent.ts +27 -0
- package/template/src/backend/controllers/gardener/addPage.ts +60 -0
- package/template/src/backend/controllers/gardener/createStatic.ts +84 -0
- package/template/src/backend/controllers/gardener/imageOptimiser.ts +67 -0
- package/template/src/backend/controllers/gardener/index.ts +4 -0
- package/template/src/backend/libs/generateWebp.ts +1 -0
- package/template/src/backend/routes/gardener.route.ts +15 -5
- package/template/src/backend/server.ts +8 -10
- package/template/src/frontend/assets/favicon.png +0 -0
- package/template/src/frontend/frontendtemplate.ejs +5 -17
- 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_50x50.webp +0 -0
- package/template/src/frontend/static/components/copybtn.js +86 -0
- package/template/src/frontend/static/components/nonui/api.js +33 -16
- package/template/src/frontend/static/components/nonui/navigation.js +59 -0
- package/template/src/frontend/static/components/secondtest.js +6 -0
- package/template/src/frontend/static/components/{emailsvg.js → testdd.js} +7 -7
- package/template/src/frontend/static/gardener.js +0 -384
- package/template/src/frontend/static/gardenerConfig.js +1 -0
- package/template/src/frontend/static/gardenerDev.js +408 -0
- package/template/src/frontend/static/global.js +2 -56
- package/template/src/frontend/static/pages/_.js +13 -0
- package/template/src/frontend/static/pages/_get-started.js +5 -0
- package/template/src/frontend/static/style.css +1039 -1
- package/template/src/frontend/static/style2.css +1 -1
- package/template/src/frontend/static/zod.js +8 -0
- package/template/src/frontend/views/_.ejs +96 -216
- package/template/src/frontend/views/_get-started.ejs +25 -0
- package/template/src/frontend/views/partials/icons/clipboard.ejs +1 -0
- package/template/src/frontend/views/partials/icons/clipboardok.ejs +1 -0
- package/template/tsconfig.json +1 -1
- package/template/src/backend/controllers/gardener.controller.ts +0 -187
- package/template/src/frontend/gardenerST.js +0 -423
- package/template/src/frontend/static/components/eyeoff.js +0 -50
- package/template/src/frontend/static/components/eyeon.js +0 -43
- package/template/src/frontend/static/components/passwordBox.js +0 -105
- package/template/src/frontend/views/_login.ejs +0 -75
- package/template/src/frontend/views/partials/loader.ejs +0 -3
package/package.json
CHANGED
package/starter.js
CHANGED
package/template/.env
ADDED
|
File without changes
|
package/template/buildHelper.js
CHANGED
|
@@ -6,6 +6,9 @@ async function buildHelper() {
|
|
|
6
6
|
const dest = path.resolve('build', 'frontend');
|
|
7
7
|
|
|
8
8
|
await fs.cp(src, dest, { recursive: true });
|
|
9
|
+
|
|
10
|
+
await fs.writeFile(path.join(dest, 'static', 'gardenerConfig.js'), "export const mode = 'pro';", 'utf8');
|
|
11
|
+
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
buildHelper();// const path = require('path');
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "esnext",
|
|
4
|
+
"module": "nodenext",
|
|
5
|
+
"noUncheckedSideEffectImports": true,
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
|
+
"checkJs": true,
|
|
8
|
+
"baseUrl": ".",
|
|
9
|
+
"paths": {
|
|
10
|
+
"/static/*.js": ["src/frontend/static/*.js"]
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"declaration": true,
|
|
16
|
+
"declarationMap": true,
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
"strict":true,
|
|
20
|
+
"verbatimModuleSyntax": true,
|
|
21
|
+
"isolatedModules": true,
|
|
22
|
+
"noUncheckedSideEffectImports": true,
|
|
23
|
+
"moduleDetection": "force",
|
|
24
|
+
"skipLibCheck": true
|
|
25
|
+
},
|
|
26
|
+
"include": ["src/frontend/static/**/*.js"]
|
|
27
|
+
}
|
package/template/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-gardener",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A dom gardener converting dom elements into json and vice versa",
|
|
5
5
|
"main": "src/build/server.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"start": "node
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
8
|
+
"start": "NODE_ENV=production node build/backend/server.js",
|
|
9
|
+
"dev": "concurrently \"NODE_ENV=development tsx watch src/backend/server.ts\" \"tailwindcss -w -i src/frontend/tailwind.css -o src/frontend/static/style.css\"",
|
|
10
|
+
"build": "tailwindcss -i src/frontend/tailwind.css -o src/frontend/static/style.css --minify && tsc && node buildHelper.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [],
|
|
14
14
|
"author": "ritishDas",
|
|
@@ -32,3 +32,4 @@
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Request, Response } from "express";
|
|
2
|
+
import fsp from "fs/promises";
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
interface AddComponentBody {
|
|
6
|
+
path: string;
|
|
7
|
+
component: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const frontendDir = path.resolve(__dirname, '..', '..', '..', 'frontend');
|
|
15
|
+
|
|
16
|
+
export async function addComponent(req: Request<{}, {}, AddComponentBody>, res: Response) {
|
|
17
|
+
try {
|
|
18
|
+
const { path: filePath, component } = req.body;
|
|
19
|
+
await fsp.mkdir(path.join(frontendDir, 'static', 'components'), { recursive: true });
|
|
20
|
+
await fsp.writeFile(path.join(frontendDir, `${filePath}`), component, "utf8");
|
|
21
|
+
res.json({ success: true });
|
|
22
|
+
|
|
23
|
+
} catch (err) {
|
|
24
|
+
const error = err as Error;
|
|
25
|
+
res.json({ success: false, msg: error.message });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Request, Response } from "express";
|
|
2
|
+
import fsp from "fs/promises";
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
const frontendDir = path.resolve(__dirname, '..', '..', '..', 'frontend');
|
|
10
|
+
|
|
11
|
+
export async function addPage(req: Request, res: Response) {
|
|
12
|
+
try {
|
|
13
|
+
const pagename: string = req.body.page;
|
|
14
|
+
const name = pagename.replaceAll('/', '_');
|
|
15
|
+
|
|
16
|
+
const templatePath = path.join(frontendDir, 'frontendtemplate.ejs');
|
|
17
|
+
const viewPath = path.join(frontendDir, `views`, `${name}.ejs`);
|
|
18
|
+
const routePath = path.resolve(__dirname, '..', '..', 'routes', 'gardener.route.ts');
|
|
19
|
+
const jsDir = path.join(frontendDir, 'static/pages');
|
|
20
|
+
const jsFilePath = path.join(jsDir, `${name}.js`);
|
|
21
|
+
|
|
22
|
+
const templateContent = await fsp.readFile(templatePath, 'utf8');
|
|
23
|
+
await fsp.writeFile(viewPath, templateContent, "utf8");
|
|
24
|
+
|
|
25
|
+
await replaceLastOccurrence(viewPath, '<script', `<script src="/static/pages/${name}.js" type='module'></script>`);
|
|
26
|
+
|
|
27
|
+
const routeEntry = `router.route("${pagename}").get((req: Request, res: Response) => res.render("${name}"));\n`;
|
|
28
|
+
await fsp.appendFile(routePath, routeEntry, "utf8");
|
|
29
|
+
|
|
30
|
+
await fsp.mkdir(jsDir, { recursive: true });
|
|
31
|
+
const jsContent = 'import { gardener, fetchElement, replaceElement, appendElement } from "/static/gardener.js";\n import {log, parser, addEl, State} from "/static/gardenerDev.js"';
|
|
32
|
+
await fsp.writeFile(jsFilePath, jsContent, "utf8");
|
|
33
|
+
|
|
34
|
+
res.json({ success: true });
|
|
35
|
+
} catch (err) {
|
|
36
|
+
const error = err as Error;
|
|
37
|
+
res.json({ success: false, msg: error.message });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function replaceLastOccurrence(filePath: string, searchPattern: string, replacementLine: string) {
|
|
42
|
+
const content = await fsp.readFile(filePath, 'utf8');
|
|
43
|
+
const lines = content.split('\n');
|
|
44
|
+
let found = false;
|
|
45
|
+
|
|
46
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
47
|
+
|
|
48
|
+
if (lines[i]!.includes(searchPattern)) {
|
|
49
|
+
lines[i] = `${replacementLine}\n${lines[i]}`;
|
|
50
|
+
found = true;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (found) {
|
|
56
|
+
await fsp.writeFile(filePath, lines.join('\n'), 'utf8');
|
|
57
|
+
} else {
|
|
58
|
+
console.warn(`Pattern "${searchPattern}" not found in ${filePath}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Request, Response } from "express";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fsp from "fs/promises";
|
|
4
|
+
import ejs from "ejs";
|
|
5
|
+
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const frontendDir = path.resolve(__dirname, '..', '..', '..', 'frontend');
|
|
11
|
+
|
|
12
|
+
export async function createStatic(req: Request, res: Response) {
|
|
13
|
+
try {
|
|
14
|
+
const viewsDir = path.join(frontendDir, "views");
|
|
15
|
+
const outDir = path.resolve("src/tempfrontend");
|
|
16
|
+
const finalOut = path.resolve("src/frontendStatic");
|
|
17
|
+
|
|
18
|
+
await fsp.mkdir(outDir, { recursive: true });
|
|
19
|
+
await fsp.mkdir(finalOut, { recursive: true });
|
|
20
|
+
|
|
21
|
+
const entries = await fsp.readdir(viewsDir, { withFileTypes: true });
|
|
22
|
+
|
|
23
|
+
const rendered: string[] = [];
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
// skip folders (partials, layouts, etc.)
|
|
28
|
+
if (!entry.isFile()) continue;
|
|
29
|
+
if (!entry.name.endsWith(".ejs")) continue;
|
|
30
|
+
|
|
31
|
+
const inputPath = path.join(viewsDir, entry.name);
|
|
32
|
+
const outputName = entry.name.replace(/\.ejs$/, ".html");
|
|
33
|
+
const outputPath = path.join(outDir, outputName);
|
|
34
|
+
|
|
35
|
+
const html = await ejs.renderFile(
|
|
36
|
+
inputPath,
|
|
37
|
+
{
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
// async: true,
|
|
41
|
+
views: [viewsDir], // needed for includes
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
await fsp.writeFile(outputPath, html, "utf8");
|
|
46
|
+
rendered.push(outputName);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const entries3 = await fsp.readdir(outDir, { withFileTypes: true });
|
|
50
|
+
for (const entry of entries3) {
|
|
51
|
+
|
|
52
|
+
// "_path1_path2_path3.html" -> ["path1", "path2", "path3"]
|
|
53
|
+
const parts = entry.name
|
|
54
|
+
.replace(/^_/, "")
|
|
55
|
+
.replace(/\.html$/, "")
|
|
56
|
+
.split("_");
|
|
57
|
+
|
|
58
|
+
const targetDir = path.join(finalOut, ...parts);
|
|
59
|
+
const targetFile = path.join(targetDir, "index.html");
|
|
60
|
+
|
|
61
|
+
// ensure directories exist
|
|
62
|
+
await fsp.mkdir(targetDir, { recursive: true });
|
|
63
|
+
console.log('done');
|
|
64
|
+
// copy file
|
|
65
|
+
await fsp.copyFile(path.join(outDir, entry.name), targetFile);
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
await fsp.rm(outDir, { recursive: true, force: true });
|
|
69
|
+
await fsp.cp(
|
|
70
|
+
path.join(frontendDir, "static"),
|
|
71
|
+
path.join(finalOut, 'static'),
|
|
72
|
+
{ recursive: true }
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return res.json({
|
|
76
|
+
success: true,
|
|
77
|
+
generated: rendered,
|
|
78
|
+
outDir,
|
|
79
|
+
});
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error(err);
|
|
82
|
+
return res.status(500).json({ error: "Static build failed" });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Request, Response } from "express";
|
|
2
|
+
import fsp from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import generateWebP from "../../libs/generateWebp.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export async function imageOptimiser(req: Request, res: Response) {
|
|
13
|
+
try {
|
|
14
|
+
const { name } = req.params;
|
|
15
|
+
|
|
16
|
+
if (typeof name !== 'string') return;
|
|
17
|
+
// name format: test_500x300.webp
|
|
18
|
+
const match = name.match(/^(.+?)_(\d+)x(\d+)\.webp$/);
|
|
19
|
+
|
|
20
|
+
if (!match) {
|
|
21
|
+
return res.status(400).json({ error: "Invalid image format" });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const [, baseName, widthStr, heightStr] = match;
|
|
25
|
+
|
|
26
|
+
if (!widthStr || !heightStr) return;
|
|
27
|
+
const width = parseInt(widthStr, 10);
|
|
28
|
+
const height = parseInt(heightStr, 10);
|
|
29
|
+
|
|
30
|
+
const cacheDir = path.join(__dirname, "..", "..", "..", "frontend", "static", "cache");
|
|
31
|
+
await fsp.mkdir(cacheDir, { recursive: true });
|
|
32
|
+
|
|
33
|
+
const outputPath = path.join(cacheDir, name);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await fsp.access(outputPath);
|
|
37
|
+
return res.sendFile(path.basename(outputPath), {
|
|
38
|
+
root: path.dirname(outputPath),
|
|
39
|
+
});
|
|
40
|
+
} catch {
|
|
41
|
+
// not cached → continue
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const assetsDir = path.resolve(__dirname, '..', '..', '..', "frontend", "assets");
|
|
45
|
+
const files = await fsp.readdir(assetsDir);
|
|
46
|
+
|
|
47
|
+
const sourceFile = files.find((file) => {
|
|
48
|
+
const parsed = path.parse(file);
|
|
49
|
+
return parsed.name === baseName;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!sourceFile) {
|
|
53
|
+
return res.status(404).json({ error: "Source image not found" });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const inputPath = path.join(assetsDir, sourceFile);
|
|
57
|
+
|
|
58
|
+
await generateWebP(inputPath, outputPath, width, height);
|
|
59
|
+
|
|
60
|
+
return res.sendFile(path.basename(outputPath), {
|
|
61
|
+
root: path.dirname(outputPath),
|
|
62
|
+
});
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error(err);
|
|
65
|
+
return res.status(500).json({ error: "Image optimisation failed" });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Request, Response } from 'express';
|
|
2
2
|
import { Router } from "express";
|
|
3
|
-
import { addComponent, addPage, createStatic, imageOptimiser } from "../controllers/gardener.
|
|
3
|
+
import { addComponent, addPage, createStatic, imageOptimiser } from "../controllers/gardener/index.js";
|
|
4
4
|
|
|
5
5
|
const router: Router = Router();
|
|
6
6
|
export default router;
|
|
@@ -9,9 +9,12 @@ export default router;
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
router.route("/static/cache/:name").get(imageOptimiser);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
router.route(
|
|
12
|
+
|
|
13
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
14
|
+
router.route("/createstatic").get(createStatic);
|
|
15
|
+
router.route('/addcomponent').post(addComponent);
|
|
16
|
+
router.route('/addpage').post(addPage);
|
|
17
|
+
}
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
|
|
@@ -19,4 +22,11 @@ router.route('/addpage').post(addPage);
|
|
|
19
22
|
|
|
20
23
|
router.route('/').get((req: Request, res: Response) => res.render('_'));
|
|
21
24
|
router.route('/login').get((req: Request, res: Response) => res.render('_login'));
|
|
22
|
-
|
|
25
|
+
router.route("/test").get((req: Request, res: Response) => res.render("_test"))
|
|
26
|
+
router.route("/rd").get((req: Request, res: Response) => res.render("_rd"));
|
|
27
|
+
router.route("/car").get((req: Request, res: Response) => res.render("_car"));
|
|
28
|
+
router.route("/onemore").get((req: Request, res: Response) => res.render("_onemore"));
|
|
29
|
+
|
|
30
|
+
router.route("/re").get((req: Request, res: Response) => res.render("_re"));
|
|
31
|
+
router.route("/playground").get((req: Request, res: Response) => res.render("_playground"));
|
|
32
|
+
router.route("/get-started").get((req: Request, res: Response) => res.render("_get-started"));
|
|
@@ -2,26 +2,24 @@
|
|
|
2
2
|
import 'dotenv/config';
|
|
3
3
|
import express from 'express';
|
|
4
4
|
import frontendRoute from './routes/gardener.route.js'
|
|
5
|
+
import path from "path";
|
|
5
6
|
|
|
6
7
|
const app = express();
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
const staticFiles = path.resolve(__dirname, '..', 'frontend')
|
|
15
|
+
|
|
16
|
+
app.set('views', path.join(staticFiles, 'views'));
|
|
11
17
|
app.set("view engine", "ejs");
|
|
12
|
-
app.use(express.static(
|
|
18
|
+
app.use(express.static(staticFiles));
|
|
13
19
|
app.use(express.json());
|
|
14
20
|
app.use(frontendRoute);
|
|
15
21
|
|
|
16
22
|
const PORT = process.env.PORT || 3000;
|
|
17
|
-
//
|
|
18
|
-
// initDB().then(
|
|
19
|
-
// () => {
|
|
20
|
-
// app.listen(PORT, () => {
|
|
21
|
-
// console.log("server listening 🚀🚀🚀 PORT:", PORT);
|
|
22
|
-
// });
|
|
23
|
-
// }
|
|
24
|
-
// )
|
|
25
23
|
|
|
26
24
|
app.listen(PORT, () => {
|
|
27
25
|
console.log("server listening 🚀🚀🚀 PORT:", PORT);
|
|
Binary file
|
|
@@ -3,33 +3,21 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<link rel="icon" type="image/svg+xml" href="/static/cache/favicon_50x50.webp" />
|
|
6
7
|
<link href="/static/style.css" rel="stylesheet"/>
|
|
7
8
|
<link href="/static/style2.css" rel="stylesheet"/>
|
|
8
|
-
<title>
|
|
9
|
+
<title>Gardener: The Mini Web Framework</title>
|
|
9
10
|
</head>
|
|
10
11
|
<body>
|
|
11
12
|
<div class='notification'></div>
|
|
12
|
-
<div class=
|
|
13
|
-
|
|
14
|
-
<%- include('partials/loader') %>
|
|
15
|
-
<!-- Remove this line when you are using hot reload as it will cause delay -->
|
|
13
|
+
<div class='loader w-screen h-screen bg-white fixed z-2'> </div>
|
|
14
|
+
<div id='main'>
|
|
16
15
|
|
|
17
|
-
<!-- Main Content-->
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
<div class="hero flex justify-around items-center p-5 h-[90vh]">
|
|
21
|
-
<p class='p-5'>
|
|
22
|
-
Gardener is a front-end library for creating and manipulating DOM elements using a declarative JavaScript object syntax. It includes a development server with features like hot-reloading and on-the-fly component creation from existing HTML. The server also provides dynamic image resizing and caching.
|
|
23
|
-
</p>
|
|
24
|
-
<img src="/cache/w_500x500.webp" alt="logo" class="w-500">
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
<script src='/static/global.js' type="module"></script>
|
|
28
|
-
<script type="module">
|
|
29
18
|
|
|
30
|
-
import { parser, fetchElement, replaceElement, appendElement } from "/static/gardener.js";
|
|
31
|
-
</script>
|
|
32
19
|
</body>
|
|
20
|
+
<script type='module' src='/static/global.js'> </script>
|
|
33
21
|
</html>
|
|
34
22
|
|
|
35
23
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
import { gardener, fetchElement, replaceElement } from '../gardener.js'
|
|
3
|
+
|
|
4
|
+
export function copybtn() {
|
|
5
|
+
return gardener({
|
|
6
|
+
"t": "button",
|
|
7
|
+
"cn": [
|
|
8
|
+
"copybtn",
|
|
9
|
+
"flex",
|
|
10
|
+
"items-center",
|
|
11
|
+
"justify-center",
|
|
12
|
+
"p-2",
|
|
13
|
+
"text-gray-400",
|
|
14
|
+
"hover:text-white",
|
|
15
|
+
"hover:bg-white/10",
|
|
16
|
+
"rounded",
|
|
17
|
+
"transition-all",
|
|
18
|
+
"duration-200",
|
|
19
|
+
"active:scale-95"
|
|
20
|
+
],
|
|
21
|
+
"attr": {
|
|
22
|
+
"title": "Copy to clipboard"
|
|
23
|
+
},
|
|
24
|
+
"children": [
|
|
25
|
+
{
|
|
26
|
+
"t": "span",
|
|
27
|
+
"cn": [
|
|
28
|
+
"w-5",
|
|
29
|
+
"h-5"
|
|
30
|
+
],
|
|
31
|
+
"children": [
|
|
32
|
+
{
|
|
33
|
+
"t": "svg",
|
|
34
|
+
"cn": [
|
|
35
|
+
"icon",
|
|
36
|
+
"icon-tabler",
|
|
37
|
+
"icons-tabler-outline",
|
|
38
|
+
"icon-tabler-clipboard-check"
|
|
39
|
+
],
|
|
40
|
+
"attr": {
|
|
41
|
+
"xmlns": "http://www.w3.org/2000/svg",
|
|
42
|
+
"width": "24",
|
|
43
|
+
"height": "24",
|
|
44
|
+
"viewBox": "0 0 24 24",
|
|
45
|
+
"fill": "none",
|
|
46
|
+
"stroke": "currentColor",
|
|
47
|
+
"stroke-width": "2",
|
|
48
|
+
"stroke-linecap": "round",
|
|
49
|
+
"stroke-linejoin": "round"
|
|
50
|
+
},
|
|
51
|
+
"children": [
|
|
52
|
+
{
|
|
53
|
+
"t": "path",
|
|
54
|
+
"attr": {
|
|
55
|
+
"stroke": "none",
|
|
56
|
+
"d": "M0 0h24v24H0z",
|
|
57
|
+
"fill": "none"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"t": "path",
|
|
62
|
+
"attr": {
|
|
63
|
+
"d": "M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"t": "path",
|
|
68
|
+
"attr": {
|
|
69
|
+
"d": "M9 5a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"t": "path",
|
|
74
|
+
"attr": {
|
|
75
|
+
"d": "M9 14l2 2l4 -4"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
@@ -1,22 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
const baseName = '';
|
|
2
|
+
|
|
3
|
+
export async function Fetch(
|
|
4
|
+
path,
|
|
5
|
+
body,
|
|
6
|
+
method = 'POST'
|
|
7
|
+
) {
|
|
8
|
+
|
|
2
9
|
try {
|
|
3
|
-
const data = await fetch(path, {
|
|
4
|
-
credentials: 'include',
|
|
5
|
-
method: 'POST',
|
|
6
|
-
headers: {
|
|
7
|
-
'Content-Type': 'application/json'
|
|
8
|
-
},
|
|
9
|
-
body: JSON.stringify(body)
|
|
10
|
-
});
|
|
11
10
|
|
|
12
|
-
|
|
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
|
+
|
|
33
|
+
|
|
34
|
+
return res
|
|
13
35
|
}
|
|
14
36
|
catch (err) {
|
|
15
|
-
console.
|
|
37
|
+
console.log(err)
|
|
16
38
|
}
|
|
17
39
|
}
|
|
18
|
-
|
|
19
|
-
export async function userlogin(email, password) {
|
|
20
|
-
const result = await postFetch('/login', { email, password });
|
|
21
|
-
console.log(result);
|
|
22
|
-
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { gardener, fetchElement, appendElement } from "/static/gardener.js";
|
|
2
|
+
import { mode } from "/static/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
|
+
}
|