@jant/core 0.3.22 → 0.3.23
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/app.js +22 -3
- package/dist/index.js +3 -4
- package/dist/lib/render.js +1 -1
- package/dist/lib/view.js +1 -1
- package/dist/routes/api/timeline.js +3 -3
- package/dist/routes/pages/archive.js +1 -1
- package/dist/routes/pages/collection.js +1 -1
- package/dist/routes/pages/home.js +1 -1
- package/dist/routes/pages/page.js +1 -1
- package/dist/routes/pages/post.js +1 -1
- package/dist/routes/pages/search.js +1 -1
- package/dist/theme/components/index.js +0 -2
- package/dist/theme/index.js +10 -16
- package/dist/theme/layouts/index.js +0 -1
- package/dist/themes/minimal/MinimalSiteLayout.js +83 -0
- package/dist/themes/minimal/index.js +65 -0
- package/dist/{theme → themes/minimal}/pages/ArchivePage.js +7 -8
- package/dist/{theme → themes/minimal}/pages/CollectionPage.js +7 -5
- package/dist/{theme → themes/minimal}/pages/HomePage.js +2 -3
- package/dist/{theme → themes/minimal}/pages/PostPage.js +5 -6
- package/dist/{theme → themes/minimal}/pages/SearchPage.js +11 -10
- package/dist/{theme → themes/minimal}/pages/SinglePage.js +3 -4
- package/dist/themes/minimal/timeline/ArticleCard.js +36 -0
- package/dist/themes/minimal/timeline/ImageCard.js +67 -0
- package/dist/{theme/components → themes/minimal}/timeline/LinkCard.js +14 -26
- package/dist/{theme/components → themes/minimal}/timeline/NoteCard.js +7 -7
- package/dist/{theme/components → themes/minimal}/timeline/QuoteCard.js +6 -6
- package/dist/{theme/components → themes/minimal}/timeline/ThreadPreview.js +13 -18
- package/dist/themes/minimal/timeline/TimelineFeed.js +48 -0
- package/dist/{theme/components → themes/minimal}/timeline/TimelineItem.js +1 -2
- package/package.json +1 -1
- package/src/app.tsx +26 -3
- package/src/i18n/locales/en.po +47 -47
- package/src/i18n/locales/zh-Hans.po +47 -47
- package/src/i18n/locales/zh-Hant.po +47 -47
- package/src/index.ts +4 -5
- package/src/lib/__tests__/view.test.ts +18 -16
- package/src/lib/render.tsx +1 -1
- package/src/lib/view.ts +1 -1
- package/src/routes/api/timeline.tsx +3 -3
- package/src/routes/pages/archive.tsx +1 -1
- package/src/routes/pages/collection.tsx +1 -1
- package/src/routes/pages/home.tsx +1 -1
- package/src/routes/pages/page.tsx +1 -1
- package/src/routes/pages/post.tsx +1 -1
- package/src/routes/pages/search.tsx +1 -1
- package/src/styles/components.css +0 -54
- package/src/theme/components/index.ts +0 -13
- package/src/theme/index.ts +10 -16
- package/src/theme/layouts/index.ts +0 -1
- package/src/themes/minimal/MinimalSiteLayout.tsx +100 -0
- package/src/themes/minimal/index.ts +83 -0
- package/src/{theme → themes/minimal}/pages/ArchivePage.tsx +8 -11
- package/src/{theme → themes/minimal}/pages/CollectionPage.tsx +6 -6
- package/src/{theme → themes/minimal}/pages/HomePage.tsx +3 -4
- package/src/{theme → themes/minimal}/pages/PostPage.tsx +6 -7
- package/src/{theme → themes/minimal}/pages/SearchPage.tsx +11 -17
- package/src/{theme → themes/minimal}/pages/SinglePage.tsx +4 -5
- package/src/themes/minimal/timeline/ArticleCard.tsx +37 -0
- package/src/themes/minimal/timeline/ImageCard.tsx +63 -0
- package/src/themes/minimal/timeline/LinkCard.tsx +48 -0
- package/src/{theme/components → themes/minimal}/timeline/NoteCard.tsx +10 -9
- package/src/{theme/components → themes/minimal}/timeline/QuoteCard.tsx +9 -8
- package/src/{theme/components → themes/minimal}/timeline/ThreadPreview.tsx +14 -16
- package/src/{theme/components → themes/minimal}/timeline/TimelineFeed.tsx +14 -13
- package/src/{theme/components → themes/minimal}/timeline/TimelineItem.tsx +1 -4
- package/dist/theme/components/timeline/ArticleCard.js +0 -46
- package/dist/theme/components/timeline/ImageCard.js +0 -83
- package/dist/theme/components/timeline/TimelineFeed.js +0 -46
- package/dist/theme/components/timeline/index.js +0 -8
- package/dist/theme/layouts/SiteLayout.js +0 -131
- package/dist/theme/pages/index.js +0 -11
- package/src/theme/components/timeline/ArticleCard.tsx +0 -45
- package/src/theme/components/timeline/ImageCard.tsx +0 -70
- package/src/theme/components/timeline/LinkCard.tsx +0 -59
- package/src/theme/components/timeline/index.ts +0 -8
- package/src/theme/layouts/SiteLayout.tsx +0 -132
- package/src/theme/pages/index.ts +0 -13
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Theme - Image Card
|
|
3
|
+
*
|
|
4
|
+
* Inline images with no card frame for type="image" posts.
|
|
5
|
+
*/ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
6
|
+
import { MediaGallery } from "../../../theme/components/MediaGallery.js";
|
|
7
|
+
export const ImageCard = ({ post, compact })=>{
|
|
8
|
+
if (compact) {
|
|
9
|
+
return /*#__PURE__*/ _jsxs("article", {
|
|
10
|
+
class: "h-entry text-sm",
|
|
11
|
+
children: [
|
|
12
|
+
post.title && /*#__PURE__*/ _jsx("h2", {
|
|
13
|
+
class: "p-name font-medium text-sm",
|
|
14
|
+
children: /*#__PURE__*/ _jsx("a", {
|
|
15
|
+
href: post.permalink,
|
|
16
|
+
class: "u-url hover:underline",
|
|
17
|
+
children: post.title
|
|
18
|
+
})
|
|
19
|
+
}),
|
|
20
|
+
post.contentHtml && /*#__PURE__*/ _jsx("div", {
|
|
21
|
+
class: "e-content prose prose-sm text-muted-foreground",
|
|
22
|
+
dangerouslySetInnerHTML: {
|
|
23
|
+
__html: post.contentHtml
|
|
24
|
+
}
|
|
25
|
+
}),
|
|
26
|
+
/*#__PURE__*/ _jsx("footer", {
|
|
27
|
+
class: "mt-1",
|
|
28
|
+
children: /*#__PURE__*/ _jsx("a", {
|
|
29
|
+
href: post.permalink,
|
|
30
|
+
class: "u-url text-xs text-muted-foreground hover:text-foreground",
|
|
31
|
+
children: /*#__PURE__*/ _jsx("time", {
|
|
32
|
+
class: "dt-published",
|
|
33
|
+
datetime: post.publishedAt,
|
|
34
|
+
children: post.publishedAtFormatted
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return /*#__PURE__*/ _jsxs("article", {
|
|
42
|
+
class: "h-entry",
|
|
43
|
+
children: [
|
|
44
|
+
post.contentHtml && /*#__PURE__*/ _jsx("div", {
|
|
45
|
+
class: "e-content prose prose-sm",
|
|
46
|
+
dangerouslySetInnerHTML: {
|
|
47
|
+
__html: post.contentHtml
|
|
48
|
+
}
|
|
49
|
+
}),
|
|
50
|
+
post.media.length > 0 && /*#__PURE__*/ _jsx(MediaGallery, {
|
|
51
|
+
attachments: post.media
|
|
52
|
+
}),
|
|
53
|
+
/*#__PURE__*/ _jsx("footer", {
|
|
54
|
+
class: "mt-2",
|
|
55
|
+
children: /*#__PURE__*/ _jsx("a", {
|
|
56
|
+
href: post.permalink,
|
|
57
|
+
class: "u-url text-xs text-muted-foreground hover:text-foreground",
|
|
58
|
+
children: /*#__PURE__*/ _jsx("time", {
|
|
59
|
+
class: "dt-published",
|
|
60
|
+
datetime: post.publishedAt,
|
|
61
|
+
children: post.publishedAtFormatted
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
]
|
|
66
|
+
});
|
|
67
|
+
};
|
|
@@ -1,33 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Link Card
|
|
2
|
+
* Minimal Theme - Link Card
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Subtle external link indicator for type="link" posts.
|
|
5
5
|
*/ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
6
6
|
export const LinkCard = ({ post, compact })=>{
|
|
7
7
|
return /*#__PURE__*/ _jsxs("article", {
|
|
8
|
-
class: `h-entry
|
|
8
|
+
class: `h-entry${compact ? " text-sm" : ""}`,
|
|
9
9
|
children: [
|
|
10
|
-
post.sourceDomain && /*#__PURE__*/ _jsxs("div", {
|
|
11
|
-
class: "text-xs text-muted-foreground mb-1 flex items-center gap-1",
|
|
12
|
-
children: [
|
|
13
|
-
/*#__PURE__*/ _jsx("svg", {
|
|
14
|
-
class: "size-3",
|
|
15
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
16
|
-
fill: "none",
|
|
17
|
-
viewBox: "0 0 24 24",
|
|
18
|
-
"stroke-width": "2",
|
|
19
|
-
stroke: "currentColor",
|
|
20
|
-
children: /*#__PURE__*/ _jsx("path", {
|
|
21
|
-
d: "M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
|
|
22
|
-
})
|
|
23
|
-
}),
|
|
24
|
-
/*#__PURE__*/ _jsx("span", {
|
|
25
|
-
children: post.sourceDomain
|
|
26
|
-
})
|
|
27
|
-
]
|
|
28
|
-
}),
|
|
29
10
|
post.title && /*#__PURE__*/ _jsx("h2", {
|
|
30
|
-
class: `p-name font-semibold ${compact ? "text-sm" : "text-base"}
|
|
11
|
+
class: `p-name font-semibold ${compact ? "text-sm" : "text-base"}`,
|
|
31
12
|
children: /*#__PURE__*/ _jsx("a", {
|
|
32
13
|
href: post.sourceUrl || post.permalink,
|
|
33
14
|
class: "u-url hover:underline",
|
|
@@ -36,17 +17,24 @@ export const LinkCard = ({ post, compact })=>{
|
|
|
36
17
|
children: post.title
|
|
37
18
|
})
|
|
38
19
|
}),
|
|
20
|
+
post.sourceDomain && /*#__PURE__*/ _jsxs("div", {
|
|
21
|
+
class: "text-xs text-muted-foreground mt-0.5",
|
|
22
|
+
children: [
|
|
23
|
+
"↗ ",
|
|
24
|
+
post.sourceDomain
|
|
25
|
+
]
|
|
26
|
+
}),
|
|
39
27
|
!compact && post.contentHtml && /*#__PURE__*/ _jsx("div", {
|
|
40
|
-
class: "e-content prose prose-sm text-muted-foreground",
|
|
28
|
+
class: "e-content prose prose-sm text-muted-foreground mt-1",
|
|
41
29
|
dangerouslySetInnerHTML: {
|
|
42
30
|
__html: post.contentHtml
|
|
43
31
|
}
|
|
44
32
|
}),
|
|
45
33
|
/*#__PURE__*/ _jsx("footer", {
|
|
46
|
-
class: "mt-2
|
|
34
|
+
class: "mt-2",
|
|
47
35
|
children: /*#__PURE__*/ _jsx("a", {
|
|
48
36
|
href: post.permalink,
|
|
49
|
-
class: "hover:
|
|
37
|
+
class: "text-xs text-muted-foreground hover:text-foreground",
|
|
50
38
|
children: /*#__PURE__*/ _jsx("time", {
|
|
51
39
|
class: "dt-published",
|
|
52
40
|
datetime: post.publishedAt,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Note Card
|
|
2
|
+
* Minimal Theme - Note Card
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Borderless, content-first card for type="note" posts.
|
|
5
5
|
*/ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
6
|
-
import { MediaGallery } from "
|
|
6
|
+
import { MediaGallery } from "../../../theme/components/MediaGallery.js";
|
|
7
7
|
export const NoteCard = ({ post, compact })=>{
|
|
8
8
|
return /*#__PURE__*/ _jsxs("article", {
|
|
9
|
-
class: `h-entry
|
|
9
|
+
class: `h-entry${compact ? " text-sm" : ""}`,
|
|
10
10
|
children: [
|
|
11
11
|
post.contentHtml && /*#__PURE__*/ _jsx("div", {
|
|
12
|
-
class: `e-content prose ${compact ? "prose-sm" : "
|
|
12
|
+
class: `e-content prose ${compact ? "prose-sm" : ""}`,
|
|
13
13
|
dangerouslySetInnerHTML: {
|
|
14
14
|
__html: post.contentHtml
|
|
15
15
|
}
|
|
@@ -18,10 +18,10 @@ export const NoteCard = ({ post, compact })=>{
|
|
|
18
18
|
attachments: post.media
|
|
19
19
|
}),
|
|
20
20
|
/*#__PURE__*/ _jsx("footer", {
|
|
21
|
-
class: "mt-2
|
|
21
|
+
class: "mt-2",
|
|
22
22
|
children: /*#__PURE__*/ _jsx("a", {
|
|
23
23
|
href: post.permalink,
|
|
24
|
-
class: "u-url hover:
|
|
24
|
+
class: "u-url text-xs text-muted-foreground hover:text-foreground",
|
|
25
25
|
children: /*#__PURE__*/ _jsx("time", {
|
|
26
26
|
class: "dt-published",
|
|
27
27
|
datetime: post.publishedAt,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Quote Card
|
|
2
|
+
* Minimal Theme - Quote Card
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Subtle blockquote with left border for type="quote" posts.
|
|
5
5
|
*/ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
6
6
|
export const QuoteCard = ({ post, compact })=>{
|
|
7
7
|
return /*#__PURE__*/ _jsxs("article", {
|
|
8
|
-
class: `h-entry
|
|
8
|
+
class: `h-entry${compact ? " text-sm" : ""}`,
|
|
9
9
|
children: [
|
|
10
10
|
post.contentHtml && /*#__PURE__*/ _jsx("blockquote", {
|
|
11
|
-
class: `e-content italic ${compact ? "text-sm" : "
|
|
11
|
+
class: `e-content border-l-2 border-muted-foreground/30 pl-4 italic ${compact ? "text-sm" : ""} leading-relaxed`,
|
|
12
12
|
children: /*#__PURE__*/ _jsx("div", {
|
|
13
13
|
dangerouslySetInnerHTML: {
|
|
14
14
|
__html: post.contentHtml
|
|
@@ -32,10 +32,10 @@ export const QuoteCard = ({ post, compact })=>{
|
|
|
32
32
|
]
|
|
33
33
|
}),
|
|
34
34
|
/*#__PURE__*/ _jsx("footer", {
|
|
35
|
-
class: "mt-2
|
|
35
|
+
class: "mt-2",
|
|
36
36
|
children: /*#__PURE__*/ _jsx("a", {
|
|
37
37
|
href: post.permalink,
|
|
38
|
-
class: "u-url hover:
|
|
38
|
+
class: "u-url text-xs text-muted-foreground hover:text-foreground",
|
|
39
39
|
children: /*#__PURE__*/ _jsx("time", {
|
|
40
40
|
class: "dt-published",
|
|
41
41
|
datetime: post.publishedAt,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Thread Preview
|
|
2
|
+
* Minimal Theme - Thread Preview
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Minimal thread indicator: root post + compact replies + "show more" link.
|
|
5
5
|
*/ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
6
6
|
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
7
7
|
import { TimelineItem } from "./TimelineItem.js";
|
|
@@ -10,7 +10,6 @@ export const ThreadPreview = ({ rootPost, previewReplies, totalReplyCount, theme
|
|
|
10
10
|
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
11
11
|
const remainingCount = totalReplyCount - previewReplies.length;
|
|
12
12
|
return /*#__PURE__*/ _jsxs("div", {
|
|
13
|
-
class: "timeline-thread",
|
|
14
13
|
children: [
|
|
15
14
|
/*#__PURE__*/ _jsx(TimelineItem, {
|
|
16
15
|
item: {
|
|
@@ -19,29 +18,25 @@ export const ThreadPreview = ({ rootPost, previewReplies, totalReplyCount, theme
|
|
|
19
18
|
theme: theme
|
|
20
19
|
}),
|
|
21
20
|
previewReplies.length > 0 && /*#__PURE__*/ _jsxs("div", {
|
|
22
|
-
class: "
|
|
21
|
+
class: "ml-4 mt-2 border-l border-border pl-4 flex flex-col gap-3",
|
|
23
22
|
children: [
|
|
24
23
|
previewReplies.map((reply)=>/*#__PURE__*/ _jsx("div", {
|
|
25
|
-
class: "timeline-thread-reply",
|
|
26
24
|
children: /*#__PURE__*/ _jsx(TimelineItemFromPost, {
|
|
27
25
|
post: reply,
|
|
28
26
|
compact: true,
|
|
29
27
|
theme: theme
|
|
30
28
|
})
|
|
31
29
|
}, reply.id)),
|
|
32
|
-
remainingCount > 0 && /*#__PURE__*/ _jsx("
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
0: remainingCount === 1 ? "reply" : "replies"
|
|
43
|
-
}
|
|
44
|
-
})
|
|
30
|
+
remainingCount > 0 && /*#__PURE__*/ _jsx("a", {
|
|
31
|
+
href: rootPost.permalink,
|
|
32
|
+
class: "text-sm text-muted-foreground hover:text-foreground hover:underline",
|
|
33
|
+
children: $__i18n._({
|
|
34
|
+
id: "smzF8S",
|
|
35
|
+
message: "Show {remainingCount} more {0}",
|
|
36
|
+
values: {
|
|
37
|
+
remainingCount: remainingCount,
|
|
38
|
+
0: remainingCount === 1 ? "reply" : "replies"
|
|
39
|
+
}
|
|
45
40
|
})
|
|
46
41
|
})
|
|
47
42
|
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Theme - Timeline Feed
|
|
3
|
+
*
|
|
4
|
+
* Divider-separated stream of posts with load-more button.
|
|
5
|
+
*/ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
6
|
+
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
7
|
+
import { TimelineItem } from "./TimelineItem.js";
|
|
8
|
+
import { ThreadPreview as DefaultThreadPreview } from "./ThreadPreview.js";
|
|
9
|
+
export const TimelineFeed = ({ items, hasMore, nextCursor, theme })=>{
|
|
10
|
+
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
11
|
+
const ResolvedThreadPreview = theme?.ThreadPreview ?? DefaultThreadPreview;
|
|
12
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
13
|
+
children: [
|
|
14
|
+
/*#__PURE__*/ _jsx("div", {
|
|
15
|
+
id: "timeline-feed",
|
|
16
|
+
class: "flex flex-col",
|
|
17
|
+
children: items.map((item, i)=>/*#__PURE__*/ _jsxs("div", {
|
|
18
|
+
children: [
|
|
19
|
+
i > 0 && /*#__PURE__*/ _jsx("hr", {
|
|
20
|
+
class: "my-6 border-border"
|
|
21
|
+
}),
|
|
22
|
+
item.threadPreview ? /*#__PURE__*/ _jsx(ResolvedThreadPreview, {
|
|
23
|
+
rootPost: item.post,
|
|
24
|
+
previewReplies: item.threadPreview.replies,
|
|
25
|
+
totalReplyCount: item.threadPreview.totalReplyCount,
|
|
26
|
+
theme: theme
|
|
27
|
+
}) : /*#__PURE__*/ _jsx(TimelineItem, {
|
|
28
|
+
item: item,
|
|
29
|
+
theme: theme
|
|
30
|
+
})
|
|
31
|
+
]
|
|
32
|
+
}, item.post.id))
|
|
33
|
+
}),
|
|
34
|
+
hasMore && nextCursor && /*#__PURE__*/ _jsx("div", {
|
|
35
|
+
id: "load-more-container",
|
|
36
|
+
class: "mt-8 text-center",
|
|
37
|
+
children: /*#__PURE__*/ _jsx("button", {
|
|
38
|
+
class: "text-sm text-muted-foreground hover:text-foreground hover:underline",
|
|
39
|
+
"data-on:click": `@get('/api/timeline?cursor=${nextCursor}')`,
|
|
40
|
+
children: $__i18n._({
|
|
41
|
+
id: "yQ2kGp",
|
|
42
|
+
message: "Load more"
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Timeline Item
|
|
2
|
+
* Minimal Theme - Timeline Item
|
|
3
3
|
*
|
|
4
4
|
* Dispatches to the correct card component based on post type.
|
|
5
|
-
* Resolves card overrides from theme components if provided.
|
|
6
5
|
*/ import { jsx as _jsx } from "hono/jsx/jsx-runtime";
|
|
7
6
|
import { NoteCard } from "./NoteCard.js";
|
|
8
7
|
import { ArticleCard } from "./ArticleCard.js";
|
package/package.json
CHANGED
package/src/app.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import { i18nMiddleware } from "./i18n/index.js";
|
|
|
11
11
|
import { useLingui } from "@lingui/react/macro";
|
|
12
12
|
import type { Bindings, JantConfig } from "./types.js";
|
|
13
13
|
import { SETTINGS_KEYS } from "./lib/constants.js";
|
|
14
|
+
import { theme as minimalTheme } from "./themes/minimal/index.js";
|
|
14
15
|
import { hashPassword } from "better-auth/crypto";
|
|
15
16
|
|
|
16
17
|
// Routes - Pages
|
|
@@ -82,6 +83,25 @@ export type App = Hono<{ Bindings: Bindings; Variables: AppVariables }>;
|
|
|
82
83
|
* ```
|
|
83
84
|
*/
|
|
84
85
|
export function createApp(config: JantConfig = {}): App {
|
|
86
|
+
// Merge with default minimal theme
|
|
87
|
+
const defaultTheme = minimalTheme();
|
|
88
|
+
const resolvedConfig: JantConfig = {
|
|
89
|
+
...config,
|
|
90
|
+
theme: {
|
|
91
|
+
name: config.theme?.name ?? defaultTheme.name,
|
|
92
|
+
components: {
|
|
93
|
+
...defaultTheme.components,
|
|
94
|
+
...config.theme?.components,
|
|
95
|
+
},
|
|
96
|
+
cssVariables: {
|
|
97
|
+
...defaultTheme.cssVariables,
|
|
98
|
+
...config.theme?.cssVariables,
|
|
99
|
+
},
|
|
100
|
+
colorThemes: config.theme?.colorThemes ?? defaultTheme.colorThemes,
|
|
101
|
+
feed: config.theme?.feed,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
85
105
|
const app = new Hono<{ Bindings: Bindings; Variables: AppVariables }>();
|
|
86
106
|
|
|
87
107
|
// Initialize services, auth, and config middleware
|
|
@@ -96,7 +116,7 @@ export function createApp(config: JantConfig = {}): App {
|
|
|
96
116
|
const db = createDatabase(session as unknown as D1Database);
|
|
97
117
|
const services = createServices(db, session as unknown as D1Database);
|
|
98
118
|
c.set("services", services);
|
|
99
|
-
c.set("config",
|
|
119
|
+
c.set("config", resolvedConfig);
|
|
100
120
|
c.set("storage", createStorageDriver(c.env));
|
|
101
121
|
|
|
102
122
|
if (c.env.AUTH_SECRET) {
|
|
@@ -117,11 +137,14 @@ export function createApp(config: JantConfig = {}): App {
|
|
|
117
137
|
// Theme middleware - resolve active color theme and build CSS
|
|
118
138
|
app.use("*", async (c, next) => {
|
|
119
139
|
const themeId = await c.var.services.settings.get(SETTINGS_KEYS.THEME);
|
|
120
|
-
const themes = getAvailableThemes(
|
|
140
|
+
const themes = getAvailableThemes(resolvedConfig);
|
|
121
141
|
const activeTheme = themeId
|
|
122
142
|
? themes.find((t) => t.id === themeId)
|
|
123
143
|
: undefined;
|
|
124
|
-
const themeStyle = buildThemeStyle(
|
|
144
|
+
const themeStyle = buildThemeStyle(
|
|
145
|
+
activeTheme,
|
|
146
|
+
resolvedConfig.theme?.cssVariables,
|
|
147
|
+
);
|
|
125
148
|
c.set("themeStyle", themeStyle);
|
|
126
149
|
await next();
|
|
127
150
|
});
|