@jant/core 0.3.23 → 0.3.25
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 +50 -26
- package/dist/db/schema.js +72 -47
- package/dist/i18n/locales/en.js +1 -1
- package/dist/i18n/locales/zh-Hans.js +1 -1
- package/dist/i18n/locales/zh-Hant.js +1 -1
- package/dist/index.js +5 -11
- package/dist/lib/constants.js +2 -4
- package/dist/lib/excerpt.js +76 -0
- package/dist/lib/feed.js +18 -7
- package/dist/lib/nav-reorder.js +1 -1
- package/dist/lib/navigation.js +30 -6
- package/dist/lib/pagination.js +44 -0
- package/dist/lib/render.js +7 -11
- package/dist/lib/schemas.js +80 -38
- package/dist/lib/theme.js +4 -4
- package/dist/lib/time.js +56 -1
- package/dist/lib/timeline.js +95 -0
- package/dist/lib/view.js +61 -72
- package/dist/routes/api/collections.js +124 -0
- package/dist/routes/api/nav-items.js +104 -0
- package/dist/routes/api/pages.js +91 -0
- package/dist/routes/api/posts.js +27 -33
- package/dist/routes/api/search.js +4 -5
- package/dist/routes/api/settings.js +68 -0
- package/dist/routes/api/upload.js +13 -13
- package/dist/routes/compose.js +48 -0
- package/dist/routes/dash/collections.js +24 -42
- package/dist/routes/dash/index.js +3 -3
- package/dist/routes/dash/media.js +2 -2
- package/dist/routes/dash/pages.js +440 -106
- package/dist/routes/dash/posts.js +27 -37
- package/dist/routes/dash/redirects.js +2 -2
- package/dist/routes/dash/settings.js +79 -5
- package/dist/routes/feed/rss.js +4 -6
- package/dist/routes/feed/sitemap.js +11 -8
- package/dist/routes/pages/archive.js +13 -15
- package/dist/routes/pages/collection.js +12 -9
- package/dist/routes/pages/collections.js +28 -0
- package/dist/routes/pages/featured.js +32 -0
- package/dist/routes/pages/home.js +19 -68
- package/dist/routes/pages/page.js +57 -29
- package/dist/routes/pages/post.js +7 -17
- package/dist/routes/pages/search.js +5 -9
- package/dist/services/collection.js +52 -64
- package/dist/services/index.js +5 -3
- package/dist/services/navigation.js +29 -53
- package/dist/services/page.js +84 -0
- package/dist/services/post.js +102 -69
- package/dist/services/search.js +24 -18
- package/dist/types.js +24 -40
- package/dist/ui/compose/ComposeDialog.js +452 -0
- package/dist/ui/compose/ComposePrompt.js +55 -0
- package/dist/{theme/components/TypeBadge.js → ui/dash/FormatBadge.js} +3 -15
- package/dist/{theme/components → ui/dash}/PageForm.js +15 -15
- package/dist/{theme/components → ui/dash}/PostForm.js +117 -137
- package/dist/{theme/components → ui/dash}/PostList.js +18 -13
- package/dist/ui/dash/StatusBadge.js +46 -0
- package/dist/{theme/components → ui/dash}/index.js +3 -6
- package/dist/ui/feed/LinkCard.js +72 -0
- package/dist/ui/feed/NoteCard.js +58 -0
- package/dist/{themes/minimal/timeline → ui/feed}/QuoteCard.js +29 -14
- package/dist/{themes/minimal/timeline → ui/feed}/ThreadPreview.js +20 -18
- package/dist/ui/feed/TimelineFeed.js +41 -0
- package/dist/ui/feed/TimelineItem.js +27 -0
- package/dist/{theme → ui}/layouts/BaseLayout.js +10 -0
- package/dist/{theme → ui}/layouts/DashLayout.js +0 -8
- package/dist/ui/layouts/SiteLayout.js +141 -0
- package/dist/{themes/minimal → ui}/pages/ArchivePage.js +37 -50
- package/dist/ui/pages/CollectionPage.js +70 -0
- package/dist/ui/pages/CollectionsPage.js +76 -0
- package/dist/ui/pages/FeaturedPage.js +24 -0
- package/dist/ui/pages/HomePage.js +24 -0
- package/dist/{themes/minimal → ui}/pages/PostPage.js +20 -12
- package/dist/{themes/minimal → ui}/pages/SearchPage.js +19 -18
- package/dist/{themes/minimal → ui}/pages/SinglePage.js +5 -4
- package/dist/ui/shared/MediaGallery.js +35 -0
- package/dist/{theme/components → ui/shared}/Pagination.js +41 -2
- package/dist/{theme/components → ui/shared}/ThreadView.js +3 -3
- package/dist/ui/shared/index.js +5 -0
- package/package.json +2 -9
- package/src/__tests__/helpers/app.ts +4 -0
- package/src/__tests__/helpers/db.ts +53 -73
- package/src/app.tsx +56 -28
- package/src/db/migrations/0005_v2_schema_migration.sql +268 -0
- package/src/db/migrations/0006_rename_slug_to_path.sql +5 -0
- package/src/db/migrations/meta/_journal.json +14 -0
- package/src/db/schema.ts +63 -46
- package/src/i18n/locales/en.po +443 -240
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +443 -240
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +443 -240
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/index.ts +29 -42
- package/src/lib/__tests__/excerpt.test.ts +125 -0
- package/src/lib/__tests__/schemas.test.ts +201 -99
- package/src/lib/__tests__/time.test.ts +62 -0
- package/src/{routes/api → lib}/__tests__/timeline.test.ts +81 -75
- package/src/lib/__tests__/view.test.ts +204 -50
- package/src/lib/constants.ts +2 -4
- package/src/lib/excerpt.ts +87 -0
- package/src/lib/feed.ts +22 -7
- package/src/lib/nav-reorder.ts +1 -1
- package/src/lib/navigation.ts +45 -8
- package/src/lib/pagination.ts +50 -0
- package/src/lib/render.tsx +7 -14
- package/src/lib/schemas.ts +119 -51
- package/src/lib/theme.ts +5 -5
- package/src/lib/time.ts +64 -0
- package/src/lib/timeline.ts +141 -0
- package/src/lib/view.ts +80 -82
- package/src/preset.css +46 -0
- package/src/routes/__tests__/compose.test.ts +199 -0
- package/src/routes/api/__tests__/collections.test.ts +249 -0
- package/src/routes/api/__tests__/nav-items.test.ts +222 -0
- package/src/routes/api/__tests__/pages.test.ts +218 -0
- package/src/routes/api/__tests__/posts.test.ts +50 -108
- package/src/routes/api/__tests__/search.test.ts +2 -3
- package/src/routes/api/__tests__/settings.test.ts +132 -0
- package/src/routes/api/collections.ts +143 -0
- package/src/routes/api/nav-items.ts +115 -0
- package/src/routes/api/pages.ts +101 -0
- package/src/routes/api/posts.ts +28 -28
- package/src/routes/api/search.ts +3 -3
- package/src/routes/api/settings.ts +91 -0
- package/src/routes/api/upload.ts +16 -6
- package/src/routes/compose.ts +63 -0
- package/src/routes/dash/__tests__/pages.test.ts +225 -0
- package/src/routes/dash/collections.tsx +20 -42
- package/src/routes/dash/index.tsx +3 -3
- package/src/routes/dash/media.tsx +2 -2
- package/src/routes/dash/pages.tsx +480 -122
- package/src/routes/dash/posts.tsx +42 -54
- package/src/routes/dash/redirects.tsx +2 -2
- package/src/routes/dash/settings.tsx +83 -5
- package/src/routes/feed/rss.ts +4 -3
- package/src/routes/feed/sitemap.ts +15 -5
- package/src/routes/pages/__tests__/collections.test.ts +94 -0
- package/src/routes/pages/__tests__/featured.test.ts +94 -0
- package/src/routes/pages/archive.tsx +15 -15
- package/src/routes/pages/collection.tsx +16 -9
- package/src/routes/pages/collections.tsx +36 -0
- package/src/routes/pages/featured.tsx +38 -0
- package/src/routes/pages/home.tsx +21 -92
- package/src/routes/pages/page.tsx +62 -27
- package/src/routes/pages/post.tsx +6 -18
- package/src/routes/pages/search.tsx +3 -7
- package/src/services/__tests__/collection.test.ts +257 -158
- package/src/services/__tests__/media.test.ts +18 -18
- package/src/services/__tests__/navigation.test.ts +161 -87
- package/src/services/__tests__/page.test.ts +106 -0
- package/src/services/__tests__/post-timeline.test.ts +92 -88
- package/src/services/__tests__/post.test.ts +432 -197
- package/src/services/__tests__/search.test.ts +19 -25
- package/src/services/collection.ts +71 -113
- package/src/services/index.ts +9 -8
- package/src/services/navigation.ts +38 -71
- package/src/services/page.ts +136 -0
- package/src/services/post.ts +141 -101
- package/src/services/search.ts +38 -27
- package/src/styles/tokens.css +47 -0
- package/src/styles/ui.css +491 -0
- package/src/types.ts +212 -198
- package/src/ui/compose/ComposeDialog.tsx +395 -0
- package/src/ui/compose/ComposePrompt.tsx +55 -0
- package/src/ui/dash/FormatBadge.tsx +28 -0
- package/src/{theme/components → ui/dash}/PageForm.tsx +21 -21
- package/src/{theme/components → ui/dash}/PostForm.tsx +110 -131
- package/src/ui/dash/PostList.tsx +101 -0
- package/src/ui/dash/StatusBadge.tsx +61 -0
- package/src/ui/dash/index.ts +10 -0
- package/src/ui/feed/LinkCard.tsx +72 -0
- package/src/ui/feed/NoteCard.tsx +63 -0
- package/src/ui/feed/QuoteCard.tsx +68 -0
- package/src/ui/feed/ThreadPreview.tsx +48 -0
- package/src/ui/feed/TimelineFeed.tsx +49 -0
- package/src/ui/feed/TimelineItem.tsx +45 -0
- package/src/{theme → ui}/layouts/BaseLayout.tsx +11 -1
- package/src/{theme → ui}/layouts/DashLayout.tsx +0 -10
- package/src/ui/layouts/SiteLayout.tsx +150 -0
- package/src/ui/pages/ArchivePage.tsx +162 -0
- package/src/ui/pages/CollectionPage.tsx +70 -0
- package/src/ui/pages/CollectionsPage.tsx +73 -0
- package/src/ui/pages/FeaturedPage.tsx +31 -0
- package/src/ui/pages/HomePage.tsx +37 -0
- package/src/ui/pages/PostPage.tsx +56 -0
- package/src/{themes/minimal → ui}/pages/SearchPage.tsx +24 -20
- package/src/{themes/minimal → ui}/pages/SinglePage.tsx +5 -5
- package/src/ui/shared/MediaGallery.tsx +59 -0
- package/src/{theme/components → ui/shared}/Pagination.tsx +67 -4
- package/src/{theme/components → ui/shared}/ThreadView.tsx +6 -3
- package/src/ui/shared/__tests__/pagination.test.ts +46 -0
- package/src/ui/shared/index.ts +12 -0
- package/bin/jant.js +0 -185
- package/dist/lib/theme-components.js +0 -49
- package/dist/routes/api/timeline.js +0 -120
- package/dist/routes/dash/navigation.js +0 -288
- package/dist/theme/components/MediaGallery.js +0 -107
- package/dist/theme/components/VisibilityBadge.js +0 -37
- package/dist/theme/index.js +0 -18
- package/dist/theme/layouts/index.js +0 -2
- package/dist/themes/minimal/MinimalSiteLayout.js +0 -83
- package/dist/themes/minimal/index.js +0 -65
- package/dist/themes/minimal/pages/CollectionPage.js +0 -65
- package/dist/themes/minimal/pages/HomePage.js +0 -25
- package/dist/themes/minimal/timeline/ArticleCard.js +0 -36
- package/dist/themes/minimal/timeline/ImageCard.js +0 -67
- package/dist/themes/minimal/timeline/LinkCard.js +0 -47
- package/dist/themes/minimal/timeline/NoteCard.js +0 -34
- package/dist/themes/minimal/timeline/TimelineFeed.js +0 -48
- package/dist/themes/minimal/timeline/TimelineItem.js +0 -44
- package/src/lib/__tests__/theme-components.test.ts +0 -126
- package/src/lib/theme-components.ts +0 -68
- package/src/routes/api/timeline.tsx +0 -159
- package/src/routes/dash/navigation.tsx +0 -316
- package/src/theme/components/MediaGallery.tsx +0 -128
- package/src/theme/components/PostList.tsx +0 -92
- package/src/theme/components/TypeBadge.tsx +0 -37
- package/src/theme/components/VisibilityBadge.tsx +0 -45
- package/src/theme/components/index.ts +0 -23
- package/src/theme/index.ts +0 -22
- package/src/theme/layouts/index.ts +0 -7
- package/src/themes/minimal/MinimalSiteLayout.tsx +0 -100
- package/src/themes/minimal/index.ts +0 -83
- package/src/themes/minimal/pages/ArchivePage.tsx +0 -157
- package/src/themes/minimal/pages/CollectionPage.tsx +0 -60
- package/src/themes/minimal/pages/HomePage.tsx +0 -41
- package/src/themes/minimal/pages/PostPage.tsx +0 -43
- package/src/themes/minimal/timeline/ArticleCard.tsx +0 -37
- package/src/themes/minimal/timeline/ImageCard.tsx +0 -63
- package/src/themes/minimal/timeline/LinkCard.tsx +0 -48
- package/src/themes/minimal/timeline/NoteCard.tsx +0 -35
- package/src/themes/minimal/timeline/QuoteCard.tsx +0 -49
- package/src/themes/minimal/timeline/ThreadPreview.tsx +0 -47
- package/src/themes/minimal/timeline/TimelineFeed.tsx +0 -57
- package/src/themes/minimal/timeline/TimelineItem.tsx +0 -75
- /package/dist/{theme → ui}/color-themes.js +0 -0
- /package/dist/{theme/components → ui/dash}/ActionButtons.js +0 -0
- /package/dist/{theme/components → ui/dash}/CrudPageHeader.js +0 -0
- /package/dist/{theme/components → ui/dash}/DangerZone.js +0 -0
- /package/dist/{theme/components → ui/dash}/ListItemRow.js +0 -0
- /package/dist/{theme/components → ui/shared}/EmptyState.js +0 -0
- /package/src/{theme → ui}/color-themes.ts +0 -0
- /package/src/{theme/components → ui/dash}/ActionButtons.tsx +0 -0
- /package/src/{theme/components → ui/dash}/CrudPageHeader.tsx +0 -0
- /package/src/{theme/components → ui/dash}/DangerZone.tsx +0 -0
- /package/src/{theme/components → ui/dash}/ListItemRow.tsx +0 -0
- /package/src/{theme/components → ui/shared}/EmptyState.tsx +0 -0
package/src/types.ts
CHANGED
|
@@ -1,48 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Jant Type Definitions
|
|
2
|
+
* Jant Type Definitions (v2)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
// =============================================================================
|
|
6
6
|
// Content Types
|
|
7
7
|
// =============================================================================
|
|
8
8
|
|
|
9
|
-
export const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
export const FORMATS = ["note", "link", "quote"] as const;
|
|
10
|
+
export type Format = (typeof FORMATS)[number];
|
|
11
|
+
|
|
12
|
+
export const STATUSES = ["draft", "published"] as const;
|
|
13
|
+
export type Status = (typeof STATUSES)[number];
|
|
14
|
+
|
|
15
|
+
export const SORT_ORDERS = [
|
|
16
|
+
"newest",
|
|
17
|
+
"oldest",
|
|
18
|
+
"rating_desc",
|
|
19
|
+
"rating_asc",
|
|
16
20
|
] as const;
|
|
17
|
-
export type
|
|
21
|
+
export type SortOrder = (typeof SORT_ORDERS)[number];
|
|
18
22
|
|
|
19
|
-
export const
|
|
23
|
+
export const NAV_ITEM_TYPES = ["page", "link"] as const;
|
|
24
|
+
export type NavItemType = (typeof NAV_ITEM_TYPES)[number];
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
* Each entry is [min, max] or null (no media allowed).
|
|
24
|
-
*/
|
|
25
|
-
export const POST_TYPE_MEDIA_RULES: Record<PostType, [number, number] | null> =
|
|
26
|
-
{
|
|
27
|
-
note: [0, 20],
|
|
28
|
-
article: [0, 20],
|
|
29
|
-
image: [1, 20],
|
|
30
|
-
link: [0, 1],
|
|
31
|
-
quote: [0, 20],
|
|
32
|
-
page: null,
|
|
33
|
-
};
|
|
26
|
+
export const MAX_MEDIA_ATTACHMENTS = 20;
|
|
27
|
+
export const MAX_PINNED_POSTS = 3;
|
|
34
28
|
|
|
35
29
|
export const STORAGE_DRIVERS = ["r2", "s3"] as const;
|
|
36
30
|
export type StorageDriver = (typeof STORAGE_DRIVERS)[number];
|
|
37
31
|
|
|
38
|
-
export const VISIBILITY_LEVELS = [
|
|
39
|
-
"featured",
|
|
40
|
-
"quiet",
|
|
41
|
-
"unlisted",
|
|
42
|
-
"draft",
|
|
43
|
-
] as const;
|
|
44
|
-
export type Visibility = (typeof VISIBILITY_LEVELS)[number];
|
|
45
|
-
|
|
46
32
|
// =============================================================================
|
|
47
33
|
// Cloudflare Bindings
|
|
48
34
|
// =============================================================================
|
|
@@ -56,6 +42,8 @@ export interface Bindings {
|
|
|
56
42
|
IMAGE_TRANSFORM_URL?: string;
|
|
57
43
|
DEMO_EMAIL?: string;
|
|
58
44
|
DEMO_PASSWORD?: string;
|
|
45
|
+
// Timeline
|
|
46
|
+
PAGE_SIZE?: string;
|
|
59
47
|
// Site configuration (optional - can be overridden in DB)
|
|
60
48
|
SITE_NAME?: string;
|
|
61
49
|
SITE_DESCRIPTION?: string;
|
|
@@ -81,8 +69,8 @@ export interface Bindings {
|
|
|
81
69
|
* Add new fields here, and they'll automatically work everywhere.
|
|
82
70
|
*
|
|
83
71
|
* Priority logic:
|
|
84
|
-
* - envOnly: false
|
|
85
|
-
* - envOnly: true
|
|
72
|
+
* - envOnly: false -> User-configurable (DB > ENV > Default)
|
|
73
|
+
* - envOnly: true -> Environment-only (ENV > Default)
|
|
86
74
|
*/
|
|
87
75
|
export const CONFIG_FIELDS = {
|
|
88
76
|
// User-configurable (can be modified in dashboard)
|
|
@@ -124,6 +112,10 @@ export const CONFIG_FIELDS = {
|
|
|
124
112
|
defaultValue: "",
|
|
125
113
|
envOnly: true,
|
|
126
114
|
},
|
|
115
|
+
PAGE_SIZE: {
|
|
116
|
+
defaultValue: "20",
|
|
117
|
+
envOnly: true,
|
|
118
|
+
},
|
|
127
119
|
STORAGE_DRIVER: {
|
|
128
120
|
defaultValue: "r2",
|
|
129
121
|
envOnly: true,
|
|
@@ -162,15 +154,18 @@ export type ConfigKey = keyof typeof CONFIG_FIELDS;
|
|
|
162
154
|
|
|
163
155
|
export interface Post {
|
|
164
156
|
id: number;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
157
|
+
format: Format;
|
|
158
|
+
status: Status;
|
|
159
|
+
featured: number; // 0 | 1
|
|
160
|
+
pinned: number; // 0 | 1
|
|
168
161
|
path: string | null;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
162
|
+
title: string | null;
|
|
163
|
+
url: string | null;
|
|
164
|
+
body: string | null;
|
|
165
|
+
bodyHtml: string | null;
|
|
166
|
+
quoteText: string | null;
|
|
167
|
+
rating: number | null;
|
|
168
|
+
collectionId: number | null;
|
|
174
169
|
replyToId: number | null;
|
|
175
170
|
threadId: number | null;
|
|
176
171
|
deletedAt: number | null;
|
|
@@ -179,6 +174,17 @@ export interface Post {
|
|
|
179
174
|
updatedAt: number;
|
|
180
175
|
}
|
|
181
176
|
|
|
177
|
+
export interface Page {
|
|
178
|
+
id: number;
|
|
179
|
+
slug: string;
|
|
180
|
+
title: string | null;
|
|
181
|
+
body: string | null;
|
|
182
|
+
bodyHtml: string | null;
|
|
183
|
+
status: Status;
|
|
184
|
+
createdAt: number;
|
|
185
|
+
updatedAt: number;
|
|
186
|
+
}
|
|
187
|
+
|
|
182
188
|
export interface Media {
|
|
183
189
|
id: string; // UUIDv7
|
|
184
190
|
postId: number | null;
|
|
@@ -214,17 +220,26 @@ export interface PostWithMedia extends Post {
|
|
|
214
220
|
|
|
215
221
|
export interface Collection {
|
|
216
222
|
id: number;
|
|
223
|
+
slug: string;
|
|
217
224
|
title: string;
|
|
218
|
-
path: string | null;
|
|
219
225
|
description: string | null;
|
|
226
|
+
icon: string | null;
|
|
227
|
+
sortOrder: SortOrder;
|
|
228
|
+
position: number;
|
|
229
|
+
showDivider: number; // 0 | 1
|
|
220
230
|
createdAt: number;
|
|
221
231
|
updatedAt: number;
|
|
222
232
|
}
|
|
223
233
|
|
|
224
|
-
export interface
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
234
|
+
export interface NavItem {
|
|
235
|
+
id: number;
|
|
236
|
+
type: NavItemType;
|
|
237
|
+
label: string;
|
|
238
|
+
url: string;
|
|
239
|
+
pageId: number | null;
|
|
240
|
+
position: number;
|
|
241
|
+
createdAt: number;
|
|
242
|
+
updatedAt: number;
|
|
228
243
|
}
|
|
229
244
|
|
|
230
245
|
export interface Redirect {
|
|
@@ -241,54 +256,91 @@ export interface Setting {
|
|
|
241
256
|
updatedAt: number;
|
|
242
257
|
}
|
|
243
258
|
|
|
244
|
-
export interface NavigationLink {
|
|
245
|
-
id: number;
|
|
246
|
-
label: string;
|
|
247
|
-
url: string;
|
|
248
|
-
position: number;
|
|
249
|
-
createdAt: number;
|
|
250
|
-
updatedAt: number;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
259
|
// =============================================================================
|
|
254
260
|
// Operation Types
|
|
255
261
|
// =============================================================================
|
|
256
262
|
|
|
257
263
|
export interface CreatePost {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
264
|
+
format: Format;
|
|
265
|
+
status?: Status;
|
|
266
|
+
featured?: boolean;
|
|
267
|
+
pinned?: boolean;
|
|
261
268
|
path?: string;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
269
|
+
title?: string;
|
|
270
|
+
url?: string;
|
|
271
|
+
body?: string;
|
|
272
|
+
quoteText?: string;
|
|
273
|
+
rating?: number;
|
|
274
|
+
collectionId?: number;
|
|
265
275
|
replyToId?: number;
|
|
266
276
|
publishedAt?: number;
|
|
267
277
|
mediaIds?: string[];
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
export interface UpdatePost {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
281
|
+
format?: Format;
|
|
282
|
+
status?: Status;
|
|
283
|
+
featured?: boolean;
|
|
284
|
+
pinned?: boolean;
|
|
274
285
|
path?: string | null;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
286
|
+
title?: string | null;
|
|
287
|
+
url?: string | null;
|
|
288
|
+
body?: string | null;
|
|
289
|
+
quoteText?: string | null;
|
|
290
|
+
rating?: number | null;
|
|
291
|
+
collectionId?: number | null;
|
|
278
292
|
publishedAt?: number;
|
|
279
293
|
mediaIds?: string[];
|
|
280
294
|
}
|
|
281
295
|
|
|
282
|
-
export interface
|
|
296
|
+
export interface CreatePage {
|
|
297
|
+
slug: string;
|
|
298
|
+
title?: string;
|
|
299
|
+
body?: string;
|
|
300
|
+
status?: Status;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export interface UpdatePage {
|
|
304
|
+
slug?: string;
|
|
305
|
+
title?: string | null;
|
|
306
|
+
body?: string | null;
|
|
307
|
+
status?: Status;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface CreateNavItem {
|
|
311
|
+
type: NavItemType;
|
|
283
312
|
label: string;
|
|
284
313
|
url: string;
|
|
314
|
+
pageId?: number;
|
|
285
315
|
position?: number;
|
|
286
316
|
}
|
|
287
317
|
|
|
288
|
-
export interface
|
|
318
|
+
export interface UpdateNavItem {
|
|
319
|
+
type?: NavItemType;
|
|
289
320
|
label?: string;
|
|
290
321
|
url?: string;
|
|
322
|
+
pageId?: number | null;
|
|
323
|
+
position?: number;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface CreateCollection {
|
|
327
|
+
slug: string;
|
|
328
|
+
title: string;
|
|
329
|
+
description?: string;
|
|
330
|
+
icon?: string;
|
|
331
|
+
sortOrder?: SortOrder;
|
|
332
|
+
position?: number;
|
|
333
|
+
showDivider?: boolean;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface UpdateCollection {
|
|
337
|
+
slug?: string;
|
|
338
|
+
title?: string;
|
|
339
|
+
description?: string | null;
|
|
340
|
+
icon?: string | null;
|
|
341
|
+
sortOrder?: SortOrder;
|
|
291
342
|
position?: number;
|
|
343
|
+
showDivider?: boolean;
|
|
292
344
|
}
|
|
293
345
|
|
|
294
346
|
// =============================================================================
|
|
@@ -297,41 +349,54 @@ export interface UpdateNavigationLink {
|
|
|
297
349
|
|
|
298
350
|
/**
|
|
299
351
|
* Render-ready post data for theme components.
|
|
300
|
-
* All fields are pre-computed
|
|
352
|
+
* All fields are pre-computed -- no lib/ imports needed.
|
|
301
353
|
*/
|
|
302
354
|
export interface PostView {
|
|
303
355
|
// Identity
|
|
304
356
|
id: number;
|
|
305
|
-
/** Pre-computed permalink,
|
|
357
|
+
/** Pre-computed permalink: "/{path}" if path set, otherwise "/p/{sqid}" */
|
|
306
358
|
permalink: string;
|
|
359
|
+
/** Custom URL path, if set. Supports multi-level paths (e.g. "2024/my-post") */
|
|
360
|
+
path?: string;
|
|
307
361
|
|
|
308
362
|
// Content
|
|
309
363
|
title?: string;
|
|
310
364
|
/** Pre-sanitized HTML */
|
|
311
|
-
|
|
365
|
+
bodyHtml?: string;
|
|
312
366
|
/** Pre-computed excerpt, max 160 chars */
|
|
313
367
|
excerpt?: string;
|
|
368
|
+
/** HTML excerpt for article previews (paragraph-aware, ~500 chars) */
|
|
369
|
+
summaryHtml?: string;
|
|
370
|
+
/** Whether summaryHtml was truncated (content continues beyond excerpt) */
|
|
371
|
+
summaryHasMore?: boolean;
|
|
372
|
+
/** URL for link/quote formats */
|
|
373
|
+
url?: string;
|
|
374
|
+
/** Quoted text for quote format */
|
|
375
|
+
quoteText?: string;
|
|
314
376
|
|
|
315
377
|
// Metadata
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
378
|
+
format: Format;
|
|
379
|
+
status: Status;
|
|
380
|
+
featured: boolean;
|
|
381
|
+
pinned: boolean;
|
|
382
|
+
rating?: number;
|
|
383
|
+
|
|
384
|
+
// Collection
|
|
385
|
+
collectionId?: number;
|
|
320
386
|
|
|
321
|
-
// Time
|
|
387
|
+
// Time -- pre-formatted
|
|
322
388
|
/** ISO 8601 string */
|
|
323
389
|
publishedAt: string;
|
|
324
390
|
/** Human-readable, e.g. "Feb 1, 2024" */
|
|
325
391
|
publishedAtFormatted: string;
|
|
392
|
+
/** 24-hour time, e.g. "23:05" */
|
|
393
|
+
publishedAtTime: string;
|
|
394
|
+
/** Short relative time, e.g. "5m", "3h", "2d", "Feb 1" */
|
|
395
|
+
publishedAtRelative: string;
|
|
326
396
|
/** ISO 8601 string */
|
|
327
397
|
updatedAt: string;
|
|
328
398
|
|
|
329
|
-
//
|
|
330
|
-
sourceUrl?: string;
|
|
331
|
-
sourceName?: string;
|
|
332
|
-
sourceDomain?: string;
|
|
333
|
-
|
|
334
|
-
// Media — URLs pre-computed
|
|
399
|
+
// Media -- URLs pre-computed
|
|
335
400
|
media: MediaView[];
|
|
336
401
|
|
|
337
402
|
// Thread context
|
|
@@ -339,12 +404,25 @@ export interface PostView {
|
|
|
339
404
|
threadRootId?: number;
|
|
340
405
|
|
|
341
406
|
// Raw content (for forms/editing, not typical theme use)
|
|
342
|
-
|
|
407
|
+
body?: string;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Render-ready page data for theme components.
|
|
412
|
+
*/
|
|
413
|
+
export interface PageView {
|
|
414
|
+
id: number;
|
|
415
|
+
slug: string;
|
|
416
|
+
title?: string;
|
|
417
|
+
bodyHtml?: string;
|
|
418
|
+
status: Status;
|
|
419
|
+
createdAt: string;
|
|
420
|
+
updatedAt: string;
|
|
343
421
|
}
|
|
344
422
|
|
|
345
423
|
/**
|
|
346
424
|
* Render-ready media data for theme components.
|
|
347
|
-
* URLs are pre-computed
|
|
425
|
+
* URLs are pre-computed -- no lib/ imports needed.
|
|
348
426
|
*/
|
|
349
427
|
export interface MediaView {
|
|
350
428
|
id: string;
|
|
@@ -360,13 +438,15 @@ export interface MediaView {
|
|
|
360
438
|
}
|
|
361
439
|
|
|
362
440
|
/**
|
|
363
|
-
* Render-ready navigation
|
|
441
|
+
* Render-ready navigation item for theme components.
|
|
364
442
|
* Active/external state pre-computed.
|
|
365
443
|
*/
|
|
366
|
-
export interface
|
|
444
|
+
export interface NavItemView {
|
|
367
445
|
id: number;
|
|
446
|
+
type: NavItemType;
|
|
368
447
|
label: string;
|
|
369
448
|
url: string;
|
|
449
|
+
pageId?: number;
|
|
370
450
|
/** Pre-computed based on currentPath */
|
|
371
451
|
isActive: boolean;
|
|
372
452
|
/** Pre-computed: starts with http(s):// */
|
|
@@ -406,12 +486,15 @@ export interface ArchiveGroup {
|
|
|
406
486
|
posts: PostView[];
|
|
407
487
|
}
|
|
408
488
|
|
|
489
|
+
// =============================================================================
|
|
490
|
+
// Page-Based Pagination Types
|
|
491
|
+
// =============================================================================
|
|
492
|
+
|
|
409
493
|
// =============================================================================
|
|
410
494
|
// Configuration Types
|
|
411
495
|
// =============================================================================
|
|
412
496
|
|
|
413
|
-
import type {
|
|
414
|
-
import type { ColorTheme } from "./theme/color-themes.js";
|
|
497
|
+
import type { ColorTheme } from "./ui/color-themes.js";
|
|
415
498
|
|
|
416
499
|
/**
|
|
417
500
|
* Search result from FTS5
|
|
@@ -430,8 +513,11 @@ export interface SearchResult {
|
|
|
430
513
|
|
|
431
514
|
export interface SiteLayoutProps {
|
|
432
515
|
siteName: string;
|
|
433
|
-
|
|
516
|
+
siteDescription?: string;
|
|
517
|
+
links: NavItemView[];
|
|
434
518
|
currentPath: string;
|
|
519
|
+
isAuthenticated?: boolean;
|
|
520
|
+
collections?: Collection[];
|
|
435
521
|
}
|
|
436
522
|
|
|
437
523
|
// =============================================================================
|
|
@@ -441,21 +527,24 @@ export interface SiteLayoutProps {
|
|
|
441
527
|
/** Props for the home page component */
|
|
442
528
|
export interface HomePageProps {
|
|
443
529
|
items: TimelineItemView[];
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
530
|
+
pinnedItems: PostView[];
|
|
531
|
+
currentPage: number;
|
|
532
|
+
totalPages: number;
|
|
447
533
|
}
|
|
448
534
|
|
|
449
535
|
/** Props for the single post page component */
|
|
450
536
|
export interface PostPageProps {
|
|
451
537
|
post: PostView;
|
|
452
|
-
theme?: ThemeComponents;
|
|
453
538
|
}
|
|
454
539
|
|
|
455
540
|
/** Props for the custom page component */
|
|
456
541
|
export interface SinglePageProps {
|
|
457
|
-
page:
|
|
458
|
-
|
|
542
|
+
page: PageView;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/** Props for the featured page component */
|
|
546
|
+
export interface FeaturedPageProps {
|
|
547
|
+
items: TimelineItemView[];
|
|
459
548
|
}
|
|
460
549
|
|
|
461
550
|
/** Props for the archive page component */
|
|
@@ -463,8 +552,8 @@ export interface ArchivePageProps {
|
|
|
463
552
|
groups: ArchiveGroup[];
|
|
464
553
|
hasMore: boolean;
|
|
465
554
|
nextCursor?: number;
|
|
466
|
-
|
|
467
|
-
|
|
555
|
+
format?: Format;
|
|
556
|
+
featured?: boolean;
|
|
468
557
|
}
|
|
469
558
|
|
|
470
559
|
/** Props for the search page component */
|
|
@@ -474,14 +563,19 @@ export interface SearchPageProps {
|
|
|
474
563
|
error?: string;
|
|
475
564
|
hasMore: boolean;
|
|
476
565
|
page: number;
|
|
477
|
-
theme?: ThemeComponents;
|
|
478
566
|
}
|
|
479
567
|
|
|
480
|
-
/** Props for the collection page component */
|
|
568
|
+
/** Props for the single collection page component */
|
|
481
569
|
export interface CollectionPageProps {
|
|
482
570
|
collection: Collection;
|
|
483
571
|
posts: PostView[];
|
|
484
|
-
|
|
572
|
+
hasMore: boolean;
|
|
573
|
+
nextCursor?: number;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** Props for the collections list page component */
|
|
577
|
+
export interface CollectionsPageProps {
|
|
578
|
+
collections: (Collection & { postCount: number })[];
|
|
485
579
|
}
|
|
486
580
|
|
|
487
581
|
// =============================================================================
|
|
@@ -501,6 +595,7 @@ export interface FeedData {
|
|
|
501
595
|
export interface SitemapData {
|
|
502
596
|
siteUrl: string;
|
|
503
597
|
posts: PostView[];
|
|
598
|
+
pages: PageView[];
|
|
504
599
|
}
|
|
505
600
|
|
|
506
601
|
// =============================================================================
|
|
@@ -518,105 +613,13 @@ export interface ThreadPreviewProps {
|
|
|
518
613
|
rootPost: PostView;
|
|
519
614
|
previewReplies: PostView[];
|
|
520
615
|
totalReplyCount: number;
|
|
521
|
-
theme?: ThemeComponents;
|
|
522
616
|
}
|
|
523
617
|
|
|
524
618
|
/** Props for the timeline feed wrapper */
|
|
525
619
|
export interface TimelineFeedProps {
|
|
526
620
|
items: TimelineItemView[];
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
theme?: ThemeComponents;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Theme component overrides
|
|
534
|
-
*/
|
|
535
|
-
export interface ThemeComponents {
|
|
536
|
-
// Layout
|
|
537
|
-
SiteLayout?: FC<PropsWithChildren<SiteLayoutProps>>;
|
|
538
|
-
|
|
539
|
-
// Pages
|
|
540
|
-
HomePage?: FC<HomePageProps>;
|
|
541
|
-
PostPage?: FC<PostPageProps>;
|
|
542
|
-
SinglePage?: FC<SinglePageProps>;
|
|
543
|
-
ArchivePage?: FC<ArchivePageProps>;
|
|
544
|
-
SearchPage?: FC<SearchPageProps>;
|
|
545
|
-
CollectionPage?: FC<CollectionPageProps>;
|
|
546
|
-
|
|
547
|
-
// Timeline sub-components
|
|
548
|
-
NoteCard?: FC<TimelineCardProps>;
|
|
549
|
-
ArticleCard?: FC<TimelineCardProps>;
|
|
550
|
-
LinkCard?: FC<TimelineCardProps>;
|
|
551
|
-
QuoteCard?: FC<TimelineCardProps>;
|
|
552
|
-
ImageCard?: FC<TimelineCardProps>;
|
|
553
|
-
ThreadPreview?: FC<ThreadPreviewProps>;
|
|
554
|
-
TimelineFeed?: FC<TimelineFeedProps>;
|
|
555
|
-
|
|
556
|
-
// Shared sub-components (re-exported real prop types from component files)
|
|
557
|
-
Pagination?: FC<PaginationComponentProps>;
|
|
558
|
-
PagePagination?: FC<PagePaginationComponentProps>;
|
|
559
|
-
EmptyState?: FC<EmptyStateComponentProps>;
|
|
560
|
-
MediaGallery?: FC<MediaGalleryComponentProps>;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/**
|
|
564
|
-
* Real component prop types (re-exported from component files via index.ts).
|
|
565
|
-
* These are provided here as aliases to avoid circular imports in types.ts.
|
|
566
|
-
* The canonical definitions live in the component files.
|
|
567
|
-
*/
|
|
568
|
-
|
|
569
|
-
/** @see Pagination component in theme/components/Pagination.tsx */
|
|
570
|
-
export interface PaginationComponentProps {
|
|
571
|
-
baseUrl: string;
|
|
572
|
-
hasMore: boolean;
|
|
573
|
-
nextCursor?: number | string;
|
|
574
|
-
prevCursor?: number | string;
|
|
575
|
-
cursorParam?: string;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
/** @see PagePagination component in theme/components/Pagination.tsx */
|
|
579
|
-
export interface PagePaginationComponentProps {
|
|
580
|
-
baseUrl: string;
|
|
581
|
-
currentPage: number;
|
|
582
|
-
hasMore: boolean;
|
|
583
|
-
pageParam?: string;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/** @see EmptyState component in theme/components/EmptyState.tsx */
|
|
587
|
-
export interface EmptyStateComponentProps {
|
|
588
|
-
message: string;
|
|
589
|
-
ctaText?: string;
|
|
590
|
-
ctaHref?: string;
|
|
591
|
-
centered?: boolean;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
/** @see MediaGallery component in theme/components/MediaGallery.tsx */
|
|
595
|
-
export interface MediaGalleryComponentProps {
|
|
596
|
-
attachments: MediaView[];
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* Theme configuration
|
|
601
|
-
*/
|
|
602
|
-
export interface JantTheme {
|
|
603
|
-
/** Theme name */
|
|
604
|
-
name?: string;
|
|
605
|
-
/** Component overrides */
|
|
606
|
-
components?: ThemeComponents;
|
|
607
|
-
/** Feed renderer overrides (RSS, Atom, Sitemap) */
|
|
608
|
-
feed?: {
|
|
609
|
-
/** Custom RSS 2.0 renderer — returns XML string */
|
|
610
|
-
rss?: (data: FeedData) => string;
|
|
611
|
-
/** Custom Atom renderer — returns XML string */
|
|
612
|
-
atom?: (data: FeedData) => string;
|
|
613
|
-
/** Custom Sitemap renderer — returns XML string */
|
|
614
|
-
sitemap?: (data: SitemapData) => string;
|
|
615
|
-
};
|
|
616
|
-
/** CSS variable overrides (highest priority, always applied) */
|
|
617
|
-
cssVariables?: Record<string, string>;
|
|
618
|
-
/** Replace built-in color themes with a custom list */
|
|
619
|
-
colorThemes?: ColorTheme[];
|
|
621
|
+
currentPage?: number;
|
|
622
|
+
totalPages?: number;
|
|
620
623
|
}
|
|
621
624
|
|
|
622
625
|
/**
|
|
@@ -624,12 +627,23 @@ export interface JantTheme {
|
|
|
624
627
|
*
|
|
625
628
|
* Configuration Philosophy:
|
|
626
629
|
* - Use environment variables for runtime config (API keys, feature flags, site settings)
|
|
627
|
-
* - Use code config (this object) for
|
|
630
|
+
* - Use code config (this object) for CSS customization and feed overrides
|
|
628
631
|
*
|
|
629
632
|
* Site-level settings (name, description, language) are configured via
|
|
630
633
|
* environment variables, not here. See lib/config.ts for details.
|
|
631
634
|
*/
|
|
632
635
|
export interface JantConfig {
|
|
633
|
-
/**
|
|
634
|
-
|
|
636
|
+
/** CSS variable overrides (highest priority after custom CSS) */
|
|
637
|
+
cssVariables?: Record<string, string>;
|
|
638
|
+
/** Replace built-in color themes with custom list */
|
|
639
|
+
colorThemes?: ColorTheme[];
|
|
640
|
+
/** Custom feed renderers */
|
|
641
|
+
feed?: {
|
|
642
|
+
/** Custom RSS 2.0 renderer -- returns XML string */
|
|
643
|
+
rss?: (data: FeedData) => string;
|
|
644
|
+
/** Custom Atom renderer -- returns XML string */
|
|
645
|
+
atom?: (data: FeedData) => string;
|
|
646
|
+
/** Custom Sitemap renderer -- returns XML string */
|
|
647
|
+
sitemap?: (data: SitemapData) => string;
|
|
648
|
+
};
|
|
635
649
|
}
|