@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,237 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
2
+ /**
3
+ * Dashboard Redirects Routes
4
+ */ import { Hono } from "hono";
5
+ import { useLingui } from "../../i18n/index.js";
6
+ import { DashLayout } from "../../theme/layouts/index.js";
7
+ import { EmptyState, ListItemRow, ActionButtons, CrudPageHeader } from "../../theme/components/index.js";
8
+ export const redirectsRoutes = new Hono();
9
+ function RedirectsListContent({ redirects }) {
10
+ const { t } = useLingui();
11
+ return /*#__PURE__*/ _jsxs(_Fragment, {
12
+ children: [
13
+ /*#__PURE__*/ _jsx(CrudPageHeader, {
14
+ title: t({
15
+ message: "Redirects",
16
+ comment: "@context: Dashboard heading"
17
+ }),
18
+ ctaLabel: t({
19
+ message: "New Redirect",
20
+ comment: "@context: Button to create new redirect"
21
+ }),
22
+ ctaHref: "/dash/redirects/new"
23
+ }),
24
+ redirects.length === 0 ? /*#__PURE__*/ _jsx(EmptyState, {
25
+ message: t({
26
+ message: "No redirects configured.",
27
+ comment: "@context: Empty state message"
28
+ }),
29
+ ctaText: t({
30
+ message: "New Redirect",
31
+ comment: "@context: Button to create new redirect"
32
+ }),
33
+ ctaHref: "/dash/redirects/new"
34
+ }) : /*#__PURE__*/ _jsx("div", {
35
+ class: "flex flex-col divide-y",
36
+ children: redirects.map((r)=>/*#__PURE__*/ _jsx(ListItemRow, {
37
+ actions: /*#__PURE__*/ _jsx(ActionButtons, {
38
+ deleteAction: `/dash/redirects/${r.id}/delete`,
39
+ deleteLabel: t({
40
+ message: "Delete",
41
+ comment: "@context: Button to delete redirect"
42
+ })
43
+ }),
44
+ children: /*#__PURE__*/ _jsxs("div", {
45
+ class: "flex items-center gap-2",
46
+ children: [
47
+ /*#__PURE__*/ _jsx("code", {
48
+ class: "text-sm bg-muted px-1 rounded",
49
+ children: r.fromPath
50
+ }),
51
+ /*#__PURE__*/ _jsx("span", {
52
+ class: "text-muted-foreground",
53
+ children: "→"
54
+ }),
55
+ /*#__PURE__*/ _jsx("code", {
56
+ class: "text-sm bg-muted px-1 rounded",
57
+ children: r.toPath
58
+ }),
59
+ /*#__PURE__*/ _jsx("span", {
60
+ class: "badge-outline",
61
+ children: r.type
62
+ })
63
+ ]
64
+ })
65
+ }, r.id))
66
+ })
67
+ ]
68
+ });
69
+ }
70
+ function NewRedirectContent() {
71
+ const { t } = useLingui();
72
+ return /*#__PURE__*/ _jsxs(_Fragment, {
73
+ children: [
74
+ /*#__PURE__*/ _jsx("h1", {
75
+ class: "text-2xl font-semibold mb-6",
76
+ children: t({
77
+ message: "New Redirect",
78
+ comment: "@context: Page heading"
79
+ })
80
+ }),
81
+ /*#__PURE__*/ _jsxs("form", {
82
+ method: "post",
83
+ action: "/dash/redirects",
84
+ class: "flex flex-col gap-4 max-w-lg",
85
+ children: [
86
+ /*#__PURE__*/ _jsxs("div", {
87
+ class: "field",
88
+ children: [
89
+ /*#__PURE__*/ _jsx("label", {
90
+ class: "label",
91
+ children: t({
92
+ message: "From Path",
93
+ comment: "@context: Redirect form field"
94
+ })
95
+ }),
96
+ /*#__PURE__*/ _jsx("input", {
97
+ type: "text",
98
+ name: "fromPath",
99
+ class: "input",
100
+ placeholder: "/old-path",
101
+ required: true
102
+ }),
103
+ /*#__PURE__*/ _jsx("p", {
104
+ class: "text-xs text-muted-foreground mt-1",
105
+ children: t({
106
+ message: "The path to redirect from",
107
+ comment: "@context: Redirect from path help text"
108
+ })
109
+ })
110
+ ]
111
+ }),
112
+ /*#__PURE__*/ _jsxs("div", {
113
+ class: "field",
114
+ children: [
115
+ /*#__PURE__*/ _jsx("label", {
116
+ class: "label",
117
+ children: t({
118
+ message: "To Path",
119
+ comment: "@context: Redirect form field"
120
+ })
121
+ }),
122
+ /*#__PURE__*/ _jsx("input", {
123
+ type: "text",
124
+ name: "toPath",
125
+ class: "input",
126
+ placeholder: "/new-path or https://...",
127
+ required: true
128
+ }),
129
+ /*#__PURE__*/ _jsx("p", {
130
+ class: "text-xs text-muted-foreground mt-1",
131
+ children: t({
132
+ message: "The destination path or URL",
133
+ comment: "@context: Redirect to path help text"
134
+ })
135
+ })
136
+ ]
137
+ }),
138
+ /*#__PURE__*/ _jsxs("div", {
139
+ class: "field",
140
+ children: [
141
+ /*#__PURE__*/ _jsx("label", {
142
+ class: "label",
143
+ children: t({
144
+ message: "Type",
145
+ comment: "@context: Redirect form field"
146
+ })
147
+ }),
148
+ /*#__PURE__*/ _jsxs("select", {
149
+ name: "type",
150
+ class: "select",
151
+ children: [
152
+ /*#__PURE__*/ _jsx("option", {
153
+ value: "301",
154
+ children: t({
155
+ message: "301 (Permanent)",
156
+ comment: "@context: Redirect type option"
157
+ })
158
+ }),
159
+ /*#__PURE__*/ _jsx("option", {
160
+ value: "302",
161
+ children: t({
162
+ message: "302 (Temporary)",
163
+ comment: "@context: Redirect type option"
164
+ })
165
+ })
166
+ ]
167
+ })
168
+ ]
169
+ }),
170
+ /*#__PURE__*/ _jsxs("div", {
171
+ class: "flex gap-2",
172
+ children: [
173
+ /*#__PURE__*/ _jsx("button", {
174
+ type: "submit",
175
+ class: "btn",
176
+ children: t({
177
+ message: "Create Redirect",
178
+ comment: "@context: Button to save new redirect"
179
+ })
180
+ }),
181
+ /*#__PURE__*/ _jsx("a", {
182
+ href: "/dash/redirects",
183
+ class: "btn-outline",
184
+ children: t({
185
+ message: "Cancel",
186
+ comment: "@context: Button to cancel form"
187
+ })
188
+ })
189
+ ]
190
+ })
191
+ ]
192
+ })
193
+ ]
194
+ });
195
+ }
196
+ // List redirects
197
+ redirectsRoutes.get("/", async (c)=>{
198
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
199
+ const redirects = await c.var.services.redirects.list();
200
+ return c.html(/*#__PURE__*/ _jsx(DashLayout, {
201
+ c: c,
202
+ title: "Redirects",
203
+ siteName: siteName,
204
+ currentPath: "/dash/redirects",
205
+ children: /*#__PURE__*/ _jsx(RedirectsListContent, {
206
+ redirects: redirects
207
+ })
208
+ }));
209
+ });
210
+ // New redirect form
211
+ redirectsRoutes.get("/new", async (c)=>{
212
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
213
+ return c.html(/*#__PURE__*/ _jsx(DashLayout, {
214
+ c: c,
215
+ title: "New Redirect",
216
+ siteName: siteName,
217
+ currentPath: "/dash/redirects",
218
+ children: /*#__PURE__*/ _jsx(NewRedirectContent, {})
219
+ }));
220
+ });
221
+ // Create redirect
222
+ redirectsRoutes.post("/", async (c)=>{
223
+ const formData = await c.req.formData();
224
+ const fromPath = formData.get("fromPath");
225
+ const toPath = formData.get("toPath");
226
+ const type = parseInt(formData.get("type"), 10);
227
+ await c.var.services.redirects.create(fromPath, toPath, type);
228
+ return c.redirect("/dash/redirects");
229
+ });
230
+ // Delete redirect
231
+ redirectsRoutes.post("/:id/delete", async (c)=>{
232
+ const id = parseInt(c.req.param("id"), 10);
233
+ if (!isNaN(id)) {
234
+ await c.var.services.redirects.delete(id);
235
+ }
236
+ return c.redirect("/dash/redirects");
237
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Dashboard Settings Routes
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 settingsRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
12
+ export {};
13
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/settings.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,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,cAAc,kDAAkB,CAAC"}
@@ -0,0 +1,154 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
2
+ /**
3
+ * Dashboard Settings Routes
4
+ */ import { Hono } from "hono";
5
+ import { useLingui } from "../../i18n/index.js";
6
+ import { DashLayout } from "../../theme/layouts/index.js";
7
+ export const settingsRoutes = new Hono();
8
+ function SettingsContent({ siteName, siteDescription, siteLanguage }) {
9
+ const { t } = useLingui();
10
+ return /*#__PURE__*/ _jsxs(_Fragment, {
11
+ children: [
12
+ /*#__PURE__*/ _jsx("h1", {
13
+ class: "text-2xl font-semibold mb-6",
14
+ children: t({
15
+ message: "Settings",
16
+ comment: "@context: Dashboard heading"
17
+ })
18
+ }),
19
+ /*#__PURE__*/ _jsxs("form", {
20
+ method: "post",
21
+ action: "/dash/settings",
22
+ class: "flex flex-col gap-6 max-w-lg",
23
+ children: [
24
+ /*#__PURE__*/ _jsxs("div", {
25
+ class: "card",
26
+ children: [
27
+ /*#__PURE__*/ _jsx("header", {
28
+ children: /*#__PURE__*/ _jsx("h2", {
29
+ children: t({
30
+ message: "General",
31
+ comment: "@context: Settings section heading"
32
+ })
33
+ })
34
+ }),
35
+ /*#__PURE__*/ _jsxs("section", {
36
+ class: "flex flex-col gap-4",
37
+ children: [
38
+ /*#__PURE__*/ _jsxs("div", {
39
+ class: "field",
40
+ children: [
41
+ /*#__PURE__*/ _jsx("label", {
42
+ class: "label",
43
+ children: t({
44
+ message: "Site Name",
45
+ comment: "@context: Settings form field"
46
+ })
47
+ }),
48
+ /*#__PURE__*/ _jsx("input", {
49
+ type: "text",
50
+ name: "siteName",
51
+ class: "input",
52
+ value: siteName,
53
+ required: true
54
+ })
55
+ ]
56
+ }),
57
+ /*#__PURE__*/ _jsxs("div", {
58
+ class: "field",
59
+ children: [
60
+ /*#__PURE__*/ _jsx("label", {
61
+ class: "label",
62
+ children: t({
63
+ message: "Site Description",
64
+ comment: "@context: Settings form field"
65
+ })
66
+ }),
67
+ /*#__PURE__*/ _jsx("textarea", {
68
+ name: "siteDescription",
69
+ class: "textarea",
70
+ rows: 3,
71
+ children: siteDescription
72
+ })
73
+ ]
74
+ }),
75
+ /*#__PURE__*/ _jsxs("div", {
76
+ class: "field",
77
+ children: [
78
+ /*#__PURE__*/ _jsx("label", {
79
+ class: "label",
80
+ children: t({
81
+ message: "Language",
82
+ comment: "@context: Settings form field"
83
+ })
84
+ }),
85
+ /*#__PURE__*/ _jsxs("select", {
86
+ name: "siteLanguage",
87
+ class: "select",
88
+ children: [
89
+ /*#__PURE__*/ _jsx("option", {
90
+ value: "en",
91
+ selected: siteLanguage === "en",
92
+ children: "English"
93
+ }),
94
+ /*#__PURE__*/ _jsx("option", {
95
+ value: "zh-Hans",
96
+ selected: siteLanguage === "zh-Hans",
97
+ children: "简体中文"
98
+ }),
99
+ /*#__PURE__*/ _jsx("option", {
100
+ value: "zh-Hant",
101
+ selected: siteLanguage === "zh-Hant",
102
+ children: "繁體中文"
103
+ })
104
+ ]
105
+ })
106
+ ]
107
+ })
108
+ ]
109
+ })
110
+ ]
111
+ }),
112
+ /*#__PURE__*/ _jsx("button", {
113
+ type: "submit",
114
+ class: "btn",
115
+ children: t({
116
+ message: "Save Settings",
117
+ comment: "@context: Button to save settings"
118
+ })
119
+ })
120
+ ]
121
+ })
122
+ ]
123
+ });
124
+ }
125
+ // Settings page
126
+ settingsRoutes.get("/", async (c)=>{
127
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
128
+ const siteDescription = await c.var.services.settings.get("SITE_DESCRIPTION") ?? "";
129
+ const siteLanguage = await c.var.services.settings.get("SITE_LANGUAGE") ?? "en";
130
+ return c.html(/*#__PURE__*/ _jsx(DashLayout, {
131
+ c: c,
132
+ title: "Settings",
133
+ siteName: siteName,
134
+ currentPath: "/dash/settings",
135
+ children: /*#__PURE__*/ _jsx(SettingsContent, {
136
+ siteName: siteName,
137
+ siteDescription: siteDescription,
138
+ siteLanguage: siteLanguage
139
+ })
140
+ }));
141
+ });
142
+ // Update settings
143
+ settingsRoutes.post("/", async (c)=>{
144
+ const formData = await c.req.formData();
145
+ const siteName = formData.get("siteName");
146
+ const siteDescription = formData.get("siteDescription");
147
+ const siteLanguage = formData.get("siteLanguage");
148
+ await c.var.services.settings.setMany({
149
+ SITE_NAME: siteName,
150
+ SITE_DESCRIPTION: siteDescription,
151
+ SITE_LANGUAGE: siteLanguage
152
+ });
153
+ return c.redirect("/dash/settings?saved=1");
154
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * RSS Feed Routes
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 rssRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
12
+ export {};
13
+ //# sourceMappingURL=rss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rss.d.ts","sourceRoot":"","sources":["../../../src/routes/feed/rss.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,SAAS,kDAAkB,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * RSS Feed Routes
3
+ */ import { Hono } from "hono";
4
+ import * as sqid from "../../lib/sqid.js";
5
+ import * as time from "../../lib/time.js";
6
+ export const rssRoutes = new Hono();
7
+ // RSS 2.0 Feed - main feed at /feed
8
+ rssRoutes.get("/", async (c)=>{
9
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
10
+ const siteDescription = await c.var.services.settings.get("SITE_DESCRIPTION") ?? "";
11
+ const siteUrl = c.env.SITE_URL;
12
+ const posts = await c.var.services.posts.list({
13
+ visibility: [
14
+ "featured",
15
+ "quiet"
16
+ ],
17
+ limit: 50
18
+ });
19
+ const items = posts.map((post)=>{
20
+ const link = `${siteUrl}/p/${sqid.encode(post.id)}`;
21
+ const title = post.title || `Post #${post.id}`;
22
+ const pubDate = new Date(post.publishedAt * 1000).toUTCString();
23
+ return `
24
+ <item>
25
+ <title><![CDATA[${escapeXml(title)}]]></title>
26
+ <link>${link}</link>
27
+ <guid isPermaLink="true">${link}</guid>
28
+ <pubDate>${pubDate}</pubDate>
29
+ <description><![CDATA[${post.contentHtml || ""}]]></description>
30
+ </item>`;
31
+ }).join("");
32
+ const rss = `<?xml version="1.0" encoding="UTF-8"?>
33
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
34
+ <channel>
35
+ <title>${escapeXml(siteName)}</title>
36
+ <link>${siteUrl}</link>
37
+ <description>${escapeXml(siteDescription)}</description>
38
+ <language>en</language>
39
+ <atom:link href="${siteUrl}/feed" rel="self" type="application/rss+xml"/>
40
+ ${items}
41
+ </channel>
42
+ </rss>`;
43
+ return new Response(rss, {
44
+ headers: {
45
+ "Content-Type": "application/rss+xml; charset=utf-8"
46
+ }
47
+ });
48
+ });
49
+ // Atom Feed
50
+ rssRoutes.get("/atom.xml", async (c)=>{
51
+ const siteName = await c.var.services.settings.get("SITE_NAME") ?? "Jant";
52
+ const siteDescription = await c.var.services.settings.get("SITE_DESCRIPTION") ?? "";
53
+ const siteUrl = c.env.SITE_URL;
54
+ const posts = await c.var.services.posts.list({
55
+ visibility: [
56
+ "featured",
57
+ "quiet"
58
+ ],
59
+ limit: 50
60
+ });
61
+ const entries = posts.map((post)=>{
62
+ const link = `${siteUrl}/p/${sqid.encode(post.id)}`;
63
+ const title = post.title || `Post #${post.id}`;
64
+ const updated = time.toISOString(post.updatedAt);
65
+ const published = time.toISOString(post.publishedAt);
66
+ return `
67
+ <entry>
68
+ <title>${escapeXml(title)}</title>
69
+ <link href="${link}" rel="alternate"/>
70
+ <id>${link}</id>
71
+ <published>${published}</published>
72
+ <updated>${updated}</updated>
73
+ <content type="html"><![CDATA[${post.contentHtml || ""}]]></content>
74
+ </entry>`;
75
+ }).join("");
76
+ const now = time.toISOString(time.now());
77
+ const atom = `<?xml version="1.0" encoding="UTF-8"?>
78
+ <feed xmlns="http://www.w3.org/2005/Atom">
79
+ <title>${escapeXml(siteName)}</title>
80
+ <subtitle>${escapeXml(siteDescription)}</subtitle>
81
+ <link href="${siteUrl}" rel="alternate"/>
82
+ <link href="${siteUrl}/feed/atom.xml" rel="self"/>
83
+ <id>${siteUrl}/</id>
84
+ <updated>${now}</updated>
85
+ ${entries}
86
+ </feed>`;
87
+ return new Response(atom, {
88
+ headers: {
89
+ "Content-Type": "application/atom+xml; charset=utf-8"
90
+ }
91
+ });
92
+ });
93
+ function escapeXml(str) {
94
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
95
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Sitemap Routes
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 sitemapRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
12
+ export {};
13
+ //# sourceMappingURL=sitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../../src/routes/feed/sitemap.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,aAAa,kDAAkB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Sitemap Routes
3
+ */ import { Hono } from "hono";
4
+ import * as sqid from "../../lib/sqid.js";
5
+ import * as time from "../../lib/time.js";
6
+ export const sitemapRoutes = new Hono();
7
+ // XML Sitemap
8
+ sitemapRoutes.get("/sitemap.xml", async (c)=>{
9
+ const siteUrl = c.env.SITE_URL;
10
+ const posts = await c.var.services.posts.list({
11
+ visibility: [
12
+ "featured",
13
+ "quiet"
14
+ ],
15
+ limit: 1000
16
+ });
17
+ const urls = posts.map((post)=>{
18
+ const loc = `${siteUrl}/p/${sqid.encode(post.id)}`;
19
+ const lastmod = time.toISOString(post.updatedAt).split("T")[0];
20
+ const priority = post.visibility === "featured" ? "0.8" : "0.6";
21
+ return `
22
+ <url>
23
+ <loc>${loc}</loc>
24
+ <lastmod>${lastmod}</lastmod>
25
+ <priority>${priority}</priority>
26
+ </url>`;
27
+ }).join("");
28
+ // Add homepage
29
+ const homepageUrl = `
30
+ <url>
31
+ <loc>${siteUrl}/</loc>
32
+ <priority>1.0</priority>
33
+ <changefreq>daily</changefreq>
34
+ </url>`;
35
+ const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
36
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
37
+ ${homepageUrl}
38
+ ${urls}
39
+ </urlset>`;
40
+ return new Response(sitemap, {
41
+ headers: {
42
+ "Content-Type": "application/xml; charset=utf-8"
43
+ }
44
+ });
45
+ });
46
+ // robots.txt
47
+ sitemapRoutes.get("/robots.txt", (c)=>{
48
+ const siteUrl = c.env.SITE_URL;
49
+ const robots = `User-agent: *
50
+ Allow: /
51
+
52
+ Sitemap: ${siteUrl}/sitemap.xml
53
+ `;
54
+ return new Response(robots, {
55
+ headers: {
56
+ "Content-Type": "text/plain; charset=utf-8"
57
+ }
58
+ });
59
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Archive Page Route
3
+ *
4
+ * Shows all posts, optionally filtered by type
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 archiveRoutes: Hono<Env, import("hono/types").BlankSchema, "/">;
14
+ export {};
15
+ //# sourceMappingURL=archive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/archive.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAOjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAI3D,eAAO,MAAM,aAAa,kDAAkB,CAAC"}