@jant/core 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/dist/app.d.ts +34 -0
  2. package/dist/app.d.ts.map +1 -0
  3. package/dist/app.js +474 -0
  4. package/dist/assets/datastar.min.js +1775 -0
  5. package/dist/auth.d.ts +23 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +34 -0
  8. package/{src/client.ts → dist/client.d.ts} +1 -1
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +4 -0
  11. package/dist/db/index.d.ts +10 -0
  12. package/dist/db/index.d.ts.map +1 -0
  13. package/dist/db/index.js +10 -0
  14. package/dist/db/schema.d.ts +1507 -0
  15. package/dist/db/schema.d.ts.map +1 -0
  16. package/dist/db/schema.js +183 -0
  17. package/{src/i18n/Trans.tsx → dist/i18n/Trans.d.ts} +4 -10
  18. package/dist/i18n/Trans.d.ts.map +1 -0
  19. package/dist/i18n/Trans.js +24 -0
  20. package/dist/i18n/context.d.ts +69 -0
  21. package/dist/i18n/context.d.ts.map +1 -0
  22. package/dist/i18n/context.js +61 -0
  23. package/dist/i18n/detect.d.ts +31 -0
  24. package/dist/i18n/detect.d.ts.map +1 -0
  25. package/dist/i18n/detect.js +77 -0
  26. package/{src/i18n/i18n.ts → dist/i18n/i18n.d.ts} +5 -25
  27. package/dist/i18n/i18n.d.ts.map +1 -0
  28. package/dist/i18n/i18n.js +55 -0
  29. package/dist/i18n/index.d.ts +41 -0
  30. package/dist/i18n/index.d.ts.map +1 -0
  31. package/{src/i18n/index.ts → dist/i18n/index.js} +3 -24
  32. package/dist/i18n/locales/en.d.ts +3 -0
  33. package/dist/i18n/locales/en.d.ts.map +1 -0
  34. package/dist/i18n/locales/en.js +1 -0
  35. package/dist/i18n/locales/zh-Hans.d.ts +3 -0
  36. package/dist/i18n/locales/zh-Hans.d.ts.map +1 -0
  37. package/dist/i18n/locales/zh-Hans.js +1 -0
  38. package/dist/i18n/locales/zh-Hant.d.ts +3 -0
  39. package/dist/i18n/locales/zh-Hant.d.ts.map +1 -0
  40. package/dist/i18n/locales/zh-Hant.js +1 -0
  41. package/dist/i18n/locales.d.ts +11 -0
  42. package/dist/i18n/locales.d.ts.map +1 -0
  43. package/dist/i18n/locales.js +13 -0
  44. package/dist/i18n/middleware.d.ts +24 -0
  45. package/dist/i18n/middleware.d.ts.map +1 -0
  46. package/dist/i18n/middleware.js +41 -0
  47. package/dist/index.d.ts +16 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/{src/index.ts → dist/index.js} +1 -28
  50. package/dist/lib/assets.d.ts +19 -0
  51. package/dist/lib/assets.d.ts.map +1 -0
  52. package/dist/lib/assets.js +33 -0
  53. package/dist/lib/constants.d.ts +36 -0
  54. package/dist/lib/constants.d.ts.map +1 -0
  55. package/dist/lib/constants.js +50 -0
  56. package/{src/lib/image.ts → dist/lib/image.d.ts} +13 -47
  57. package/dist/lib/image.d.ts.map +1 -0
  58. package/dist/lib/image.js +77 -0
  59. package/{src/lib/index.ts → dist/lib/index.d.ts} +1 -1
  60. package/dist/lib/index.d.ts.map +1 -0
  61. package/dist/lib/index.js +7 -0
  62. package/dist/lib/markdown.d.ts +60 -0
  63. package/dist/lib/markdown.d.ts.map +1 -0
  64. package/{src/lib/markdown.ts → dist/lib/markdown.js} +16 -26
  65. package/dist/lib/schemas.d.ts +113 -0
  66. package/dist/lib/schemas.d.ts.map +1 -0
  67. package/dist/lib/schemas.js +71 -0
  68. package/dist/lib/sqid.d.ts +60 -0
  69. package/dist/lib/sqid.d.ts.map +1 -0
  70. package/{src/lib/sqid.ts → dist/lib/sqid.js} +15 -22
  71. package/dist/lib/sse.d.ts +95 -0
  72. package/dist/lib/sse.d.ts.map +1 -0
  73. package/dist/lib/sse.js +81 -0
  74. package/dist/lib/time.d.ts +90 -0
  75. package/dist/lib/time.d.ts.map +1 -0
  76. package/{src/lib/time.ts → dist/lib/time.js} +20 -33
  77. package/{src/lib/url.ts → dist/lib/url.d.ts} +5 -30
  78. package/dist/lib/url.d.ts.map +1 -0
  79. package/dist/lib/url.js +89 -0
  80. package/dist/middleware/auth.d.ts +24 -0
  81. package/dist/middleware/auth.d.ts.map +1 -0
  82. package/dist/middleware/auth.js +52 -0
  83. package/dist/routes/api/posts.d.ts +13 -0
  84. package/dist/routes/api/posts.d.ts.map +1 -0
  85. package/dist/routes/api/posts.js +124 -0
  86. package/dist/routes/api/search.d.ts +13 -0
  87. package/dist/routes/api/search.d.ts.map +1 -0
  88. package/dist/routes/api/search.js +49 -0
  89. package/dist/routes/api/upload.d.ts +16 -0
  90. package/dist/routes/api/upload.d.ts.map +1 -0
  91. package/dist/routes/api/upload.js +227 -0
  92. package/dist/routes/dash/collections.d.ts +13 -0
  93. package/dist/routes/dash/collections.d.ts.map +1 -0
  94. package/dist/routes/dash/collections.js +512 -0
  95. package/dist/routes/dash/index.d.ts +15 -0
  96. package/dist/routes/dash/index.d.ts.map +1 -0
  97. package/dist/routes/dash/index.js +117 -0
  98. package/dist/routes/dash/media.d.ts +16 -0
  99. package/dist/routes/dash/media.d.ts.map +1 -0
  100. package/dist/routes/dash/media.js +589 -0
  101. package/dist/routes/dash/pages.d.ts +15 -0
  102. package/dist/routes/dash/pages.d.ts.map +1 -0
  103. package/dist/routes/dash/pages.js +290 -0
  104. package/dist/routes/dash/posts.d.ts +13 -0
  105. package/dist/routes/dash/posts.d.ts.map +1 -0
  106. package/dist/routes/dash/posts.js +226 -0
  107. package/dist/routes/dash/redirects.d.ts +13 -0
  108. package/dist/routes/dash/redirects.d.ts.map +1 -0
  109. package/dist/routes/dash/redirects.js +237 -0
  110. package/dist/routes/dash/settings.d.ts +13 -0
  111. package/dist/routes/dash/settings.d.ts.map +1 -0
  112. package/dist/routes/dash/settings.js +154 -0
  113. package/dist/routes/feed/rss.d.ts +13 -0
  114. package/dist/routes/feed/rss.d.ts.map +1 -0
  115. package/dist/routes/feed/rss.js +95 -0
  116. package/dist/routes/feed/sitemap.d.ts +13 -0
  117. package/dist/routes/feed/sitemap.d.ts.map +1 -0
  118. package/dist/routes/feed/sitemap.js +59 -0
  119. package/dist/routes/pages/archive.d.ts +15 -0
  120. package/dist/routes/pages/archive.d.ts.map +1 -0
  121. package/dist/routes/pages/archive.js +255 -0
  122. package/dist/routes/pages/collection.d.ts +13 -0
  123. package/dist/routes/pages/collection.d.ts.map +1 -0
  124. package/dist/routes/pages/collection.js +93 -0
  125. package/dist/routes/pages/home.d.ts +13 -0
  126. package/dist/routes/pages/home.d.ts.map +1 -0
  127. package/dist/routes/pages/home.js +122 -0
  128. package/dist/routes/pages/page.d.ts +15 -0
  129. package/dist/routes/pages/page.d.ts.map +1 -0
  130. package/dist/routes/pages/page.js +69 -0
  131. package/dist/routes/pages/post.d.ts +13 -0
  132. package/dist/routes/pages/post.d.ts.map +1 -0
  133. package/dist/routes/pages/post.js +90 -0
  134. package/dist/routes/pages/search.d.ts +13 -0
  135. package/dist/routes/pages/search.d.ts.map +1 -0
  136. package/dist/routes/pages/search.js +180 -0
  137. package/dist/services/collection.d.ts +31 -0
  138. package/dist/services/collection.d.ts.map +1 -0
  139. package/dist/services/collection.js +108 -0
  140. package/dist/services/index.d.ts +28 -0
  141. package/dist/services/index.d.ts.map +1 -0
  142. package/dist/services/index.js +20 -0
  143. package/dist/services/media.d.ts +27 -0
  144. package/dist/services/media.d.ts.map +1 -0
  145. package/dist/services/media.js +62 -0
  146. package/dist/services/post.d.ts +31 -0
  147. package/dist/services/post.d.ts.map +1 -0
  148. package/dist/services/post.js +191 -0
  149. package/dist/services/redirect.d.ts +15 -0
  150. package/dist/services/redirect.d.ts.map +1 -0
  151. package/dist/services/redirect.js +48 -0
  152. package/dist/services/search.d.ts +26 -0
  153. package/dist/services/search.d.ts.map +1 -0
  154. package/dist/services/search.js +61 -0
  155. package/dist/services/settings.d.ts +17 -0
  156. package/dist/services/settings.d.ts.map +1 -0
  157. package/dist/services/settings.js +65 -0
  158. package/dist/theme/components/ActionButtons.d.ts +43 -0
  159. package/dist/theme/components/ActionButtons.d.ts.map +1 -0
  160. package/dist/theme/components/ActionButtons.js +50 -0
  161. package/dist/theme/components/CrudPageHeader.d.ts +23 -0
  162. package/dist/theme/components/CrudPageHeader.d.ts.map +1 -0
  163. package/dist/theme/components/CrudPageHeader.js +22 -0
  164. package/dist/theme/components/DangerZone.d.ts +36 -0
  165. package/dist/theme/components/DangerZone.d.ts.map +1 -0
  166. package/dist/theme/components/DangerZone.js +39 -0
  167. package/dist/theme/components/EmptyState.d.ts +27 -0
  168. package/dist/theme/components/EmptyState.d.ts.map +1 -0
  169. package/dist/theme/components/EmptyState.js +27 -0
  170. package/dist/theme/components/ListItemRow.d.ts +15 -0
  171. package/dist/theme/components/ListItemRow.d.ts.map +1 -0
  172. package/dist/theme/components/ListItemRow.js +21 -0
  173. package/dist/theme/components/PageForm.d.ts +14 -0
  174. package/dist/theme/components/PageForm.d.ts.map +1 -0
  175. package/dist/theme/components/PageForm.js +173 -0
  176. package/dist/theme/components/Pagination.d.ts +46 -0
  177. package/dist/theme/components/Pagination.d.ts.map +1 -0
  178. package/dist/theme/components/Pagination.js +159 -0
  179. package/dist/theme/components/PostForm.d.ts +12 -0
  180. package/dist/theme/components/PostForm.d.ts.map +1 -0
  181. package/dist/theme/components/PostForm.js +230 -0
  182. package/dist/theme/components/PostList.d.ts +10 -0
  183. package/dist/theme/components/PostList.d.ts.map +1 -0
  184. package/dist/theme/components/PostList.js +73 -0
  185. package/dist/theme/components/ThreadView.d.ts +15 -0
  186. package/dist/theme/components/ThreadView.d.ts.map +1 -0
  187. package/dist/theme/components/ThreadView.js +111 -0
  188. package/dist/theme/components/TypeBadge.d.ts +12 -0
  189. package/dist/theme/components/TypeBadge.d.ts.map +1 -0
  190. package/dist/theme/components/TypeBadge.js +39 -0
  191. package/dist/theme/components/VisibilityBadge.d.ts +12 -0
  192. package/dist/theme/components/VisibilityBadge.d.ts.map +1 -0
  193. package/dist/theme/components/VisibilityBadge.js +37 -0
  194. package/{src/theme/components/index.ts → dist/theme/components/index.d.ts} +1 -0
  195. package/dist/theme/components/index.d.ts.map +1 -0
  196. package/dist/theme/components/index.js +12 -0
  197. package/dist/theme/index.d.ts +21 -0
  198. package/dist/theme/index.d.ts.map +1 -0
  199. package/{src/theme/index.ts → dist/theme/index.js} +1 -4
  200. package/dist/theme/layouts/BaseLayout.d.ts +16 -0
  201. package/dist/theme/layouts/BaseLayout.d.ts.map +1 -0
  202. package/dist/theme/layouts/BaseLayout.js +58 -0
  203. package/dist/theme/layouts/DashLayout.d.ts +15 -0
  204. package/dist/theme/layouts/DashLayout.d.ts.map +1 -0
  205. package/dist/theme/layouts/DashLayout.js +139 -0
  206. package/{src/theme/layouts/index.ts → dist/theme/layouts/index.d.ts} +1 -0
  207. package/dist/theme/layouts/index.d.ts.map +1 -0
  208. package/dist/theme/layouts/index.js +2 -0
  209. package/dist/theme/styles/main.css +2 -0
  210. package/dist/types.d.ts +179 -0
  211. package/dist/types.d.ts.map +1 -0
  212. package/dist/types.js +19 -0
  213. package/package.json +26 -26
  214. package/drizzle.config.ts +0 -10
  215. package/lingui.config.ts +0 -16
  216. package/src/app.tsx +0 -377
  217. package/src/assets/datastar.min.js +0 -8
  218. package/src/auth.ts +0 -38
  219. package/src/db/index.ts +0 -14
  220. package/src/db/migrations/0000_solid_moon_knight.sql +0 -118
  221. package/src/db/migrations/0001_add_search_fts.sql +0 -40
  222. package/src/db/migrations/0002_collection_path.sql +0 -2
  223. package/src/db/migrations/0003_collection_path_nullable.sql +0 -21
  224. package/src/db/migrations/0004_media_uuid.sql +0 -35
  225. package/src/db/migrations/meta/0000_snapshot.json +0 -784
  226. package/src/db/migrations/meta/_journal.json +0 -41
  227. package/src/db/schema.ts +0 -159
  228. package/src/i18n/EXAMPLES.md +0 -235
  229. package/src/i18n/README.md +0 -296
  230. package/src/i18n/context.tsx +0 -101
  231. package/src/i18n/detect.ts +0 -100
  232. package/src/i18n/locales/en.po +0 -875
  233. package/src/i18n/locales/en.ts +0 -1
  234. package/src/i18n/locales/zh-Hans.po +0 -875
  235. package/src/i18n/locales/zh-Hans.ts +0 -1
  236. package/src/i18n/locales/zh-Hant.po +0 -875
  237. package/src/i18n/locales/zh-Hant.ts +0 -1
  238. package/src/i18n/locales.ts +0 -14
  239. package/src/i18n/middleware.ts +0 -59
  240. package/src/lib/assets.ts +0 -47
  241. package/src/lib/constants.ts +0 -67
  242. package/src/lib/schemas.ts +0 -92
  243. package/src/lib/sse.ts +0 -152
  244. package/src/middleware/auth.ts +0 -59
  245. package/src/routes/api/posts.ts +0 -127
  246. package/src/routes/api/search.ts +0 -53
  247. package/src/routes/api/upload.ts +0 -240
  248. package/src/routes/dash/collections.tsx +0 -341
  249. package/src/routes/dash/index.tsx +0 -89
  250. package/src/routes/dash/media.tsx +0 -551
  251. package/src/routes/dash/pages.tsx +0 -245
  252. package/src/routes/dash/posts.tsx +0 -202
  253. package/src/routes/dash/redirects.tsx +0 -155
  254. package/src/routes/dash/settings.tsx +0 -93
  255. package/src/routes/feed/rss.ts +0 -119
  256. package/src/routes/feed/sitemap.ts +0 -75
  257. package/src/routes/pages/archive.tsx +0 -223
  258. package/src/routes/pages/collection.tsx +0 -79
  259. package/src/routes/pages/home.tsx +0 -93
  260. package/src/routes/pages/page.tsx +0 -64
  261. package/src/routes/pages/post.tsx +0 -81
  262. package/src/routes/pages/search.tsx +0 -162
  263. package/src/services/collection.ts +0 -180
  264. package/src/services/index.ts +0 -40
  265. package/src/services/media.ts +0 -97
  266. package/src/services/post.ts +0 -279
  267. package/src/services/redirect.ts +0 -74
  268. package/src/services/search.ts +0 -117
  269. package/src/services/settings.ts +0 -76
  270. package/src/theme/components/ActionButtons.tsx +0 -98
  271. package/src/theme/components/CrudPageHeader.tsx +0 -48
  272. package/src/theme/components/DangerZone.tsx +0 -77
  273. package/src/theme/components/EmptyState.tsx +0 -56
  274. package/src/theme/components/ListItemRow.tsx +0 -24
  275. package/src/theme/components/PageForm.tsx +0 -114
  276. package/src/theme/components/Pagination.tsx +0 -196
  277. package/src/theme/components/PostForm.tsx +0 -122
  278. package/src/theme/components/PostList.tsx +0 -68
  279. package/src/theme/components/ThreadView.tsx +0 -118
  280. package/src/theme/components/TypeBadge.tsx +0 -28
  281. package/src/theme/components/VisibilityBadge.tsx +0 -33
  282. package/src/theme/layouts/BaseLayout.tsx +0 -49
  283. package/src/theme/layouts/DashLayout.tsx +0 -108
  284. package/src/theme/styles/main.css +0 -52
  285. package/src/types.ts +0 -222
  286. package/tsconfig.json +0 -16
  287. package/vite.config.ts +0 -82
  288. package/wrangler.toml +0 -21
