@leadertechie/personal-site-kit 0.1.0-alpha.16 → 0.1.0-alpha.17
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 +94 -17
- package/dist/api/content-utils.d.ts.map +1 -1
- package/dist/api/handlers/about-me.d.ts.map +1 -1
- package/dist/api/handlers/home.d.ts.map +1 -1
- package/dist/api.js +2 -2
- package/dist/chunks/{index-B2jGIzSi.js → index-DAog9TQE.js} +24 -2
- package/dist/chunks/{template-DXUSp0BG.js → template-DUdadCrH.js} +63 -5
- package/dist/chunks/{website-api-C3lGjXdD.js → website-api-Cy2kZ0dC.js} +59 -9
- package/dist/index.js +3 -3
- package/dist/prerender/data-fetcher.d.ts.map +1 -1
- package/dist/prerender/page-content.d.ts.map +1 -1
- package/dist/prerender/template.d.ts.map +1 -1
- package/dist/prerender.js +52 -3
- package/dist/shared/core/theme-toggle.d.ts.map +1 -1
- package/dist/shared/page-content.d.ts.map +1 -1
- package/dist/shared/router.d.ts +5 -0
- package/dist/shared/router.d.ts.map +1 -1
- package/dist/shared/website-ui.d.ts +21 -0
- package/dist/shared/website-ui.d.ts.map +1 -1
- package/dist/shared.js +1 -1
- package/dist/ui/blog-viewer/index.d.ts.map +1 -1
- package/dist/ui/story-viewer/index.d.ts.map +1 -1
- package/dist/ui.js +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @leadertechie/personal-site-kit
|
|
2
2
|
|
|
3
|
-
A high-performance, modular engine for building personal websites and professional portfolios. Powered by Cloudflare Workers, R2 Storage,
|
|
3
|
+
A high-performance, modular engine for building personal websites and professional portfolios. Powered by Cloudflare Workers, R2 Storage, Lit Web Components, and the **@leadertechie** ecosystem.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -8,18 +8,21 @@ A high-performance, modular engine for building personal websites and profession
|
|
|
8
8
|
- **🛠️ 4-Section Engine**: Fully integrated logic for **API**, **UI**, **Prerender**, and **Admin**.
|
|
9
9
|
- **🎨 Modern Layout**: Semantic grid system with responsive `main-column` and `sidebar-column` components.
|
|
10
10
|
- **🌓 Theme Engine**: Built-in light/dark mode support with persistent user preferences.
|
|
11
|
-
- **📝 Content Driven**: Dynamic Markdown rendering with frontmatter support via `@leadertechie/md2html
|
|
11
|
+
- **📝 Content Driven**: Dynamic Markdown rendering with frontmatter support via `@leadertechie/md2html` (v2).
|
|
12
12
|
- **⚙️ Remote Config**: Manage site settings (title, copyright, social links) directly from R2 without re-deploying.
|
|
13
13
|
- **🔍 SEO Optimized**: Server-side prerendering ensures search engines see your content perfectly.
|
|
14
|
+
- **🔄 SWR Caching**: Stale-while-revalidate caching via `@leadertechie/r2tohtml` for optimal performance.
|
|
15
|
+
- **⚡ Client-Side Interactivity**: DOM interaction patterns (poll, live-update, click-toggle, infinite-scroll, form-live) via `@leadertechie/md2interact`.
|
|
16
|
+
- **🎯 CSS Hydration**: Inline critical CSS, layer injection, and theme toggle support.
|
|
14
17
|
|
|
15
18
|
## Architecture
|
|
16
19
|
|
|
17
20
|
The kit is divided into four logical subpaths:
|
|
18
21
|
|
|
19
|
-
1. **/shared**: Common interfaces, types,
|
|
20
|
-
2. **/ui**: Web components for the Banner, Footer, About Me, and Admin Portal.
|
|
21
|
-
3. **/api**: Standard handlers for Cloudflare Workers to manage R2 content.
|
|
22
|
-
4. **/prerender**: SEO engine to generate static HTML for crawlers.
|
|
22
|
+
1. **/shared**: Common interfaces, types, the reactive `SiteStore`, and the `WebsiteUI` bootstrap.
|
|
23
|
+
2. **/ui**: Web components for the Banner, Footer, About Me, Blog Viewer, Story Viewer, and Admin Portal.
|
|
24
|
+
3. **/api**: Standard handlers for Cloudflare Workers to manage R2 content with v2 caching.
|
|
25
|
+
4. **/prerender**: SEO engine to generate static HTML for crawlers with SWR caching.
|
|
23
26
|
|
|
24
27
|
## Installation
|
|
25
28
|
|
|
@@ -29,26 +32,100 @@ npm install @leadertechie/personal-site-kit
|
|
|
29
32
|
|
|
30
33
|
## Quick Start (Usage)
|
|
31
34
|
|
|
32
|
-
### 1. API Worker (`api.ts`)
|
|
35
|
+
### 1. API Worker (`api/index.ts`)
|
|
36
|
+
|
|
33
37
|
```typescript
|
|
34
|
-
import {
|
|
38
|
+
import { WebsiteAPI } from '@leadertechie/personal-site-kit/api';
|
|
39
|
+
|
|
40
|
+
export default new WebsiteAPI();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 2. UI Entry (`ui/index.ts`)
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
```typescript
|
|
46
|
+
import { WebsiteUI } from '@leadertechie/personal-site-kit/shared';
|
|
47
|
+
import '@leadertechie/personal-site-kit/styles/theme.css';
|
|
48
|
+
import '@leadertechie/personal-site-kit/ui';
|
|
49
|
+
|
|
50
|
+
// Bootstrap the UI — md2interact is automatically initialized
|
|
51
|
+
WebsiteUI.getInstance({
|
|
52
|
+
apiUrl: window.location.origin,
|
|
53
|
+
// Optional: configure md2interact interactions
|
|
54
|
+
interactConfig: {
|
|
55
|
+
interactions: {
|
|
56
|
+
'poll': { selector: '[data-interact="poll"]' },
|
|
57
|
+
'live-update': { selector: '[data-interact="live-update"]' },
|
|
58
|
+
'click-toggle': { selector: '[data-interact="click-toggle"]' },
|
|
59
|
+
'infinite-scroll': { selector: '[data-interact="infinite-scroll"]' },
|
|
60
|
+
'form-live': { selector: '[data-interact="form-live"]' }
|
|
61
|
+
},
|
|
62
|
+
cssHydration: {
|
|
63
|
+
inlineCritical: true,
|
|
64
|
+
layerInjection: true,
|
|
65
|
+
themeToggle: true
|
|
66
|
+
}
|
|
39
67
|
}
|
|
40
|
-
};
|
|
68
|
+
}).bootstrap();
|
|
41
69
|
```
|
|
42
70
|
|
|
43
|
-
###
|
|
71
|
+
### 3. Prerender (`prerender/index.ts`)
|
|
72
|
+
|
|
44
73
|
```typescript
|
|
45
|
-
import {
|
|
46
|
-
import '@leadertechie/personal-site-kit/ui/banner';
|
|
74
|
+
import { WebsitePrerender } from '@leadertechie/personal-site-kit/prerender';
|
|
47
75
|
|
|
48
|
-
|
|
49
|
-
await store.init({ apiUrl: 'https://api.yourdomain.com' });
|
|
76
|
+
export default new WebsitePrerender();
|
|
50
77
|
```
|
|
51
78
|
|
|
79
|
+
## Client-Side Interactivity with md2interact
|
|
80
|
+
|
|
81
|
+
The kit automatically initializes `@leadertechie/md2interact` during `WebsiteUI.bootstrap()`. This enables:
|
|
82
|
+
|
|
83
|
+
### DOM Interaction Patterns
|
|
84
|
+
|
|
85
|
+
Markdown content with frontmatter can declare interaction patterns:
|
|
86
|
+
|
|
87
|
+
```markdown
|
|
88
|
+
---
|
|
89
|
+
interaction: poll
|
|
90
|
+
interactConfig:
|
|
91
|
+
url: /api/data
|
|
92
|
+
interval: 5000
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
# Live Poll Data
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Supported patterns: `poll`, `live-update`, `click-toggle`, `infinite-scroll`, `form-live`, `mfe`, `custom`
|
|
99
|
+
|
|
100
|
+
### CSS Hydration
|
|
101
|
+
|
|
102
|
+
- **inlineCritical**: Injects critical CSS directly into the DOM
|
|
103
|
+
- **layerInjection**: Uses CSS `@layer` for organized style injection
|
|
104
|
+
- **themeToggle**: Enables light/dark theme toggling
|
|
105
|
+
|
|
106
|
+
### SPA Navigation
|
|
107
|
+
|
|
108
|
+
After dynamic content loads (e.g., blog detail pages), call `reinitInteract()` to re-scan the DOM:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
const ui = WebsiteUI.getInstance();
|
|
112
|
+
ui.reinitInteract();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Caching Strategy (v2)
|
|
116
|
+
|
|
117
|
+
The kit uses `@leadertechie/r2tohtml` with a multi-tier caching strategy:
|
|
118
|
+
|
|
119
|
+
| Tier | Cache | TTL |
|
|
120
|
+
|------|-------|-----|
|
|
121
|
+
| In-Memory | `ContentCacheV2` with SWR | 5 min fresh, 30 min stale |
|
|
122
|
+
| Cloudflare Edge | `cfCache` | 5 min |
|
|
123
|
+
|
|
124
|
+
This means:
|
|
125
|
+
- **Fresh**: Served instantly from memory
|
|
126
|
+
- **Stale**: Served from memory while revalidating in background (SWR)
|
|
127
|
+
- **Miss**: Fetched from R2, cached at edge and in-memory
|
|
128
|
+
|
|
52
129
|
## Deployment
|
|
53
130
|
|
|
54
131
|
This kit is designed to be deployed to **Cloudflare**. Ensure your `wrangler.toml` is configured with an R2 bucket named `CONTENT_BUCKET`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-utils.d.ts","sourceRoot":"","sources":["../../src/api/content-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"content-utils.d.ts","sourceRoot":"","sources":["../../src/api/content-utils.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAS,SAAQ,eAAe;IAC/C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAU,SAAQ,eAAe;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AASD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAoBtF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAMvD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA6BhG;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ,GAAG,IAAI,CAK5D;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAqB1H;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAiB1H;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC,CA2BjG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"about-me.d.ts","sourceRoot":"","sources":["../../../src/api/handlers/about-me.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"about-me.d.ts","sourceRoot":"","sources":["../../../src/api/handlers/about-me.ts"],"names":[],"mappings":"AA0DA,wBAAgB,iBAAiB,SAEhC;AAED,wBAAsB,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4DhE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/api/handlers/home.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/api/handlers/home.ts"],"names":[],"mappings":"AA+CA,wBAAgB,iBAAiB,SAEhC;AAED,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwC7D"}
|
package/dist/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { W as WebsiteAPI } from "./chunks/website-api-
|
|
2
|
-
import { A, B, M, R, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-
|
|
1
|
+
import { W as WebsiteAPI } from "./chunks/website-api-Cy2kZ0dC.js";
|
|
2
|
+
import { A, B, M, R, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-Cy2kZ0dC.js";
|
|
3
3
|
const defaultAPI = new WebsiteAPI();
|
|
4
4
|
export {
|
|
5
5
|
A as AUTH_KV,
|
|
@@ -2385,9 +2385,20 @@ var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "
|
|
|
2385
2385
|
var _error_dec$1, _loading_dec$1, _blogPost_dec, _slug_dec$1, _a$1, _BlogViewer_decorators, _init$1, _slug$1, _blogPost, _loading$1, _error$1;
|
|
2386
2386
|
const pipeline$1 = new MarkdownPipeline({
|
|
2387
2387
|
imagePathPrefix: "images/",
|
|
2388
|
+
preserveRawHTML: true,
|
|
2389
|
+
errorRecovery: "warn",
|
|
2390
|
+
maxRecursionDepth: 50,
|
|
2388
2391
|
styleOptions: {
|
|
2389
2392
|
classPrefix: "md-",
|
|
2390
|
-
addHeadingIds: true
|
|
2393
|
+
addHeadingIds: true,
|
|
2394
|
+
emitScopeAnchors: true
|
|
2395
|
+
},
|
|
2396
|
+
slotPattern: /\[\[(.*?)\]\]/g,
|
|
2397
|
+
onSlot: (name) => {
|
|
2398
|
+
const slotMap = {
|
|
2399
|
+
"CURRENT_YEAR": (/* @__PURE__ */ new Date()).getFullYear().toString()
|
|
2400
|
+
};
|
|
2401
|
+
return slotMap[name] || `[[${name}]]`;
|
|
2391
2402
|
}
|
|
2392
2403
|
});
|
|
2393
2404
|
_BlogViewer_decorators = [customElement("my-blog-viewer")];
|
|
@@ -2583,9 +2594,20 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2583
2594
|
var _error_dec, _loading_dec, _storyPost_dec, _slug_dec, _a, _StoryViewer_decorators, _init, _slug, _storyPost, _loading, _error;
|
|
2584
2595
|
const pipeline = new MarkdownPipeline({
|
|
2585
2596
|
imagePathPrefix: "images/",
|
|
2597
|
+
preserveRawHTML: true,
|
|
2598
|
+
errorRecovery: "warn",
|
|
2599
|
+
maxRecursionDepth: 50,
|
|
2586
2600
|
styleOptions: {
|
|
2587
2601
|
classPrefix: "md-",
|
|
2588
|
-
addHeadingIds: true
|
|
2602
|
+
addHeadingIds: true,
|
|
2603
|
+
emitScopeAnchors: true
|
|
2604
|
+
},
|
|
2605
|
+
slotPattern: /\[\[(.*?)\]\]/g,
|
|
2606
|
+
onSlot: (name) => {
|
|
2607
|
+
const slotMap = {
|
|
2608
|
+
"CURRENT_YEAR": (/* @__PURE__ */ new Date()).getFullYear().toString()
|
|
2609
|
+
};
|
|
2610
|
+
return slotMap[name] || `[[${name}]]`;
|
|
2589
2611
|
}
|
|
2590
2612
|
});
|
|
2591
2613
|
_StoryViewer_decorators = [customElement("my-story-viewer")];
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import { S as SiteStore } from "./site-store-CGV9c2DI.js";
|
|
2
2
|
import { MarkdownPipeline } from "@leadertechie/r2tohtml";
|
|
3
|
+
import { init, reinit } from "@leadertechie/md2interact";
|
|
3
4
|
const pipeline = new MarkdownPipeline({
|
|
4
5
|
imagePathPrefix: "images/",
|
|
6
|
+
preserveRawHTML: true,
|
|
7
|
+
errorRecovery: "warn",
|
|
8
|
+
maxRecursionDepth: 50,
|
|
5
9
|
styleOptions: {
|
|
6
10
|
classPrefix: "md-",
|
|
7
|
-
addHeadingIds: true
|
|
11
|
+
addHeadingIds: true,
|
|
12
|
+
emitScopeAnchors: true
|
|
13
|
+
},
|
|
14
|
+
slotPattern: /\[\[(.*?)\]\]/g,
|
|
15
|
+
onSlot: (name) => {
|
|
16
|
+
const slotMap = {
|
|
17
|
+
"SITE_TITLE": document?.querySelector("title")?.textContent || "My Site",
|
|
18
|
+
"CURRENT_YEAR": (/* @__PURE__ */ new Date()).getFullYear().toString()
|
|
19
|
+
};
|
|
20
|
+
return slotMap[name] || `[[${name}]]`;
|
|
8
21
|
}
|
|
9
22
|
});
|
|
10
23
|
const renderMarkdown = (content) => {
|
|
@@ -277,6 +290,13 @@ class Router {
|
|
|
277
290
|
}
|
|
278
291
|
canonicalLink.setAttribute("href", url);
|
|
279
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* After rendering new content, reinitialize md2interact so it
|
|
295
|
+
* re-scans the DOM for interaction elements (poll, live-update, etc.)
|
|
296
|
+
*/
|
|
297
|
+
afterRender() {
|
|
298
|
+
this.ui.reinitInteract();
|
|
299
|
+
}
|
|
280
300
|
async renderHomePage() {
|
|
281
301
|
let blogs = [];
|
|
282
302
|
let stories = [];
|
|
@@ -311,6 +331,7 @@ class Router {
|
|
|
311
331
|
});
|
|
312
332
|
if (this.appElement) this.appElement.innerHTML = pageContent.content;
|
|
313
333
|
this.setPageMeta(pageContent.title, pageContent.description, pageContent.canonicalUrl);
|
|
334
|
+
this.afterRender();
|
|
314
335
|
}
|
|
315
336
|
renderAboutMePage() {
|
|
316
337
|
const pageContent = generatePageContent("/about-me", this.routes, this.footerLinks, {
|
|
@@ -320,6 +341,7 @@ class Router {
|
|
|
320
341
|
});
|
|
321
342
|
if (this.appElement) this.appElement.innerHTML = pageContent.content;
|
|
322
343
|
this.setPageMeta(pageContent.title, pageContent.description, pageContent.canonicalUrl);
|
|
344
|
+
this.afterRender();
|
|
323
345
|
}
|
|
324
346
|
async renderContentListPage(pathname) {
|
|
325
347
|
const type = pathname === "/blogs" ? "blogs" : "stories";
|
|
@@ -338,6 +360,7 @@ class Router {
|
|
|
338
360
|
});
|
|
339
361
|
if (this.appElement) this.appElement.innerHTML = pageContent.content;
|
|
340
362
|
this.setPageMeta(pageContent.title, pageContent.description, pageContent.canonicalUrl);
|
|
363
|
+
this.afterRender();
|
|
341
364
|
}
|
|
342
365
|
async renderContentDetailPage(pathname) {
|
|
343
366
|
const isBlog = pathname.startsWith("/blogs/");
|
|
@@ -357,6 +380,7 @@ class Router {
|
|
|
357
380
|
});
|
|
358
381
|
if (this.appElement) this.appElement.innerHTML = pageContent.content;
|
|
359
382
|
this.setPageMeta(`${slug.replace(/-/g, " ")} - ${this.siteTitle}`, "Read more content", window.location.href);
|
|
383
|
+
this.afterRender();
|
|
360
384
|
}
|
|
361
385
|
async renderAdminPage() {
|
|
362
386
|
generatePageContent("/admin", this.routes, this.footerLinks, {
|
|
@@ -377,11 +401,13 @@ class Router {
|
|
|
377
401
|
<my-footer copyright="${this.copyright}" footerLinks='${JSON.stringify(this.footerLinks)}'></my-footer>
|
|
378
402
|
`;
|
|
379
403
|
}
|
|
404
|
+
this.afterRender();
|
|
380
405
|
}
|
|
381
406
|
}
|
|
382
407
|
class WebsiteUI {
|
|
383
408
|
constructor(config = {}) {
|
|
384
409
|
this.router = null;
|
|
410
|
+
this.interactInitialized = false;
|
|
385
411
|
this.store = SiteStore.getInstance();
|
|
386
412
|
this.config = config;
|
|
387
413
|
}
|
|
@@ -411,11 +437,44 @@ class WebsiteUI {
|
|
|
411
437
|
this.updateBanner(this.store.getConfig());
|
|
412
438
|
this.router = new Router(this);
|
|
413
439
|
this.router.init(this.config.appElementId || "app");
|
|
440
|
+
this.initInteract();
|
|
414
441
|
if (this.config.onBootstrap) {
|
|
415
442
|
await this.config.onBootstrap(this);
|
|
416
443
|
}
|
|
417
444
|
console.log("WebsiteUI bootstrapped");
|
|
418
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* Initialize md2interact for client-side DOM interactions,
|
|
448
|
+
* CSS hydration, and event bus communication.
|
|
449
|
+
*/
|
|
450
|
+
initInteract() {
|
|
451
|
+
if (this.interactInitialized) return;
|
|
452
|
+
const interactCfg = this.config.interactConfig || {};
|
|
453
|
+
init({
|
|
454
|
+
interactions: interactCfg.interactions || {
|
|
455
|
+
"poll": { selector: '[data-interact="poll"]' },
|
|
456
|
+
"live-update": { selector: '[data-interact="live-update"]' },
|
|
457
|
+
"click-toggle": { selector: '[data-interact="click-toggle"]' },
|
|
458
|
+
"infinite-scroll": { selector: '[data-interact="infinite-scroll"]' },
|
|
459
|
+
"form-live": { selector: '[data-interact="form-live"]' }
|
|
460
|
+
},
|
|
461
|
+
cssHydration: interactCfg.cssHydration || {
|
|
462
|
+
inlineCritical: true,
|
|
463
|
+
layerInjection: true,
|
|
464
|
+
themeToggle: true
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
this.interactInitialized = true;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Reinitialize md2interact after dynamic content changes (e.g., SPA navigation).
|
|
471
|
+
* This re-scans the DOM for new interaction elements.
|
|
472
|
+
*/
|
|
473
|
+
reinitInteract() {
|
|
474
|
+
if (this.interactInitialized) {
|
|
475
|
+
reinit();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
419
478
|
updateBanner(config) {
|
|
420
479
|
const banner = document.querySelector("my-banner");
|
|
421
480
|
if (banner) {
|
|
@@ -493,13 +552,12 @@ class ThemeToggle extends HTMLElement {
|
|
|
493
552
|
cursor: pointer;
|
|
494
553
|
font-size: 1.5rem;
|
|
495
554
|
padding: 0.5rem;
|
|
496
|
-
color: var(--text-color, #213547);
|
|
555
|
+
color: var(--text-color, #213547);
|
|
497
556
|
transition: color 0.3s ease;
|
|
498
557
|
}
|
|
499
558
|
button:hover {
|
|
500
|
-
color: var(--primary-color, #747bff);
|
|
559
|
+
color: var(--primary-color, #747bff);
|
|
501
560
|
}
|
|
502
|
-
/* Dark mode specific styles for the button */
|
|
503
561
|
html[data-theme='dark'] button {
|
|
504
562
|
color: var(--dark-mode-text-color, rgba(255, 255, 255, 0.87));
|
|
505
563
|
}
|
|
@@ -508,7 +566,7 @@ class ThemeToggle extends HTMLElement {
|
|
|
508
566
|
}
|
|
509
567
|
</style>
|
|
510
568
|
<button id="theme-toggle" aria-label="Toggle theme">
|
|
511
|
-
<span class="icon">${this.getSunIcon()}</span>
|
|
569
|
+
<span class="icon">${this.getSunIcon()}</span>
|
|
512
570
|
</button>
|
|
513
571
|
`;
|
|
514
572
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R2ContentLoader } from "@leadertechie/r2tohtml";
|
|
1
|
+
import { ContentCacheV2, R2ContentLoader } from "@leadertechie/r2tohtml";
|
|
2
2
|
function createJSONResponse(data, status = 200) {
|
|
3
3
|
return new Response(JSON.stringify(data), {
|
|
4
4
|
status,
|
|
@@ -9,6 +9,14 @@ function createErrorResponse(message, status = 500) {
|
|
|
9
9
|
return createJSONResponse({ error: message }, status);
|
|
10
10
|
}
|
|
11
11
|
let loader$1 = null;
|
|
12
|
+
new ContentCacheV2(
|
|
13
|
+
5 * 60 * 1e3,
|
|
14
|
+
// TTL: 5 minutes fresh
|
|
15
|
+
true,
|
|
16
|
+
// enabled
|
|
17
|
+
30 * 60 * 1e3
|
|
18
|
+
// SWR TTL: 30 minutes stale window
|
|
19
|
+
);
|
|
12
20
|
function getLoader$1(env) {
|
|
13
21
|
if (!env?.CONTENT_BUCKET) {
|
|
14
22
|
return null;
|
|
@@ -17,14 +25,24 @@ function getLoader$1(env) {
|
|
|
17
25
|
loader$1 = new R2ContentLoader(
|
|
18
26
|
{
|
|
19
27
|
bucket: env.CONTENT_BUCKET,
|
|
20
|
-
cacheTTL: 5 * 60 * 1e3
|
|
28
|
+
cacheTTL: 5 * 60 * 1e3,
|
|
29
|
+
cfCache: true,
|
|
30
|
+
// Enable Cloudflare edge cache tier
|
|
31
|
+
cfCacheTTL: 300,
|
|
32
|
+
// CF cache for 5 minutes
|
|
33
|
+
swrTTL: 30 * 60 * 1e3
|
|
34
|
+
// SWR window: 30 minutes
|
|
21
35
|
},
|
|
22
36
|
{
|
|
23
37
|
md2html: {
|
|
24
38
|
imagePathPrefix: "images/",
|
|
39
|
+
preserveRawHTML: true,
|
|
40
|
+
errorRecovery: "warn",
|
|
41
|
+
maxRecursionDepth: 50,
|
|
25
42
|
styleOptions: {
|
|
26
43
|
classPrefix: "md-",
|
|
27
|
-
addHeadingIds: true
|
|
44
|
+
addHeadingIds: true,
|
|
45
|
+
emitScopeAnchors: true
|
|
28
46
|
}
|
|
29
47
|
}
|
|
30
48
|
}
|
|
@@ -89,19 +107,37 @@ async function handleAboutMe(env) {
|
|
|
89
107
|
}
|
|
90
108
|
}
|
|
91
109
|
let loader = null;
|
|
110
|
+
new ContentCacheV2(
|
|
111
|
+
5 * 60 * 1e3,
|
|
112
|
+
// TTL: 5 minutes fresh
|
|
113
|
+
true,
|
|
114
|
+
// enabled
|
|
115
|
+
30 * 60 * 1e3
|
|
116
|
+
// SWR TTL: 30 minutes stale window
|
|
117
|
+
);
|
|
92
118
|
function getLoader(env) {
|
|
93
119
|
if (!loader && env?.CONTENT_BUCKET) {
|
|
94
120
|
loader = new R2ContentLoader(
|
|
95
121
|
{
|
|
96
122
|
bucket: env.CONTENT_BUCKET,
|
|
97
|
-
cacheTTL: 5 * 60 * 1e3
|
|
123
|
+
cacheTTL: 5 * 60 * 1e3,
|
|
124
|
+
cfCache: true,
|
|
125
|
+
// Enable Cloudflare edge cache tier
|
|
126
|
+
cfCacheTTL: 300,
|
|
127
|
+
// CF cache for 5 minutes
|
|
128
|
+
swrTTL: 30 * 60 * 1e3
|
|
129
|
+
// SWR window: 30 minutes
|
|
98
130
|
},
|
|
99
131
|
{
|
|
100
132
|
md2html: {
|
|
101
133
|
imagePathPrefix: "images/",
|
|
134
|
+
preserveRawHTML: true,
|
|
135
|
+
errorRecovery: "warn",
|
|
136
|
+
maxRecursionDepth: 50,
|
|
102
137
|
styleOptions: {
|
|
103
138
|
classPrefix: "md-",
|
|
104
|
-
addHeadingIds: true
|
|
139
|
+
addHeadingIds: true,
|
|
140
|
+
emitScopeAnchors: true
|
|
105
141
|
}
|
|
106
142
|
}
|
|
107
143
|
}
|
|
@@ -543,15 +579,29 @@ async function handleLogout(request, env) {
|
|
|
543
579
|
}
|
|
544
580
|
});
|
|
545
581
|
}
|
|
546
|
-
const contentCache =
|
|
547
|
-
|
|
582
|
+
const contentCache = new ContentCacheV2(
|
|
583
|
+
5 * 60 * 1e3,
|
|
584
|
+
// TTL: 5 minutes fresh
|
|
585
|
+
true,
|
|
586
|
+
// enabled
|
|
587
|
+
30 * 60 * 1e3
|
|
588
|
+
// SWR TTL: 30 minutes stale window
|
|
589
|
+
);
|
|
548
590
|
function getCachedOrFetch(key, fetchFn) {
|
|
549
591
|
const cached = contentCache.get(key);
|
|
550
|
-
if (cached
|
|
592
|
+
if (cached) {
|
|
593
|
+
if (!cached.stale) {
|
|
594
|
+
return Promise.resolve(cached.data);
|
|
595
|
+
}
|
|
596
|
+
fetchFn().then((data) => {
|
|
597
|
+
contentCache.set(key, data);
|
|
598
|
+
contentCache.refresh(key);
|
|
599
|
+
}).catch(() => {
|
|
600
|
+
});
|
|
551
601
|
return Promise.resolve(cached.data);
|
|
552
602
|
}
|
|
553
603
|
return fetchFn().then((data) => {
|
|
554
|
-
contentCache.set(key,
|
|
604
|
+
contentCache.set(key, data);
|
|
555
605
|
return data;
|
|
556
606
|
});
|
|
557
607
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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-Cy2kZ0dC.js";
|
|
2
2
|
import { WebsitePrerender } from "./prerender.js";
|
|
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-
|
|
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-DAog9TQE.js";
|
|
4
4
|
import { S as S2, g as g3, i as i2, r as r2 } from "./chunks/site-store-CGV9c2DI.js";
|
|
5
|
-
import { R as R2, T, W as W2, b as b3, c as c3, g as g4, r as r3 } from "./chunks/template-
|
|
5
|
+
import { R as R2, T, W as W2, b as b3, c as c3, g as g4, r as r3 } from "./chunks/template-DUdadCrH.js";
|
|
6
6
|
export {
|
|
7
7
|
A as AUTH_KV,
|
|
8
8
|
A2 as AdminAboutMeSection,
|
|
@@ -1 +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;
|
|
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;AAwCD,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;
|
|
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;AAgHD,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,EAChB,QAAQ,MAAM,EAAE,EAChB,aAAa,WAAW,EAAE,EAC1B,MAAM,GAAG,KACR,OAAO,CAAC,WAAW,CAqJrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/prerender/template.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAsDD,eAAO,MAAM,kBAAkB,GAAU,8FAStC,aAAa,KAAG,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/prerender/template.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAsDD,eAAO,MAAM,kBAAkB,GAAU,8FAStC,aAAa,KAAG,OAAO,CAAC,MAAM,CAuDhC,CAAC"}
|
package/dist/prerender.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R2ContentLoader } from "@leadertechie/r2tohtml";
|
|
1
|
+
import { ContentCacheV2, R2ContentLoader } from "@leadertechie/r2tohtml";
|
|
2
2
|
let cachedAssets = null;
|
|
3
3
|
let isDiscovering = false;
|
|
4
4
|
async function getAssetPaths(baseSiteUrl) {
|
|
@@ -73,6 +73,26 @@ const createHtmlTemplate = async ({
|
|
|
73
73
|
<link rel="canonical" href="${canonicalUrl}" />
|
|
74
74
|
<link rel="stylesheet" crossorigin href="${css}" />
|
|
75
75
|
<script type="module" crossorigin src="${js}"><\/script>
|
|
76
|
+
<!-- md2interact: client-side DOM interactions, CSS hydration, and event bus -->
|
|
77
|
+
<script type="module">
|
|
78
|
+
import { init } from '@leadertechie/md2interact';
|
|
79
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
80
|
+
init({
|
|
81
|
+
interactions: {
|
|
82
|
+
'poll': { selector: '[data-interact="poll"]' },
|
|
83
|
+
'live-update': { selector: '[data-interact="live-update"]' },
|
|
84
|
+
'click-toggle': { selector: '[data-interact="click-toggle"]' },
|
|
85
|
+
'infinite-scroll': { selector: '[data-interact="infinite-scroll"]' },
|
|
86
|
+
'form-live': { selector: '[data-interact="form-live"]' }
|
|
87
|
+
},
|
|
88
|
+
cssHydration: {
|
|
89
|
+
inlineCritical: true,
|
|
90
|
+
layerInjection: true,
|
|
91
|
+
themeToggle: true
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
<\/script>
|
|
76
96
|
</head>
|
|
77
97
|
<body>
|
|
78
98
|
${hydrationData}
|
|
@@ -83,12 +103,41 @@ const createHtmlTemplate = async ({
|
|
|
83
103
|
</html>`;
|
|
84
104
|
};
|
|
85
105
|
let loader = null;
|
|
106
|
+
new ContentCacheV2(
|
|
107
|
+
5 * 60 * 1e3,
|
|
108
|
+
// TTL: 5 minutes fresh
|
|
109
|
+
true,
|
|
110
|
+
// enabled
|
|
111
|
+
30 * 60 * 1e3
|
|
112
|
+
// SWR TTL: 30 minutes stale window
|
|
113
|
+
);
|
|
86
114
|
function getLoader(env) {
|
|
87
115
|
if (!loader) {
|
|
88
116
|
if (!env?.CONTENT_BUCKET) return null;
|
|
89
117
|
loader = new R2ContentLoader(
|
|
90
|
-
{
|
|
91
|
-
|
|
118
|
+
{
|
|
119
|
+
bucket: env.CONTENT_BUCKET,
|
|
120
|
+
cacheTTL: 5 * 60 * 1e3,
|
|
121
|
+
cfCache: true,
|
|
122
|
+
// Enable Cloudflare edge cache tier
|
|
123
|
+
cfCacheTTL: 300,
|
|
124
|
+
// CF cache for 5 minutes
|
|
125
|
+
swrTTL: 30 * 60 * 1e3
|
|
126
|
+
// SWR window: 30 minutes
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
md2html: {
|
|
130
|
+
imagePathPrefix: "images/",
|
|
131
|
+
preserveRawHTML: true,
|
|
132
|
+
errorRecovery: "warn",
|
|
133
|
+
maxRecursionDepth: 50,
|
|
134
|
+
styleOptions: {
|
|
135
|
+
classPrefix: "md-",
|
|
136
|
+
addHeadingIds: true,
|
|
137
|
+
emitScopeAnchors: true
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
92
141
|
);
|
|
93
142
|
}
|
|
94
143
|
return loader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-toggle.d.ts","sourceRoot":"","sources":["../../../src/shared/core/theme-toggle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme-toggle.d.ts","sourceRoot":"","sources":["../../../src/shared/core/theme-toggle.ts"],"names":[],"mappings":"AAEA,qBAAa,WAAY,SAAQ,WAAW;;IAQ1C,iBAAiB;IAIjB,oBAAoB;IAIpB,MAAM;IAiCN,0BAA0B;IAc1B,WAAW,aAOT;IAEF,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAUhC,UAAU,IAAI,MAAM;IAgBpB,WAAW,IAAI,MAAM;IAQrB,wBAAwB,CAAC,KAAK,EAAE,MAAM;CAQvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-content.d.ts","sourceRoot":"","sources":["../../src/shared/page-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AAGpC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"page-content.d.ts","sourceRoot":"","sources":["../../src/shared/page-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AAGpC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwBD,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAGhD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,EAChB,QAAQ,MAAM,EAAE,EAChB,aAAa,WAAW,EAAE,EAC1B,OAAO;IACL,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,KACA,WA0JF,CAAC"}
|
package/dist/shared/router.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export declare class Router {
|
|
|
14
14
|
private setupEventListeners;
|
|
15
15
|
navigate(path: string): Promise<void>;
|
|
16
16
|
private setPageMeta;
|
|
17
|
+
/**
|
|
18
|
+
* After rendering new content, reinitialize md2interact so it
|
|
19
|
+
* re-scans the DOM for interaction elements (poll, live-update, etc.)
|
|
20
|
+
*/
|
|
21
|
+
private afterRender;
|
|
17
22
|
private renderHomePage;
|
|
18
23
|
private renderAboutMePage;
|
|
19
24
|
private renderContentListPage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/shared/router.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,qBAAa,MAAM;IAML,OAAO,CAAC,EAAE;IALtB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,UAAU,CAA4B;gBAE1B,EAAE,EAAE,SAAS;IAejC,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,WAAW,GAatB;IAEM,IAAI,CAAC,YAAY,GAAE,MAAc;IAWxC,OAAO,CAAC,mBAAmB;IAmCd,QAAQ,CAAC,IAAI,EAAE,MAAM;IA6BlC,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/shared/router.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,qBAAa,MAAM;IAML,OAAO,CAAC,EAAE;IALtB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,UAAU,CAA4B;gBAE1B,EAAE,EAAE,SAAS;IAejC,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,KAAK,WAAW,GAatB;IAEM,IAAI,CAAC,YAAY,GAAE,MAAc;IAWxC,OAAO,CAAC,mBAAmB;IAmCd,QAAQ,CAAC,IAAI,EAAE,MAAM;IA6BlC,OAAO,CAAC,WAAW;IAgCnB;;;OAGG;IACH,OAAO,CAAC,WAAW;YAIL,cAAc;IAmC5B,OAAO,CAAC,iBAAiB;YASX,qBAAqB;YAkBrB,uBAAuB;YAoBvB,eAAe;CAsB9B"}
|
|
@@ -13,15 +13,36 @@ export interface UIConfig {
|
|
|
13
13
|
customCss?: string;
|
|
14
14
|
};
|
|
15
15
|
onBootstrap?: (ui: WebsiteUI) => void | Promise<void>;
|
|
16
|
+
interactConfig?: {
|
|
17
|
+
interactions?: Record<string, {
|
|
18
|
+
selector: string;
|
|
19
|
+
}>;
|
|
20
|
+
cssHydration?: {
|
|
21
|
+
inlineCritical?: boolean;
|
|
22
|
+
layerInjection?: boolean;
|
|
23
|
+
themeToggle?: boolean;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
16
26
|
}
|
|
17
27
|
export declare class WebsiteUI {
|
|
18
28
|
private static instance;
|
|
19
29
|
private store;
|
|
20
30
|
private config;
|
|
21
31
|
private router;
|
|
32
|
+
private interactInitialized;
|
|
22
33
|
private constructor();
|
|
23
34
|
static getInstance(config?: UIConfig): WebsiteUI;
|
|
24
35
|
bootstrap(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Initialize md2interact for client-side DOM interactions,
|
|
38
|
+
* CSS hydration, and event bus communication.
|
|
39
|
+
*/
|
|
40
|
+
private initInteract;
|
|
41
|
+
/**
|
|
42
|
+
* Reinitialize md2interact after dynamic content changes (e.g., SPA navigation).
|
|
43
|
+
* This re-scans the DOM for new interaction elements.
|
|
44
|
+
*/
|
|
45
|
+
reinitInteract(): void;
|
|
25
46
|
private updateBanner;
|
|
26
47
|
private applyTheme;
|
|
27
48
|
private updateFavicon;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"website-ui.d.ts","sourceRoot":"","sources":["../../src/shared/website-ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"website-ui.d.ts","sourceRoot":"","sources":["../../src/shared/website-ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,cAAc,CAAC,EAAE;QACf,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACpD,YAAY,CAAC,EAAE;YACb,cAAc,CAAC,EAAE,OAAO,CAAC;YACzB,cAAc,CAAC,EAAE,OAAO,CAAC;YACzB,WAAW,CAAC,EAAE,OAAO,CAAC;SACvB,CAAC;KACH,CAAC;CACH;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAY;IACnC,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IAEpC,OAAO;WAKO,WAAW,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS;IAU1C,SAAS;IAyCtB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAuBpB;;;OAGG;IACI,cAAc;IAMrB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,aAAa;IAad,QAAQ;IAIR,SAAS;IAIT,SAAS;CAGjB;AAED,eAAO,MAAM,SAAS,GAAI,SAAS,QAAQ,kBAA8C,CAAC"}
|
package/dist/shared.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { S, g, i, r } from "./chunks/site-store-CGV9c2DI.js";
|
|
2
|
-
import { R, T, W, b, c, g as g2, r as r2 } from "./chunks/template-
|
|
2
|
+
import { R, T, W, b, c, g as g2, r as r2 } from "./chunks/template-DUdadCrH.js";
|
|
3
3
|
export {
|
|
4
4
|
R as Router,
|
|
5
5
|
S as SiteStore,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/blog-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/blog-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AA0B5C,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,UAAW,SAAQ,UAAU;IACxC,MAAM,CAAC,MAAM,0BAAoB;IAGjC,QAAQ,CAAC,IAAI,SAAM;IAGnB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAG1C,QAAQ,CAAC,OAAO,UAAQ;IAGxB,QAAQ,CAAC,KAAK,SAAM;IAEpB,OAAO,KAAK,UAAU,GAMrB;IAED,iBAAiB;IAOjB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAM/C,QAAQ;IA4BR,MAAM;IA+BN,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAKxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/story-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/story-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AA0B5C,UAAU,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,WAAY,SAAQ,UAAU;IACzC,MAAM,CAAC,MAAM,0BAAqB;IAGlC,QAAQ,CAAC,IAAI,SAAM;IAGnB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAG5C,QAAQ,CAAC,OAAO,UAAQ;IAGxB,QAAQ,CAAC,KAAK,SAAM;IAEpB,OAAO,KAAK,UAAU,GAKrB;IAEK,iBAAiB;IAOvB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;IAMrC,SAAS;IAuBf,MAAM;IA+BN,OAAO,CAAC,cAAc;CAKvB"}
|
package/dist/ui.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leadertechie/personal-site-kit",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A high-performance personal website engine for Cloudflare Workers and R2",
|
|
6
6
|
"repository": {
|
|
@@ -43,8 +43,9 @@
|
|
|
43
43
|
"test": "vitest run"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@leadertechie/md2html": "^0.1.0-alpha.
|
|
47
|
-
"@leadertechie/
|
|
46
|
+
"@leadertechie/md2html": "^0.1.0-alpha.15",
|
|
47
|
+
"@leadertechie/md2interact": "^0.1.0-alpha.1",
|
|
48
|
+
"@leadertechie/r2tohtml": "^0.1.0-alpha.14",
|
|
48
49
|
"lit": "^3.2.1"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|