@leadertechie/personal-site-kit 0.1.0-alpha.7 → 0.1.0-alpha.9
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/dist/api/content-utils.d.ts +27 -0
- package/dist/api/content-utils.d.ts.map +1 -0
- package/dist/api/handlers/about-me.d.ts.map +1 -1
- package/dist/api/handlers/content-api.d.ts +0 -1
- package/dist/api/handlers/content-api.d.ts.map +1 -1
- package/dist/api/website-api.d.ts.map +1 -1
- package/dist/api.js +2 -2
- package/dist/chunks/index-CGvOrVf8.js +213 -0
- package/dist/chunks/{index-Bq8WDk9L.js → index-CnSEOZse.js} +1285 -477
- package/dist/chunks/{template-Boh_MKY5.js → template-DWcsZW22.js} +8 -7
- package/dist/chunks/{website-api-XoeLwo_N.js → website-api-BEYGOsT3.js} +137 -156
- package/dist/index.js +19 -9
- package/dist/prerender/data-fetcher.d.ts +19 -0
- package/dist/prerender/data-fetcher.d.ts.map +1 -0
- package/dist/prerender/page-content.d.ts.map +1 -1
- package/dist/prerender/page-generators/about.d.ts +16 -0
- package/dist/prerender/page-generators/about.d.ts.map +1 -0
- package/dist/prerender/page-generators/base.d.ts +26 -0
- package/dist/prerender/page-generators/base.d.ts.map +1 -0
- package/dist/prerender/page-generators/blog-detail.d.ts +15 -0
- package/dist/prerender/page-generators/blog-detail.d.ts.map +1 -0
- package/dist/prerender/page-generators/blogs-list.d.ts +17 -0
- package/dist/prerender/page-generators/blogs-list.d.ts.map +1 -0
- package/dist/prerender/page-generators/home.d.ts +19 -0
- package/dist/prerender/page-generators/home.d.ts.map +1 -0
- package/dist/prerender/page-generators/index.d.ts +9 -0
- package/dist/prerender/page-generators/index.d.ts.map +1 -0
- package/dist/prerender/page-generators/not-found.d.ts +14 -0
- package/dist/prerender/page-generators/not-found.d.ts.map +1 -0
- package/dist/prerender/page-generators/stories-list.d.ts +17 -0
- package/dist/prerender/page-generators/stories-list.d.ts.map +1 -0
- package/dist/prerender/page-generators/story-detail.d.ts +15 -0
- package/dist/prerender/page-generators/story-detail.d.ts.map +1 -0
- package/dist/prerender.js +109 -102
- package/dist/shared.js +1 -1
- package/dist/ui/about-me/index.d.ts +2 -10
- package/dist/ui/about-me/index.d.ts.map +1 -1
- package/dist/ui/admin/api.d.ts +16 -0
- package/dist/ui/admin/api.d.ts.map +1 -0
- package/dist/ui/admin/components/AboutMeSection.d.ts +7 -0
- package/dist/ui/admin/components/AboutMeSection.d.ts.map +1 -0
- package/dist/ui/admin/components/AdminSection.d.ts +13 -0
- package/dist/ui/admin/components/AdminSection.d.ts.map +1 -0
- package/dist/ui/admin/components/BlogsSection.d.ts +7 -0
- package/dist/ui/admin/components/BlogsSection.d.ts.map +1 -0
- package/dist/ui/admin/components/HomeSection.d.ts +7 -0
- package/dist/ui/admin/components/HomeSection.d.ts.map +1 -0
- package/dist/ui/admin/components/ImagesSection.d.ts +7 -0
- package/dist/ui/admin/components/ImagesSection.d.ts.map +1 -0
- package/dist/ui/admin/components/LoginForm.d.ts +9 -0
- package/dist/ui/admin/components/LoginForm.d.ts.map +1 -0
- package/dist/ui/admin/components/LogoSection.d.ts +7 -0
- package/dist/ui/admin/components/LogoSection.d.ts.map +1 -0
- package/dist/ui/admin/components/ProfileSection.d.ts +7 -0
- package/dist/ui/admin/components/ProfileSection.d.ts.map +1 -0
- package/dist/ui/admin/components/StaticSection.d.ts +13 -0
- package/dist/ui/admin/components/StaticSection.d.ts.map +1 -0
- package/dist/ui/admin/components/StoriesSection.d.ts +7 -0
- package/dist/ui/admin/components/StoriesSection.d.ts.map +1 -0
- package/dist/ui/admin/components/index.d.ts +11 -0
- package/dist/ui/admin/components/index.d.ts.map +1 -0
- package/dist/ui/admin/index.d.ts +18 -26
- package/dist/ui/admin/index.d.ts.map +1 -1
- package/dist/ui/admin/types.d.ts +24 -0
- package/dist/ui/admin/types.d.ts.map +1 -0
- package/dist/ui/blog-viewer/index.d.ts.map +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/story-viewer/index.d.ts.map +1 -1
- package/dist/ui.js +14 -4
- package/package.json +4 -4
- package/dist/ui/about-me/renderer.d.ts +0 -6
- package/dist/ui/about-me/renderer.d.ts.map +0 -1
- package/src/api/__tests__/info.test.ts +0 -44
- package/src/api/__tests__/utils.test.ts +0 -78
- package/src/api/handlers/about-me.ts +0 -99
- package/src/api/handlers/auth-handler.ts +0 -194
- package/src/api/handlers/auth.ts +0 -157
- package/src/api/handlers/content-api.ts +0 -268
- package/src/api/handlers/content.ts +0 -139
- package/src/api/handlers/home.ts +0 -79
- package/src/api/handlers/info.ts +0 -12
- package/src/api/handlers/logo.ts +0 -55
- package/src/api/handlers/static-details.ts +0 -48
- package/src/api/index.ts +0 -9
- package/src/api/utils.ts +0 -16
- package/src/api/website-api.ts +0 -138
- package/src/index.ts +0 -4
- package/src/prerender/__tests__/page-content.test.ts +0 -54
- package/src/prerender/__tests__/template.test.ts +0 -54
- package/src/prerender/index.ts +0 -7
- package/src/prerender/page-content.ts +0 -263
- package/src/prerender/prerender.ts +0 -25
- package/src/prerender/template.ts +0 -65
- package/src/prerender/website-prerender.ts +0 -152
- package/src/shared/config/api.ts +0 -16
- package/src/shared/config/index.ts +0 -43
- package/src/shared/config/types.ts +0 -16
- package/src/shared/core/__tests__/theme-toggle.test.ts +0 -204
- package/src/shared/core/site-store.ts +0 -38
- package/src/shared/core/theme-toggle.ts +0 -118
- package/src/shared/index.ts +0 -17
- package/src/shared/interfaces/ifooter-link.ts +0 -4
- package/src/shared/interfaces/iroute.ts +0 -4
- package/src/shared/models/theme-variables.css +0 -25
- package/src/shared/page-content.ts +0 -210
- package/src/shared/router.ts +0 -250
- package/src/shared/runtime.ts +0 -11
- package/src/shared/template.ts +0 -35
- package/src/shared/website-ui.ts +0 -92
- package/src/styles/markdown.css +0 -129
- package/src/ui/about-me/api.ts +0 -12
- package/src/ui/about-me/index.ts +0 -164
- package/src/ui/about-me/renderer.ts +0 -23
- package/src/ui/about-me/styles.ts +0 -85
- package/src/ui/admin/index.ts +0 -655
- package/src/ui/admin/styles.ts +0 -270
- package/src/ui/banner/index.ts +0 -38
- package/src/ui/banner/styles.ts +0 -95
- package/src/ui/blog-viewer/__tests__/blogviewer.test.ts +0 -7
- package/src/ui/blog-viewer/index.ts +0 -124
- package/src/ui/blog-viewer/styles.ts +0 -23
- package/src/ui/footer/index.ts +0 -37
- package/src/ui/footer/styles.ts +0 -50
- package/src/ui/index.ts +0 -6
- package/src/ui/story-viewer/__tests__/storyviewer.test.ts +0 -7
- package/src/ui/story-viewer/index.ts +0 -120
- package/src/ui/story-viewer/styles.ts +0 -54
- /package/{src/shared → dist}/styles/markdown.css +0 -0
- /package/{src → dist}/styles/theme.css +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { MarkdownPipeline } from "@leadertechie/md2html";
|
|
2
|
+
const __vite_import_meta_env__ = {};
|
|
2
3
|
const DEFAULT_INFRA = {
|
|
3
4
|
baseUrl: typeof window !== "undefined" ? window.location.origin : "http://localhost:5173",
|
|
4
|
-
apiUrl: typeof window !== "undefined" && window.__VITE_API_URL__ || "http://localhost:8787"
|
|
5
|
+
apiUrl: typeof window !== "undefined" && (window.__VITE_API_URL__ || __vite_import_meta_env__?.VITE_API_URL) || (typeof window !== "undefined" ? window.location.origin : "http://localhost:8787")
|
|
5
6
|
};
|
|
6
7
|
const DEFAULT_STATIC = {
|
|
7
8
|
siteTitle: "My Personal Website",
|
|
@@ -92,7 +93,7 @@ const generatePageContent = (pathname, routes, footerLinks, data) => {
|
|
|
92
93
|
const footerTemplate = `
|
|
93
94
|
<my-footer
|
|
94
95
|
copyright="${copyright}"
|
|
95
|
-
|
|
96
|
+
footerLinks='${JSON.stringify(footerLinks)}'>
|
|
96
97
|
</my-footer>`;
|
|
97
98
|
const renderContentGists = (items = [], title, type) => {
|
|
98
99
|
const listHtml = items.length > 0 ? items.map((item) => `
|
|
@@ -231,10 +232,10 @@ class Router {
|
|
|
231
232
|
return url;
|
|
232
233
|
};
|
|
233
234
|
this.footerLinks = [
|
|
234
|
-
{ text: "LinkedIn", link: normalizeUrl(config.linkedin) },
|
|
235
|
-
{ text: "GitHub", link: normalizeUrl(config.github) },
|
|
236
|
-
{ text: "Email", link: config.email ? `mailto:${config.email}` : "" }
|
|
237
|
-
]
|
|
235
|
+
{ text: "LinkedIn", link: normalizeUrl(config.linkedin) || "https://linkedin.com" },
|
|
236
|
+
{ text: "GitHub", link: normalizeUrl(config.github) || "https://github.com" },
|
|
237
|
+
{ text: "Email", link: config.email ? `mailto:${config.email}` : "mailto:hello@example.com" }
|
|
238
|
+
];
|
|
238
239
|
}
|
|
239
240
|
init(appElementId = "app") {
|
|
240
241
|
this.appElement = document.getElementById(appElementId);
|
|
@@ -426,7 +427,7 @@ class Router {
|
|
|
426
427
|
<main class="container container-medium">
|
|
427
428
|
<admin-portal></admin-portal>
|
|
428
429
|
</main>
|
|
429
|
-
<my-footer copyright="${this.copyright}"
|
|
430
|
+
<my-footer copyright="${this.copyright}" footerLinks='[]'></my-footer>
|
|
430
431
|
`;
|
|
431
432
|
}
|
|
432
433
|
}
|
|
@@ -52,20 +52,30 @@ async function handleAboutMe(env) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
console.log("handleAboutMe: r2 created, fetching data");
|
|
55
|
-
const [profileObj,
|
|
55
|
+
const [profileObj, rendered] = await Promise.all([
|
|
56
56
|
r2.getObject("profile.json"),
|
|
57
|
-
r2.
|
|
57
|
+
r2.getRendered("about-me.md")
|
|
58
58
|
]);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
if (!rendered) {
|
|
60
|
+
return new Response(JSON.stringify({ error: "About-me content not found. Please run seed." }), {
|
|
61
|
+
status: 404,
|
|
62
|
+
headers: { "Content-Type": "application/json" }
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
let profile = {
|
|
66
|
+
name: "Your Name",
|
|
67
|
+
title: "Professional",
|
|
68
|
+
experience: "Experienced",
|
|
69
|
+
profileImageUrl: ""
|
|
70
|
+
};
|
|
71
|
+
if (profileObj) {
|
|
72
|
+
profile = await profileObj.json();
|
|
62
73
|
}
|
|
63
|
-
const profile = await profileObj.json();
|
|
64
74
|
console.log("handleAboutMe: profile loaded:", profile.name);
|
|
65
75
|
const responseData = {
|
|
66
76
|
profile,
|
|
67
|
-
contentNodes:
|
|
68
|
-
processedMarkdown:
|
|
77
|
+
contentNodes: [],
|
|
78
|
+
processedMarkdown: rendered.content
|
|
69
79
|
};
|
|
70
80
|
return new Response(JSON.stringify(responseData), {
|
|
71
81
|
headers: { "Content-Type": "application/json" }
|
|
@@ -109,8 +119,8 @@ async function handleHome(env) {
|
|
|
109
119
|
}
|
|
110
120
|
const r2 = getLoader(env);
|
|
111
121
|
const [astResult, renderedResult] = await Promise.all([
|
|
112
|
-
r2.getWithAST("home.md"),
|
|
113
|
-
r2.getRendered("home.md")
|
|
122
|
+
r2.getWithAST("pages/home.md"),
|
|
123
|
+
r2.getRendered("pages/home.md")
|
|
114
124
|
]);
|
|
115
125
|
if (!astResult || !renderedResult) {
|
|
116
126
|
return new Response(JSON.stringify({
|
|
@@ -281,7 +291,7 @@ async function handleContent(request, env, subpath) {
|
|
|
281
291
|
}
|
|
282
292
|
return createErrorResponse("Admin not configured. Use POST /auth/setup to configure.", 401);
|
|
283
293
|
}
|
|
284
|
-
const sessionToken = getSessionToken(request);
|
|
294
|
+
const sessionToken = getSessionToken(request) || request.headers.get("X-Session-Token");
|
|
285
295
|
let isAuthenticated = false;
|
|
286
296
|
if (sessionToken) {
|
|
287
297
|
const session = await env.KV.get(`session:${sessionToken}`, "json");
|
|
@@ -403,32 +413,40 @@ async function handleAuth(request, env, subpath) {
|
|
|
403
413
|
}
|
|
404
414
|
}
|
|
405
415
|
async function handleSetup(request, env, clientIP, origin) {
|
|
416
|
+
console.log("handleSetup: starting setup, env.KV exists:", !!env.KV);
|
|
406
417
|
if (request.method !== "POST") {
|
|
407
418
|
return createErrorResponse("Method not allowed", 405);
|
|
408
419
|
}
|
|
409
|
-
const existing = await getAuthStore(env);
|
|
410
|
-
if (existing) {
|
|
411
|
-
return createErrorResponse("Admin already configured. Use /auth/login to login.", 400);
|
|
412
|
-
}
|
|
413
420
|
try {
|
|
421
|
+
const existing = await getAuthStore(env);
|
|
422
|
+
console.log("handleSetup: existing store check:", !!existing);
|
|
423
|
+
if (existing) {
|
|
424
|
+
return createErrorResponse("Admin already configured. Use /auth/login to login.", 400);
|
|
425
|
+
}
|
|
414
426
|
const body = await request.json();
|
|
415
427
|
const { username, password } = body;
|
|
428
|
+
console.log("handleSetup: body parsed, username:", username);
|
|
416
429
|
if (!username || !password) {
|
|
417
430
|
return createErrorResponse("Username and password required", 400);
|
|
418
431
|
}
|
|
419
432
|
if (username.length < 3 || password.length < 8) {
|
|
420
433
|
return createErrorResponse("Username must be 3+ chars, password must be 8+ chars", 400);
|
|
421
434
|
}
|
|
435
|
+
console.log("handleSetup: calling setupAuth");
|
|
422
436
|
await setupAuth(env, username, password);
|
|
437
|
+
console.log("handleSetup: setupAuth successful");
|
|
423
438
|
await clearRateLimit(env, clientIP);
|
|
424
439
|
const token = crypto.randomUUID();
|
|
440
|
+
console.log("handleSetup: session token generated");
|
|
425
441
|
await env.KV.put(`session:${token}`, JSON.stringify({
|
|
426
442
|
createdAt: Date.now(),
|
|
427
443
|
expiresAt: Date.now() + 7 * 24 * 60 * 60 * 1e3
|
|
428
444
|
}), { expirationTtl: 7 * 24 * 60 * 60 });
|
|
445
|
+
console.log("handleSetup: session stored in KV");
|
|
429
446
|
const headers = {
|
|
430
447
|
"Content-Type": "application/json",
|
|
431
|
-
"Set-Cookie": createSessionCookie(token, origin)
|
|
448
|
+
"Set-Cookie": createSessionCookie(token, origin),
|
|
449
|
+
"X-Session-Token": token
|
|
432
450
|
};
|
|
433
451
|
return new Response(JSON.stringify({
|
|
434
452
|
success: true,
|
|
@@ -438,7 +456,8 @@ async function handleSetup(request, env, clientIP, origin) {
|
|
|
438
456
|
headers
|
|
439
457
|
});
|
|
440
458
|
} catch (e) {
|
|
441
|
-
|
|
459
|
+
console.error("handleSetup: error occurred:", e);
|
|
460
|
+
return createErrorResponse("Internal server error: " + e.message, 500);
|
|
442
461
|
}
|
|
443
462
|
}
|
|
444
463
|
async function handleStatus(env) {
|
|
@@ -471,7 +490,8 @@ async function handleLogin(request, env, clientIP, origin) {
|
|
|
471
490
|
}), { expirationTtl: 7 * 24 * 60 * 60 });
|
|
472
491
|
const headers = {
|
|
473
492
|
"Content-Type": "application/json",
|
|
474
|
-
"Set-Cookie": createSessionCookie(token, origin)
|
|
493
|
+
"Set-Cookie": createSessionCookie(token, origin),
|
|
494
|
+
"X-Session-Token": token
|
|
475
495
|
};
|
|
476
496
|
return new Response(JSON.stringify({
|
|
477
497
|
success: true,
|
|
@@ -512,14 +532,15 @@ async function handleLogout(request, env) {
|
|
|
512
532
|
}
|
|
513
533
|
const contentCache = /* @__PURE__ */ new Map();
|
|
514
534
|
const CACHE_TTL = 5 * 60 * 1e3;
|
|
515
|
-
|
|
535
|
+
function getCachedOrFetch(key, fetchFn) {
|
|
516
536
|
const cached = contentCache.get(key);
|
|
517
537
|
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
518
|
-
return cached.data;
|
|
538
|
+
return Promise.resolve(cached.data);
|
|
519
539
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
540
|
+
return fetchFn().then((data) => {
|
|
541
|
+
contentCache.set(key, { data, timestamp: Date.now() });
|
|
542
|
+
return data;
|
|
543
|
+
});
|
|
523
544
|
}
|
|
524
545
|
function parseFrontmatter(content) {
|
|
525
546
|
const lines = content.split("\n");
|
|
@@ -549,159 +570,117 @@ function parseFrontmatter(content) {
|
|
|
549
570
|
content: lines.slice(contentStart).join("\n").trim()
|
|
550
571
|
};
|
|
551
572
|
}
|
|
573
|
+
function checkContentBucket(env) {
|
|
574
|
+
if (!env?.CONTENT_BUCKET) {
|
|
575
|
+
return createErrorResponse("Content bucket not configured", 500);
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
async function fetchContentItem(bucket, type, slug) {
|
|
580
|
+
const mdObj = await bucket.get(`${type}/${slug}.md`);
|
|
581
|
+
const jsonObj = await bucket.get(`${type}/${slug}.json`);
|
|
582
|
+
if (!mdObj && !jsonObj) throw new Error(`${type.slice(0, -1)} not found`);
|
|
583
|
+
let metadata = {};
|
|
584
|
+
if (jsonObj) {
|
|
585
|
+
metadata = await jsonObj.json();
|
|
586
|
+
}
|
|
587
|
+
let content = "";
|
|
588
|
+
if (mdObj) {
|
|
589
|
+
const text = await mdObj.text();
|
|
590
|
+
const parsed = parseFrontmatter(text);
|
|
591
|
+
content = parsed.content;
|
|
592
|
+
metadata = { ...parsed.metadata, ...metadata };
|
|
593
|
+
}
|
|
594
|
+
return { ...metadata, slug, content };
|
|
595
|
+
}
|
|
596
|
+
async function fetchContentList(bucket, type, latest) {
|
|
597
|
+
const list = await bucket.list({ prefix: `${type}/` });
|
|
598
|
+
const items = [];
|
|
599
|
+
for (const item of list.objects) {
|
|
600
|
+
if (item.key.endsWith(".json")) {
|
|
601
|
+
const obj = await bucket.get(item.key);
|
|
602
|
+
if (obj) {
|
|
603
|
+
const metadata = await obj.json();
|
|
604
|
+
const slug = item.key.replace(`${type}/`, "").replace(".json", "");
|
|
605
|
+
items.push({ ...metadata, slug });
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const sorted = items.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
610
|
+
return latest ? sorted.slice(0, latest) : sorted;
|
|
611
|
+
}
|
|
612
|
+
async function searchContent(bucket, query) {
|
|
613
|
+
const q = query.toLowerCase();
|
|
614
|
+
const results = [];
|
|
615
|
+
const [blogsList, storiesList] = await Promise.all([
|
|
616
|
+
bucket.list({ prefix: "blogs/" }),
|
|
617
|
+
bucket.list({ prefix: "stories/" })
|
|
618
|
+
]);
|
|
619
|
+
for (const item of [...blogsList.objects, ...storiesList.objects]) {
|
|
620
|
+
if (item.key.endsWith(".md")) {
|
|
621
|
+
const obj = await bucket.get(item.key);
|
|
622
|
+
if (obj) {
|
|
623
|
+
const text = await obj.text();
|
|
624
|
+
const { metadata } = parseFrontmatter(text);
|
|
625
|
+
const matchTitle = metadata.title?.toLowerCase().includes(q);
|
|
626
|
+
const matchDesc = metadata.description?.toLowerCase().includes(q);
|
|
627
|
+
const matchTags = metadata.tags?.some((t) => t.toLowerCase().includes(q));
|
|
628
|
+
if (matchTitle || matchDesc || matchTags) {
|
|
629
|
+
results.push(metadata);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return results;
|
|
635
|
+
}
|
|
552
636
|
async function handleBlogs(env, slug, latest) {
|
|
637
|
+
const bucketCheck = checkContentBucket(env);
|
|
638
|
+
if (bucketCheck) return bucketCheck;
|
|
553
639
|
try {
|
|
554
|
-
if (!env?.CONTENT_BUCKET) {
|
|
555
|
-
return new Response(JSON.stringify({ error: "Content bucket not configured" }), {
|
|
556
|
-
status: 500,
|
|
557
|
-
headers: { "Content-Type": "application/json" }
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
640
|
const cacheKey = slug ? `blog-${slug}` : `blogs-list-${latest || "all"}`;
|
|
561
641
|
const result = await getCachedOrFetch(cacheKey, async () => {
|
|
562
642
|
if (slug) {
|
|
563
|
-
|
|
564
|
-
const jsonObj = await env.CONTENT_BUCKET.get(`blogs/${slug}.json`);
|
|
565
|
-
if (!mdObj && !jsonObj) throw new Error("Blog not found");
|
|
566
|
-
let metadata = {};
|
|
567
|
-
if (jsonObj) {
|
|
568
|
-
metadata = await jsonObj.json();
|
|
569
|
-
}
|
|
570
|
-
let content = "";
|
|
571
|
-
if (mdObj) {
|
|
572
|
-
const text = await mdObj.text();
|
|
573
|
-
const parsed = parseFrontmatter(text);
|
|
574
|
-
content = parsed.content;
|
|
575
|
-
metadata = { ...parsed.metadata, ...metadata };
|
|
576
|
-
}
|
|
577
|
-
return { ...metadata, slug, content };
|
|
578
|
-
}
|
|
579
|
-
const list = await env.CONTENT_BUCKET.list({ prefix: "blogs/" });
|
|
580
|
-
const blogs = [];
|
|
581
|
-
for (const item of list.objects) {
|
|
582
|
-
if (item.key.endsWith(".json")) {
|
|
583
|
-
const obj = await env.CONTENT_BUCKET.get(item.key);
|
|
584
|
-
if (obj) {
|
|
585
|
-
const metadata = await obj.json();
|
|
586
|
-
const slug2 = item.key.replace("blogs/", "").replace(".json", "");
|
|
587
|
-
blogs.push({ ...metadata, slug: slug2 });
|
|
588
|
-
}
|
|
589
|
-
}
|
|
643
|
+
return await fetchContentItem(env.CONTENT_BUCKET, "blogs", slug);
|
|
590
644
|
}
|
|
591
|
-
|
|
592
|
-
return latest ? sorted.slice(0, latest) : sorted;
|
|
593
|
-
});
|
|
594
|
-
return new Response(JSON.stringify(result), {
|
|
595
|
-
headers: { "Content-Type": "application/json" }
|
|
645
|
+
return await fetchContentList(env.CONTENT_BUCKET, "blogs", latest);
|
|
596
646
|
});
|
|
647
|
+
return createJSONResponse(result);
|
|
597
648
|
} catch (error) {
|
|
598
649
|
console.error("Error serving blogs:", error);
|
|
599
|
-
return
|
|
600
|
-
status: 404,
|
|
601
|
-
headers: { "Content-Type": "application/json" }
|
|
602
|
-
});
|
|
650
|
+
return createErrorResponse("Blog not found", 404);
|
|
603
651
|
}
|
|
604
652
|
}
|
|
605
653
|
async function handleStories(env, slug, latest) {
|
|
654
|
+
const bucketCheck = checkContentBucket(env);
|
|
655
|
+
if (bucketCheck) return bucketCheck;
|
|
606
656
|
try {
|
|
607
|
-
if (!env?.CONTENT_BUCKET) {
|
|
608
|
-
return new Response(JSON.stringify({ error: "Content bucket not configured" }), {
|
|
609
|
-
status: 500,
|
|
610
|
-
headers: { "Content-Type": "application/json" }
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
657
|
const cacheKey = slug ? `story-${slug}` : `stories-list-${latest || "all"}`;
|
|
614
658
|
const result = await getCachedOrFetch(cacheKey, async () => {
|
|
615
659
|
if (slug) {
|
|
616
|
-
|
|
617
|
-
const jsonObj = await env.CONTENT_BUCKET.get(`stories/${slug}.json`);
|
|
618
|
-
if (!mdObj && !jsonObj) throw new Error("Story not found");
|
|
619
|
-
let metadata = {};
|
|
620
|
-
if (jsonObj) {
|
|
621
|
-
metadata = await jsonObj.json();
|
|
622
|
-
}
|
|
623
|
-
let content = "";
|
|
624
|
-
if (mdObj) {
|
|
625
|
-
const text = await mdObj.text();
|
|
626
|
-
const parsed = parseFrontmatter(text);
|
|
627
|
-
content = parsed.content;
|
|
628
|
-
metadata = { ...parsed.metadata, ...metadata };
|
|
629
|
-
}
|
|
630
|
-
return { ...metadata, slug, content };
|
|
631
|
-
}
|
|
632
|
-
const list = await env.CONTENT_BUCKET.list({ prefix: "stories/" });
|
|
633
|
-
const stories = [];
|
|
634
|
-
for (const item of list.objects) {
|
|
635
|
-
if (item.key.endsWith(".json")) {
|
|
636
|
-
const obj = await env.CONTENT_BUCKET.get(item.key);
|
|
637
|
-
if (obj) {
|
|
638
|
-
const metadata = await obj.json();
|
|
639
|
-
const slug2 = item.key.replace("stories/", "").replace(".json", "");
|
|
640
|
-
stories.push({ ...metadata, slug: slug2 });
|
|
641
|
-
}
|
|
642
|
-
}
|
|
660
|
+
return await fetchContentItem(env.CONTENT_BUCKET, "stories", slug);
|
|
643
661
|
}
|
|
644
|
-
|
|
645
|
-
return latest ? sorted.slice(0, latest) : sorted;
|
|
646
|
-
});
|
|
647
|
-
return new Response(JSON.stringify(result), {
|
|
648
|
-
headers: { "Content-Type": "application/json" }
|
|
662
|
+
return await fetchContentList(env.CONTENT_BUCKET, "stories", latest);
|
|
649
663
|
});
|
|
664
|
+
return createJSONResponse(result);
|
|
650
665
|
} catch (error) {
|
|
651
666
|
console.error("Error serving stories:", error);
|
|
652
|
-
return
|
|
653
|
-
status: 404,
|
|
654
|
-
headers: { "Content-Type": "application/json" }
|
|
655
|
-
});
|
|
667
|
+
return createErrorResponse("Story not found", 404);
|
|
656
668
|
}
|
|
657
669
|
}
|
|
658
670
|
async function handleSearch(env, query) {
|
|
671
|
+
const bucketCheck = checkContentBucket(env);
|
|
672
|
+
if (bucketCheck) return bucketCheck;
|
|
673
|
+
if (!query) {
|
|
674
|
+
return createErrorResponse("Search query required", 400);
|
|
675
|
+
}
|
|
659
676
|
try {
|
|
660
|
-
if (!env?.CONTENT_BUCKET) {
|
|
661
|
-
return new Response(JSON.stringify({ error: "Content bucket not configured" }), {
|
|
662
|
-
status: 500,
|
|
663
|
-
headers: { "Content-Type": "application/json" }
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
if (!query) {
|
|
667
|
-
return new Response(JSON.stringify({ error: "Search query required" }), {
|
|
668
|
-
status: 400,
|
|
669
|
-
headers: { "Content-Type": "application/json" }
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
677
|
const searchResults = await getCachedOrFetch(`search-${query}`, async () => {
|
|
673
|
-
|
|
674
|
-
const results = [];
|
|
675
|
-
const [blogsList, storiesList] = await Promise.all([
|
|
676
|
-
env.CONTENT_BUCKET.list({ prefix: "blogs/" }),
|
|
677
|
-
env.CONTENT_BUCKET.list({ prefix: "stories/" })
|
|
678
|
-
]);
|
|
679
|
-
for (const item of [...blogsList.objects, ...storiesList.objects]) {
|
|
680
|
-
if (item.key.endsWith(".md")) {
|
|
681
|
-
const obj = await env.CONTENT_BUCKET.get(item.key);
|
|
682
|
-
if (obj) {
|
|
683
|
-
const text = await obj.text();
|
|
684
|
-
const { metadata } = parseFrontmatter(text);
|
|
685
|
-
const matchTitle = metadata.title?.toLowerCase().includes(q);
|
|
686
|
-
const matchDesc = metadata.description?.toLowerCase().includes(q);
|
|
687
|
-
const matchTags = metadata.tags?.some((t) => t.toLowerCase().includes(q));
|
|
688
|
-
if (matchTitle || matchDesc || matchTags) {
|
|
689
|
-
results.push(metadata);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
return results;
|
|
695
|
-
});
|
|
696
|
-
return new Response(JSON.stringify(searchResults), {
|
|
697
|
-
headers: { "Content-Type": "application/json" }
|
|
678
|
+
return await searchContent(env.CONTENT_BUCKET, query);
|
|
698
679
|
});
|
|
680
|
+
return createJSONResponse(searchResults);
|
|
699
681
|
} catch (error) {
|
|
700
682
|
console.error("Error serving search:", error);
|
|
701
|
-
return
|
|
702
|
-
status: 500,
|
|
703
|
-
headers: { "Content-Type": "application/json" }
|
|
704
|
-
});
|
|
683
|
+
return createErrorResponse("Search failed", 500);
|
|
705
684
|
}
|
|
706
685
|
}
|
|
707
686
|
const PLACEHOLDER_LOGO = `<svg width="600" height="320" viewBox="0 0 600 320" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -770,7 +749,7 @@ async function handleStaticDetails(env, method, body) {
|
|
|
770
749
|
});
|
|
771
750
|
}
|
|
772
751
|
if (!method || method === "GET") {
|
|
773
|
-
const staticDetails = await env.CONTENT_BUCKET.get("
|
|
752
|
+
const staticDetails = await env.CONTENT_BUCKET.get("static-details.json");
|
|
774
753
|
if (staticDetails) {
|
|
775
754
|
const data = await staticDetails.json();
|
|
776
755
|
return new Response(JSON.stringify({ ...DEFAULT_STATIC_DETAILS, ...data }), {
|
|
@@ -808,25 +787,25 @@ class WebsiteAPI {
|
|
|
808
787
|
addCORSHeaders(response) {
|
|
809
788
|
response.headers.set("Access-Control-Allow-Origin", "*");
|
|
810
789
|
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
811
|
-
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
790
|
+
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Session-Token");
|
|
812
791
|
return response;
|
|
813
792
|
}
|
|
814
793
|
addAdminCORSHeaders(response, origin) {
|
|
815
|
-
const allowOrigin = origin.includes("localhost") || origin.includes("127.0.0.1") ? origin : "same-origin";
|
|
794
|
+
const allowOrigin = origin && (origin.includes("localhost") || origin.includes("127.0.0.1")) ? origin : "same-origin";
|
|
816
795
|
response.headers.set("Access-Control-Allow-Origin", allowOrigin);
|
|
817
796
|
response.headers.set("Access-Control-Allow-Credentials", "true");
|
|
818
797
|
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
819
|
-
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
798
|
+
response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Session-Token");
|
|
820
799
|
return response;
|
|
821
800
|
}
|
|
822
801
|
handleCORS(origin) {
|
|
823
|
-
const allowOrigin = origin.includes("localhost") || origin.includes("127.0.0.1") ? origin : "*";
|
|
802
|
+
const allowOrigin = origin && (origin.includes("localhost") || origin.includes("127.0.0.1")) ? origin : "*";
|
|
824
803
|
return new Response(null, {
|
|
825
804
|
status: 200,
|
|
826
805
|
headers: {
|
|
827
806
|
"Access-Control-Allow-Origin": allowOrigin,
|
|
828
807
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
|
|
829
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
808
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Session-Token",
|
|
830
809
|
"Access-Control-Allow-Credentials": "true",
|
|
831
810
|
"Access-Control-Max-Age": "86400"
|
|
832
811
|
}
|
|
@@ -849,6 +828,10 @@ class WebsiteAPI {
|
|
|
849
828
|
const subpath = route.replace(/^content\/?/, "");
|
|
850
829
|
return this.addAdminCORSHeaders(await handleContent(request, env, subpath), origin);
|
|
851
830
|
}
|
|
831
|
+
if (route === "auth" || route.startsWith("auth/")) {
|
|
832
|
+
const subpath = route.replace(/^auth\/?/, "");
|
|
833
|
+
return this.addAdminCORSHeaders(await handleAuth(request, env, subpath || "/"), origin);
|
|
834
|
+
}
|
|
852
835
|
switch (route) {
|
|
853
836
|
case "info":
|
|
854
837
|
return this.addCORSHeaders(await handleInfo());
|
|
@@ -869,8 +852,6 @@ class WebsiteAPI {
|
|
|
869
852
|
return this.addCORSHeaders(await handleLogo(env));
|
|
870
853
|
case "static":
|
|
871
854
|
return this.addCORSHeaders(await handleStaticDetails(env));
|
|
872
|
-
case "auth":
|
|
873
|
-
return this.addAdminCORSHeaders(await handleAuth(request, env, "/auth"), origin);
|
|
874
855
|
case "blogs":
|
|
875
856
|
return this.addCORSHeaders(await handleBlogs(env));
|
|
876
857
|
case "blogs/latest":
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
-
import { A, B, M, R, W, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-
|
|
1
|
+
import { A, B, M, R, W, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-BEYGOsT3.js";
|
|
2
2
|
import { WebsitePrerender } from "./prerender.js";
|
|
3
|
-
import { A as A2, B as B2, F, M as M2,
|
|
4
|
-
import { R as R2, S as S2, T, W as W2, b as
|
|
3
|
+
import { A as A2, a as a2, b as b2, c as c2, d as d2, e as e2, f, g as g2, h as h2, i, B as B2, F, M as M2, j, S, k } from "./chunks/index-CnSEOZse.js";
|
|
4
|
+
import { R as R2, S as S2, T, W as W2, b as b3, c as c3, g as g3, a as a3, i as i2, r as r2 } from "./chunks/template-DWcsZW22.js";
|
|
5
5
|
export {
|
|
6
6
|
A as AUTH_KV,
|
|
7
|
-
A2 as
|
|
7
|
+
A2 as AdminAboutMeSection,
|
|
8
|
+
a2 as AdminBlogsSection,
|
|
9
|
+
b2 as AdminHomeSection,
|
|
10
|
+
c2 as AdminImagesSection,
|
|
11
|
+
d2 as AdminLoginForm,
|
|
12
|
+
e2 as AdminLogoSection,
|
|
13
|
+
f as AdminPortal,
|
|
14
|
+
g2 as AdminProfileSection,
|
|
15
|
+
h2 as AdminStaticSection,
|
|
16
|
+
i as AdminStoriesSection,
|
|
8
17
|
B as BASE_DELAY_MS,
|
|
9
18
|
B2 as BlogViewer,
|
|
10
19
|
F as FooterComponent,
|
|
11
20
|
M as MAX_ATTEMPTS,
|
|
12
21
|
M2 as MyAboutme,
|
|
13
|
-
|
|
22
|
+
j as MyBanner,
|
|
14
23
|
R as RATE_LIMIT_KV,
|
|
15
24
|
R2 as Router,
|
|
16
25
|
S2 as SiteStore,
|
|
@@ -19,18 +28,19 @@ export {
|
|
|
19
28
|
W as WebsiteAPI,
|
|
20
29
|
WebsitePrerender,
|
|
21
30
|
W2 as WebsiteUI,
|
|
22
|
-
|
|
31
|
+
k as adminLoaded,
|
|
32
|
+
b3 as bootstrap,
|
|
23
33
|
c as checkRateLimit,
|
|
24
34
|
a as clearRateLimit,
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
c3 as createHtmlTemplate,
|
|
36
|
+
g3 as generatePageContent,
|
|
27
37
|
g as generateSalt,
|
|
28
38
|
b as getAuthStore,
|
|
29
39
|
d as getClientIP,
|
|
30
40
|
a3 as getConfig,
|
|
31
41
|
h as handleAuth,
|
|
32
42
|
e as hashPassword,
|
|
33
|
-
|
|
43
|
+
i2 as initializeConfig,
|
|
34
44
|
r as recordFailedAttempt,
|
|
35
45
|
r2 as renderMarkdown,
|
|
36
46
|
s as setupAuth,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface Profile {
|
|
2
|
+
name: string;
|
|
3
|
+
title: string;
|
|
4
|
+
experience: string;
|
|
5
|
+
profileImageUrl: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BlogMeta {
|
|
8
|
+
slug: string;
|
|
9
|
+
title: string;
|
|
10
|
+
summary: string;
|
|
11
|
+
tags: string[];
|
|
12
|
+
date: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function fetchProfile(env: any): Promise<Profile | null>;
|
|
15
|
+
export declare function fetchAboutMe(env: any): Promise<string>;
|
|
16
|
+
export declare function fetchHome(env: any): Promise<string>;
|
|
17
|
+
export declare function fetchLatestBlogSummaries(env: any, count?: number): Promise<BlogMeta[]>;
|
|
18
|
+
export declare function fetchLatestStorySummaries(env: any, count?: number): Promise<BlogMeta[]>;
|
|
19
|
+
//# sourceMappingURL=data-fetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-fetcher.d.ts","sourceRoot":"","sources":["../../src/prerender/data-fetcher.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAeD,wBAAsB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQpE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAO5D;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzD;AAED,wBAAsB,wBAAwB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAgB/F;AAED,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAgBhG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-content.d.ts","sourceRoot":"","sources":["../../src/prerender/page-content.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAuFD,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,EAChB,QAAQ,MAAM,EAAE,EAChB,aAAa,WAAW,EAAE,EAC1B,MAAM,GAAG,KACR,OAAO,CAAC,WAAW,
|
|
1
|
+
{"version":3,"file":"page-content.d.ts","sourceRoot":"","sources":["../../src/prerender/page-content.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAuFD,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,EAChB,QAAQ,MAAM,EAAE,EAChB,aAAa,WAAW,EAAE,EAC1B,MAAM,GAAG,KACR,OAAO,CAAC,WAAW,CAqJrB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BasePageGenerator, StaticDetails } from './base';
|
|
2
|
+
import { IRoute, IFooterLink, PageContent } from '../page-content';
|
|
3
|
+
import { Profile } from '../data-fetcher';
|
|
4
|
+
export interface AboutPageData {
|
|
5
|
+
routes: IRoute[];
|
|
6
|
+
footerLinks: IFooterLink[];
|
|
7
|
+
staticDetails: StaticDetails;
|
|
8
|
+
apiUrl: string;
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
pathname: string;
|
|
11
|
+
profile: Profile | null;
|
|
12
|
+
}
|
|
13
|
+
export declare class AboutPageGenerator extends BasePageGenerator {
|
|
14
|
+
generate(data: AboutPageData): PageContent;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=about.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"about.d.ts","sourceRoot":"","sources":["../../../src/prerender/page-generators/about.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,qBAAa,kBAAmB,SAAQ,iBAAiB;IAChD,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,WAAW;CAsBlD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IRoute, IFooterLink, PageContent } from '../page-content';
|
|
2
|
+
export interface StaticDetails {
|
|
3
|
+
siteTitle?: string;
|
|
4
|
+
copyright?: string;
|
|
5
|
+
linkedin?: string;
|
|
6
|
+
github?: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BasePageData {
|
|
10
|
+
routes: IRoute[];
|
|
11
|
+
footerLinks: IFooterLink[];
|
|
12
|
+
staticDetails: StaticDetails;
|
|
13
|
+
apiUrl: string;
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
pathname: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class BasePageGenerator {
|
|
20
|
+
protected generateBanner(routes: IRoute[], siteTitle: string, logo: string): string;
|
|
21
|
+
protected generateFooter(footerLinks: IFooterLink[], copyright: string): string;
|
|
22
|
+
protected generateMeta(title: string, description: string, canonicalUrl: string): void;
|
|
23
|
+
protected wrapContent(banner: string, mainContent: string, footer: string): string;
|
|
24
|
+
generatePage(pathname: string, routes: IRoute[], footerLinks: IFooterLink[], staticDetails: StaticDetails, apiUrl: string, baseUrl: string, mainContent: string, title: string, description: string): PageContent;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/prerender/page-generators/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,iBAAiB;IAC5B,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAcnF,SAAS,CAAC,cAAc,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAQ/E,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAItF,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAI3E,YAAY,CACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,WAAW,EAAE,WAAW,EAAE,EAC1B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,WAAW;CAcf"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BasePageGenerator, StaticDetails } from './base';
|
|
2
|
+
import { IRoute, IFooterLink, PageContent } from '../page-content';
|
|
3
|
+
export interface BlogDetailPageData {
|
|
4
|
+
routes: IRoute[];
|
|
5
|
+
footerLinks: IFooterLink[];
|
|
6
|
+
staticDetails: StaticDetails;
|
|
7
|
+
apiUrl: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
pathname: string;
|
|
10
|
+
slug: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class BlogDetailPageGenerator extends BasePageGenerator {
|
|
13
|
+
generate(data: BlogDetailPageData): PageContent;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=blog-detail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blog-detail.d.ts","sourceRoot":"","sources":["../../../src/prerender/page-generators/blog-detail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,uBAAwB,SAAQ,iBAAiB;IACrD,QAAQ,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW;CAoBvD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BasePageGenerator, StaticDetails } from './base';
|
|
2
|
+
import { IRoute, IFooterLink, PageContent } from '../page-content';
|
|
3
|
+
import { BlogMeta } from '../data-fetcher';
|
|
4
|
+
export interface BlogsListPageData {
|
|
5
|
+
routes: IRoute[];
|
|
6
|
+
footerLinks: IFooterLink[];
|
|
7
|
+
staticDetails: StaticDetails;
|
|
8
|
+
apiUrl: string;
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
pathname: string;
|
|
11
|
+
latestBlogs: BlogMeta[];
|
|
12
|
+
name: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class BlogsListPageGenerator extends BasePageGenerator {
|
|
15
|
+
generate(data: BlogsListPageData): PageContent;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=blogs-list.d.ts.map
|