@@ -0,0 +1,255 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
+ /**
3
+ * Archive Page Route
4
+ *
5
+ * Shows all posts, optionally filtered by type
6
+ */ import { Hono } from "hono";
7
+ import { useLingui } from "../../i18n/index.js";
8
+ import { BaseLayout } from "../../theme/layouts/index.js";
9
+ import { Pagination } from "../../theme/components/index.js";
10
+ import { POST_TYPES } from "../../types.js";
11
+ import * as sqid from "../../lib/sqid.js";
12
+ import * as time from "../../lib/time.js";
13
+ const PAGE_SIZE = 50;
14
+ export const archiveRoutes = new Hono();
15
+ function getTypeLabel(type) {
16
+ const { t } = useLingui();
17
+ const labels = {
18
+ note: t({
19
+ message: "Note",
20
+ comment: "@context: Post type label - note"
21
+ }),
22
+ article: t({
23
+ message: "Article",
24
+ comment: "@context: Post type label - article"
25
+ }),
26
+ link: t({
27
+ message: "Link",
28
+ comment: "@context: Post type label - link"
29
+ }),
30
+ quote: t({
31
+ message: "Quote",
32
+ comment: "@context: Post type label - quote"
33
+ }),
34
+ image: t({
35
+ message: "Image",
36
+ comment: "@context: Post type label - image"
37
+ }),
38
+ page: t({
39
+ message: "Page",
40
+ comment: "@context: Post type label - page"
41
+ })
42
+ };
43
+ return labels[type] ?? type;
44
+ }
45
+ function getTypeLabelPlural(type) {
46
+ const { t } = useLingui();
47
+ const labels = {
48
+ note: t({
49
+ message: "Notes",
50
+ comment: "@context: Post type label plural - notes"
51
+ }),
52
+ article: t({
53
+ message: "Articles",
54
+ comment: "@context: Post type label plural - articles"
55
+ }),
56
+ link: t({
57
+ message: "Links",
58
+ comment: "@context: Post type label plural - links"
59
+ }),
60
+ quote: t({
61
+ message: "Quotes",
62
+ comment: "@context: Post type label plural - quotes"
63
+ }),
64
+ image: t({
65
+ message: "Images",
66
+ comment: "@context: Post type label plural - images"
67
+ }),
68
+ page: t({
69
+ message: "Pages",
70
+ comment: "@context: Post type label plural - pages"
71
+ })
72
+ };
73
+ return labels[type] ?? `${type}s`;
74
+ }
75
+ function formatYearMonth(yearMonth) {
76
+ const [year, month] = yearMonth.split("-");
77
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- yearMonth format YYYY-MM guarantees both year and month exist
78
+ const date = new Date(parseInt(year, 10), parseInt(month, 10) - 1);
79
+ return date.toLocaleDateString("en-US", {
80
+ year: "numeric",
81
+ month: "long"
82
+ });
83
+ }
84
+ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, replyCounts }) {
85
+ const { t } = useLingui();
86
+ const title = type ? getTypeLabelPlural(type) : t({
87
+ message: "Archive",
88
+ comment: "@context: Archive page title"
89
+ });
90
+ return /*#__PURE__*/ _jsxs("div", {
91
+ class: "container py-8",
92
+ children: [
93
+ /*#__PURE__*/ _jsxs("header", {
94
+ class: "mb-8",
95
+ children: [
96
+ /*#__PURE__*/ _jsx("h1", {
97
+ class: "text-2xl font-semibold",
98
+ children: title
99
+ }),
100
+ /*#__PURE__*/ _jsxs("nav", {
101
+ class: "flex flex-wrap gap-2 mt-4",
102
+ children: [
103
+ /*#__PURE__*/ _jsx("a", {
104
+ href: "/archive",
105
+ class: `badge ${!type ? "badge-primary" : "badge-outline"}`,
106
+ children: t({
107
+ message: "All",
108
+ comment: "@context: Archive filter - all types"
109
+ })
110
+ }),
111
+ POST_TYPES.filter((t)=>t !== "page").map((typeKey)=>/*#__PURE__*/ _jsx("a", {
112
+ href: `/archive?type=${typeKey}`,
113
+ class: `badge ${type === typeKey ? "badge-primary" : "badge-outline"}`,
114
+ children: getTypeLabelPlural(typeKey)
115
+ }, typeKey))
116
+ ]
117
+ })
118
+ ]
119
+ }),
120
+ /*#__PURE__*/ _jsx("main", {
121
+ children: displayPosts.length === 0 ? /*#__PURE__*/ _jsx("p", {
122
+ class: "text-muted-foreground",
123
+ children: t({
124
+ message: "No posts found.",
125
+ comment: "@context: Archive empty state"
126
+ })
127
+ }) : Array.from(grouped.entries()).map(([yearMonth, monthPosts])=>/*#__PURE__*/ _jsxs("section", {
128
+ class: "mb-8",
129
+ children: [
130
+ /*#__PURE__*/ _jsx("h2", {
131
+ class: "text-lg font-medium mb-4 text-muted-foreground",
132
+ children: formatYearMonth(yearMonth)
133
+ }),
134
+ /*#__PURE__*/ _jsx("div", {
135
+ class: "flex flex-col gap-3",
136
+ children: monthPosts.map((post)=>{
137
+ const replyCount = replyCounts.get(post.id);
138
+ return /*#__PURE__*/ _jsxs("article", {
139
+ class: "flex items-baseline gap-4",
140
+ children: [
141
+ /*#__PURE__*/ _jsx("time", {
142
+ class: "text-sm text-muted-foreground w-12 shrink-0",
143
+ datetime: time.toISOString(post.publishedAt),
144
+ children: new Date(post.publishedAt * 1000).getDate()
145
+ }),
146
+ /*#__PURE__*/ _jsxs("div", {
147
+ class: "flex-1 min-w-0",
148
+ children: [
149
+ /*#__PURE__*/ _jsx("a", {
150
+ href: `/p/${sqid.encode(post.id)}`,
151
+ class: "hover:underline",
152
+ children: post.title || post.content?.slice(0, 80) || `Post #${post.id}`
153
+ }),
154
+ !type && /*#__PURE__*/ _jsx("span", {
155
+ class: "ml-2 badge-outline text-xs",
156
+ children: getTypeLabel(post.type)
157
+ }),
158
+ replyCount && replyCount > 0 && /*#__PURE__*/ _jsxs("span", {
159
+ class: "ml-2 text-xs text-muted-foreground",
160
+ children: [
161
+ "(",
162
+ replyCount === 1 ? t({
163
+ message: "1 reply",
164
+ comment: "@context: Archive post reply indicator - single"
165
+ }) : t({
166
+ message: "{count} replies",
167
+ comment: "@context: Archive post reply indicator - plural",
168
+ values: {
169
+ count: String(replyCount)
170
+ }
171
+ }),
172
+ ")"
173
+ ]
174
+ })
175
+ ]
176
+ })
177
+ ]
178
+ }, post.id);
179
+ })
180
+ })
181
+ ]
182
+ }, yearMonth))
183
+ }),
184
+ /*#__PURE__*/ _jsx(Pagination, {
185
+ baseUrl: type ? `/archive?type=${type}` : "/archive",
186
+ hasMore: hasMore,
187
+ nextCursor: nextCursor
188
+ }),
189
+ /*#__PURE__*/ _jsx("nav", {
190
+ class: "mt-4",
191
+ children: /*#__PURE__*/ _jsxs("a", {
192
+ href: "/",
193
+ class: "text-sm hover:underline",
194
+ children: [
195
+ "← ",
196
+ t({
197
+ message: "Back to home",
198
+ comment: "@context: Navigation link back to home page"
199
+ })
200
+ ]
201
+ })
202
+ })
203
+ ]
204
+ });
205
+ }
206
+ // Archive page - all posts
207
+ archiveRoutes.get("/", async (c)=>{
208
+ const typeParam = c.req.query("type");
209
+ const type = typeParam && POST_TYPES.includes(typeParam) ? typeParam : undefined;
210
+ // Parse cursor
211
+ const cursorParam = c.req.query("cursor");
212
+ const cursor = cursorParam ? parseInt(cursorParam, 10) : undefined;
213
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
214
+ // Fetch one extra to check for more
215
+ const posts = await c.var.services.posts.list({
216
+ type,
217
+ visibility: [
218
+ "featured",
219
+ "quiet"
220
+ ],
221
+ excludeReplies: true,
222
+ cursor,
223
+ limit: PAGE_SIZE + 1
224
+ });
225
+ const hasMore = posts.length > PAGE_SIZE;
226
+ const displayPosts = hasMore ? posts.slice(0, PAGE_SIZE) : posts;
227
+ // Get reply counts for thread indicators
228
+ const postIds = displayPosts.map((p)=>p.id);
229
+ const replyCounts = await c.var.services.posts.getReplyCounts(postIds);
230
+ // Get next cursor
231
+ const nextCursor = hasMore && displayPosts.length > 0 ? displayPosts[displayPosts.length - 1].id : undefined;
232
+ // Group posts by year-month
233
+ const grouped = new Map();
234
+ for (const post of displayPosts){
235
+ const date = new Date(post.publishedAt * 1000);
236
+ const key = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
237
+ if (!grouped.has(key)) {
238
+ grouped.set(key, []);
239
+ }
240
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Map.set() above guarantees key exists
241
+ grouped.get(key).push(post);
242
+ }
243
+ return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
244
+ title: `Archive - ${siteName}`,
245
+ c: c,
246
+ children: /*#__PURE__*/ _jsx(ArchiveContent, {
247
+ displayPosts: displayPosts,
248
+ hasMore: hasMore,
249
+ nextCursor: nextCursor,
250
+ type: type,
251
+ grouped: grouped,
252
+ replyCounts: replyCounts
253
+ })
254
+ }));
255
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Collection Page Route
3
+ */
4
+ import { Hono } from "hono";
5
+ import type { Bindings } from "../../types.js";
6
+ import type { AppVariables } from "../../app.js";
7
+ type Env = {
8
+ Bindings: Bindings;
9
+ Variables: AppVariables;
10
+ };
11
+ export declare const collectionRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
12
+ export {};
13
+ //# sourceMappingURL=collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/collection.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,gBAAgB,kDAAkB,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
+ /**
3
+ * Collection Page Route
4
+ */ import { Hono } from "hono";
5
+ import { useLingui } from "../../i18n/index.js";
6
+ import { BaseLayout } from "../../theme/layouts/index.js";
7
+ import * as sqid from "../../lib/sqid.js";
8
+ import * as time from "../../lib/time.js";
9
+ export const collectionRoutes = new Hono();
10
+ function CollectionContent({ collection, posts }) {
11
+ const { t } = useLingui();
12
+ return /*#__PURE__*/ _jsxs("div", {
13
+ class: "container py-8",
14
+ children: [
15
+ /*#__PURE__*/ _jsxs("header", {
16
+ class: "mb-8",
17
+ children: [
18
+ /*#__PURE__*/ _jsx("h1", {
19
+ class: "text-2xl font-semibold",
20
+ children: collection.title
21
+ }),
22
+ collection.description && /*#__PURE__*/ _jsx("p", {
23
+ class: "text-muted-foreground mt-2",
24
+ children: collection.description
25
+ })
26
+ ]
27
+ }),
28
+ /*#__PURE__*/ _jsx("main", {
29
+ class: "flex flex-col gap-6",
30
+ children: posts.length === 0 ? /*#__PURE__*/ _jsx("p", {
31
+ class: "text-muted-foreground",
32
+ children: t({
33
+ message: "No posts in this collection.",
34
+ comment: "@context: Empty state message"
35
+ })
36
+ }) : posts.map((post)=>/*#__PURE__*/ _jsxs("article", {
37
+ class: "h-entry",
38
+ children: [
39
+ post.title && /*#__PURE__*/ _jsx("h2", {
40
+ class: "p-name text-lg font-medium mb-2",
41
+ children: /*#__PURE__*/ _jsx("a", {
42
+ href: `/p/${sqid.encode(post.id)}`,
43
+ class: "u-url hover:underline",
44
+ children: post.title
45
+ })
46
+ }),
47
+ /*#__PURE__*/ _jsx("div", {
48
+ class: "e-content prose prose-sm",
49
+ dangerouslySetInnerHTML: {
50
+ __html: post.contentHtml || ""
51
+ }
52
+ }),
53
+ /*#__PURE__*/ _jsx("footer", {
54
+ class: "mt-2 text-sm text-muted-foreground",
55
+ children: /*#__PURE__*/ _jsx("time", {
56
+ class: "dt-published",
57
+ datetime: time.toISOString(post.publishedAt),
58
+ children: time.formatDate(post.publishedAt)
59
+ })
60
+ })
61
+ ]
62
+ }, post.id))
63
+ }),
64
+ /*#__PURE__*/ _jsx("nav", {
65
+ class: "mt-8",
66
+ children: /*#__PURE__*/ _jsx("a", {
67
+ href: "/",
68
+ class: "text-sm hover:underline",
69
+ children: t({
70
+ message: "← Back to home",
71
+ comment: "@context: Navigation link"
72
+ })
73
+ })
74
+ })
75
+ ]
76
+ });
77
+ }
78
+ collectionRoutes.get("/:path", async (c)=>{
79
+ const path = c.req.param("path");
80
+ const collection = await c.var.services.collections.getByPath(path);
81
+ if (!collection) return c.notFound();
82
+ const posts = await c.var.services.collections.getPosts(collection.id);
83
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
84
+ return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
85
+ title: `${collection.title} - ${siteName}`,
86
+ description: collection.description ?? undefined,
87
+ c: c,
88
+ children: /*#__PURE__*/ _jsx(CollectionContent, {
89
+ collection: collection,
90
+ posts: posts
91
+ })
92
+ }));
93
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Home Page Route
3
+ */
4
+ import { Hono } from "hono";
5
+ import type { Bindings } from "../../types.js";
6
+ import type { AppVariables } from "../../app.js";
7
+ type Env = {
8
+ Bindings: Bindings;
9
+ Variables: AppVariables;
10
+ };
11
+ export declare const homeRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
12
+ export {};
13
+ //# sourceMappingURL=home.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/home.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,UAAU,kDAAkB,CAAC"}
@@ -0,0 +1,122 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
+ /**
3
+ * Home Page Route
4
+ */ import { Hono } from "hono";
5
+ import { useLingui } from "../../i18n/index.js";
6
+ import { BaseLayout } from "../../theme/layouts/index.js";
7
+ import * as sqid from "../../lib/sqid.js";
8
+ import * as time from "../../lib/time.js";
9
+ export const homeRoutes = new Hono();
10
+ function HomeContent({ siteName, posts }) {
11
+ const { t } = useLingui();
12
+ return /*#__PURE__*/ _jsxs("div", {
13
+ class: "container py-8",
14
+ children: [
15
+ /*#__PURE__*/ _jsxs("header", {
16
+ class: "mb-8 flex items-center justify-between",
17
+ children: [
18
+ /*#__PURE__*/ _jsx("h1", {
19
+ class: "text-2xl font-semibold",
20
+ children: siteName
21
+ }),
22
+ /*#__PURE__*/ _jsxs("nav", {
23
+ class: "flex items-center gap-4 text-sm",
24
+ children: [
25
+ /*#__PURE__*/ _jsx("a", {
26
+ href: "/archive",
27
+ class: "text-muted-foreground hover:text-foreground",
28
+ children: t({
29
+ message: "Archive",
30
+ comment: "@context: Navigation link to archive page"
31
+ })
32
+ }),
33
+ /*#__PURE__*/ _jsx("a", {
34
+ href: "/feed",
35
+ class: "text-muted-foreground hover:text-foreground",
36
+ children: "RSS"
37
+ })
38
+ ]
39
+ })
40
+ ]
41
+ }),
42
+ /*#__PURE__*/ _jsx("main", {
43
+ class: "flex flex-col gap-6",
44
+ children: posts.length === 0 ? /*#__PURE__*/ _jsx("p", {
45
+ class: "text-muted-foreground",
46
+ children: t({
47
+ message: "No posts yet.",
48
+ comment: "@context: Empty state message on home page"
49
+ })
50
+ }) : posts.map((post)=>/*#__PURE__*/ _jsxs("article", {
51
+ class: "h-entry",
52
+ children: [
53
+ post.title && /*#__PURE__*/ _jsx("h2", {
54
+ class: "p-name text-lg font-medium mb-2",
55
+ children: /*#__PURE__*/ _jsx("a", {
56
+ href: `/p/${sqid.encode(post.id)}`,
57
+ class: "u-url hover:underline",
58
+ children: post.title
59
+ })
60
+ }),
61
+ /*#__PURE__*/ _jsx("div", {
62
+ class: "e-content prose prose-sm",
63
+ dangerouslySetInnerHTML: {
64
+ __html: post.contentHtml || ""
65
+ }
66
+ }),
67
+ /*#__PURE__*/ _jsxs("footer", {
68
+ class: "mt-2 text-sm text-muted-foreground",
69
+ children: [
70
+ /*#__PURE__*/ _jsx("time", {
71
+ class: "dt-published",
72
+ datetime: time.toISOString(post.publishedAt),
73
+ children: time.formatDate(post.publishedAt)
74
+ }),
75
+ post.visibility === "featured" && /*#__PURE__*/ _jsx("span", {
76
+ class: "ml-2 text-xs",
77
+ children: t({
78
+ message: "Featured",
79
+ comment: "@context: Post visibility badge"
80
+ })
81
+ })
82
+ ]
83
+ })
84
+ ]
85
+ }, post.id))
86
+ }),
87
+ posts.length >= 20 && /*#__PURE__*/ _jsx("nav", {
88
+ class: "mt-8 text-center",
89
+ children: /*#__PURE__*/ _jsx("a", {
90
+ href: "/archive",
91
+ class: "text-sm text-muted-foreground hover:text-foreground",
92
+ children: t({
93
+ message: "View all posts →",
94
+ comment: "@context: Link to view all posts on archive page"
95
+ })
96
+ })
97
+ })
98
+ ]
99
+ });
100
+ }
101
+ homeRoutes.get("/", async (c)=>{
102
+ const isComplete = await c.var.services.settings.isOnboardingComplete();
103
+ if (!isComplete) {
104
+ return c.redirect("/setup");
105
+ }
106
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
107
+ const posts = await c.var.services.posts.list({
108
+ visibility: [
109
+ "featured",
110
+ "quiet"
111
+ ],
112
+ limit: 20
113
+ });
114
+ return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
115
+ title: siteName,
116
+ c: c,
117
+ children: /*#__PURE__*/ _jsx(HomeContent, {
118
+ siteName: siteName,
119
+ posts: posts
120
+ })
121
+ }));
122
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Custom Page Route
3
+ *
4
+ * Catch-all route for custom pages accessible via their path field
5
+ */
6
+ import { Hono } from "hono";
7
+ import type { Bindings } from "../../types.js";
8
+ import type { AppVariables } from "../../app.js";
9
+ type Env = {
10
+ Bindings: Bindings;
11
+ Variables: AppVariables;
12
+ };
13
+ export declare const pageRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
14
+ export {};
15
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/page.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,UAAU,kDAAkB,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
+ /**
3
+ * Custom Page Route
4
+ *
5
+ * Catch-all route for custom pages accessible via their path field
6
+ */ import { Hono } from "hono";
7
+ import { useLingui } from "../../i18n/index.js";
8
+ import { BaseLayout } from "../../theme/layouts/index.js";
9
+ export const pageRoutes = new Hono();
10
+ function PageContent({ page }) {
11
+ const { t } = useLingui();
12
+ return /*#__PURE__*/ _jsxs("div", {
13
+ class: "container py-8 max-w-2xl",
14
+ children: [
15
+ /*#__PURE__*/ _jsxs("article", {
16
+ class: "h-entry",
17
+ children: [
18
+ page.title && /*#__PURE__*/ _jsx("h1", {
19
+ class: "p-name text-3xl font-semibold mb-6",
20
+ children: page.title
21
+ }),
22
+ /*#__PURE__*/ _jsx("div", {
23
+ class: "e-content prose",
24
+ dangerouslySetInnerHTML: {
25
+ __html: page.contentHtml || ""
26
+ }
27
+ })
28
+ ]
29
+ }),
30
+ /*#__PURE__*/ _jsx("nav", {
31
+ class: "mt-8 pt-6 border-t",
32
+ children: /*#__PURE__*/ _jsxs("a", {
33
+ href: "/",
34
+ class: "text-sm hover:underline",
35
+ children: [
36
+ "← ",
37
+ t({
38
+ message: "Back to home",
39
+ comment: "@context: Navigation link back to home page"
40
+ })
41
+ ]
42
+ })
43
+ })
44
+ ]
45
+ });
46
+ }
47
+ // Catch-all for custom page paths
48
+ pageRoutes.get("/:path", async (c)=>{
49
+ const path = c.req.param("path");
50
+ // Look up page by path
51
+ const page = await c.var.services.posts.getByPath(path);
52
+ // Not found or not a page
53
+ if (!page || page.type !== "page") {
54
+ return c.notFound();
55
+ }
56
+ // Don't show drafts
57
+ if (page.visibility === "draft") {
58
+ return c.notFound();
59
+ }
60
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
61
+ return c.html(/*#__PURE__*/ _jsx(BaseLayout, {
62
+ title: `${page.title} - ${siteName}`,
63
+ description: page.content?.slice(0, 160),
64
+ c: c,
65
+ children: /*#__PURE__*/ _jsx(PageContent, {
66
+ page: page
67
+ })
68
+ }));
69
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Single Post Page Route
3
+ */
4
+ import { Hono } from "hono";
5
+ import type { Bindings } from "../../types.js";
6
+ import type { AppVariables } from "../../app.js";
7
+ type Env = {
8
+ Bindings: Bindings;
9
+ Variables: AppVariables;
10
+ };
11
+ export declare const postRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
12
+ export {};
13
+ //# sourceMappingURL=post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/post.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,UAAU,kDAAkB,CAAC"}