@jant/core 0.2.12 → 0.2.13

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 (146) hide show
  1. package/bin/jant.js +3 -1
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +112 -85
  4. package/dist/auth.d.ts +1 -0
  5. package/dist/auth.d.ts.map +1 -1
  6. package/dist/auth.js +2 -1
  7. package/dist/client.js +1 -1
  8. package/dist/db/schema.d.ts.map +1 -1
  9. package/dist/i18n/context.d.ts.map +1 -1
  10. package/dist/i18n/context.js +0 -3
  11. package/dist/i18n/detect.d.ts +0 -11
  12. package/dist/i18n/detect.d.ts.map +1 -1
  13. package/dist/i18n/detect.js +1 -52
  14. package/dist/i18n/i18n.d.ts +4 -14
  15. package/dist/i18n/i18n.d.ts.map +1 -1
  16. package/dist/i18n/i18n.js +19 -25
  17. package/dist/i18n/index.d.ts +1 -1
  18. package/dist/i18n/index.d.ts.map +1 -1
  19. package/dist/i18n/index.js +1 -1
  20. package/dist/i18n/middleware.d.ts +2 -5
  21. package/dist/i18n/middleware.d.ts.map +1 -1
  22. package/dist/i18n/middleware.js +12 -23
  23. package/dist/lib/constants.d.ts.map +1 -1
  24. package/dist/lib/image.d.ts.map +1 -1
  25. package/dist/lib/schemas.d.ts.map +1 -1
  26. package/dist/lib/sse.d.ts +45 -17
  27. package/dist/lib/sse.d.ts.map +1 -1
  28. package/dist/lib/sse.js +77 -37
  29. package/dist/middleware/auth.d.ts.map +1 -1
  30. package/dist/routes/api/posts.js +0 -1
  31. package/dist/routes/api/upload.js +3 -1
  32. package/dist/routes/dash/collections.d.ts.map +1 -1
  33. package/dist/routes/dash/collections.js +134 -142
  34. package/dist/routes/dash/index.js +25 -26
  35. package/dist/routes/dash/media.d.ts.map +1 -1
  36. package/dist/routes/dash/media.js +60 -56
  37. package/dist/routes/dash/pages.js +64 -66
  38. package/dist/routes/dash/posts.d.ts.map +1 -1
  39. package/dist/routes/dash/posts.js +50 -59
  40. package/dist/routes/dash/redirects.d.ts.map +1 -1
  41. package/dist/routes/dash/redirects.js +63 -60
  42. package/dist/routes/dash/settings.d.ts.map +1 -1
  43. package/dist/routes/dash/settings.js +249 -93
  44. package/dist/routes/feed/rss.js +6 -4
  45. package/dist/routes/pages/archive.js +60 -62
  46. package/dist/routes/pages/collection.js +8 -8
  47. package/dist/routes/pages/home.js +14 -14
  48. package/dist/routes/pages/page.js +7 -6
  49. package/dist/routes/pages/post.js +8 -8
  50. package/dist/routes/pages/search.js +25 -27
  51. package/dist/services/collection.d.ts.map +1 -1
  52. package/dist/services/index.d.ts.map +1 -1
  53. package/dist/services/media.d.ts.map +1 -1
  54. package/dist/services/post.d.ts.map +1 -1
  55. package/dist/services/redirect.d.ts.map +1 -1
  56. package/dist/services/settings.d.ts.map +1 -1
  57. package/dist/theme/components/ActionButtons.d.ts +1 -1
  58. package/dist/theme/components/ActionButtons.d.ts.map +1 -1
  59. package/dist/theme/components/ActionButtons.js +17 -21
  60. package/dist/theme/components/CrudPageHeader.d.ts.map +1 -1
  61. package/dist/theme/components/DangerZone.d.ts.map +1 -1
  62. package/dist/theme/components/DangerZone.js +12 -15
  63. package/dist/theme/components/EmptyState.d.ts.map +1 -1
  64. package/dist/theme/components/PageForm.d.ts.map +1 -1
  65. package/dist/theme/components/PageForm.js +58 -56
  66. package/dist/theme/components/Pagination.d.ts.map +1 -1
  67. package/dist/theme/components/Pagination.js +22 -25
  68. package/dist/theme/components/PostForm.d.ts +0 -1
  69. package/dist/theme/components/PostForm.d.ts.map +1 -1
  70. package/dist/theme/components/PostForm.js +85 -77
  71. package/dist/theme/components/PostList.d.ts.map +1 -1
  72. package/dist/theme/components/PostList.js +17 -17
  73. package/dist/theme/components/ThreadView.d.ts.map +1 -1
  74. package/dist/theme/components/ThreadView.js +15 -18
  75. package/dist/theme/components/TypeBadge.d.ts.map +1 -1
  76. package/dist/theme/components/TypeBadge.js +20 -20
  77. package/dist/theme/components/VisibilityBadge.d.ts.map +1 -1
  78. package/dist/theme/components/VisibilityBadge.js +14 -14
  79. package/dist/theme/components/index.d.ts +1 -1
  80. package/dist/theme/components/index.d.ts.map +1 -1
  81. package/dist/theme/layouts/BaseLayout.d.ts.map +1 -1
  82. package/dist/theme/layouts/BaseLayout.js +4 -2
  83. package/dist/theme/layouts/DashLayout.d.ts.map +1 -1
  84. package/dist/theme/layouts/DashLayout.js +29 -29
  85. package/dist/types/lingui-react-macro.d.js +9 -0
  86. package/dist/types.d.ts +2 -0
  87. package/dist/types.d.ts.map +1 -1
  88. package/dist/vendor/datastar.js +1606 -0
  89. package/package.json +5 -2
  90. package/src/app.tsx +175 -56
  91. package/src/auth.ts +5 -1
  92. package/src/client.ts +1 -1
  93. package/src/db/schema.ts +22 -7
  94. package/src/i18n/EXAMPLES.md +34 -14
  95. package/src/i18n/README.md +19 -9
  96. package/src/i18n/context.tsx +1 -4
  97. package/src/i18n/detect.ts +1 -67
  98. package/src/i18n/i18n.ts +15 -19
  99. package/src/i18n/index.ts +0 -3
  100. package/src/i18n/middleware.ts +12 -24
  101. package/src/lib/constants.ts +2 -1
  102. package/src/lib/image-processor.ts +23 -7
  103. package/src/lib/image.ts +6 -2
  104. package/src/lib/schemas.ts +6 -2
  105. package/src/lib/sse.ts +138 -50
  106. package/src/middleware/auth.ts +6 -2
  107. package/src/routes/api/posts.ts +14 -5
  108. package/src/routes/api/upload.ts +25 -7
  109. package/src/routes/dash/collections.tsx +162 -70
  110. package/src/routes/dash/index.tsx +22 -7
  111. package/src/routes/dash/media.tsx +59 -16
  112. package/src/routes/dash/pages.tsx +102 -44
  113. package/src/routes/dash/posts.tsx +87 -54
  114. package/src/routes/dash/redirects.tsx +74 -26
  115. package/src/routes/dash/settings.tsx +250 -57
  116. package/src/routes/feed/rss.ts +6 -4
  117. package/src/routes/pages/archive.tsx +71 -21
  118. package/src/routes/pages/collection.tsx +21 -6
  119. package/src/routes/pages/home.tsx +30 -9
  120. package/src/routes/pages/page.tsx +14 -5
  121. package/src/routes/pages/post.tsx +21 -7
  122. package/src/routes/pages/search.tsx +42 -11
  123. package/src/services/collection.ts +34 -9
  124. package/src/services/index.ts +4 -1
  125. package/src/services/media.ts +15 -3
  126. package/src/services/post.ts +39 -10
  127. package/src/services/redirect.ts +4 -1
  128. package/src/services/settings.ts +14 -3
  129. package/src/theme/components/ActionButtons.tsx +26 -14
  130. package/src/theme/components/CrudPageHeader.tsx +6 -1
  131. package/src/theme/components/DangerZone.tsx +19 -13
  132. package/src/theme/components/EmptyState.tsx +6 -1
  133. package/src/theme/components/PageForm.tsx +71 -24
  134. package/src/theme/components/Pagination.tsx +26 -8
  135. package/src/theme/components/PostForm.tsx +72 -25
  136. package/src/theme/components/PostList.tsx +16 -5
  137. package/src/theme/components/ThreadView.tsx +25 -7
  138. package/src/theme/components/TypeBadge.tsx +13 -4
  139. package/src/theme/components/VisibilityBadge.tsx +17 -5
  140. package/src/theme/components/index.ts +4 -1
  141. package/src/theme/layouts/BaseLayout.tsx +5 -2
  142. package/src/theme/layouts/DashLayout.tsx +41 -12
  143. package/src/types/lingui-react-macro.d.ts +34 -0
  144. package/src/types.ts +16 -2
  145. package/src/vendor/datastar.js +9 -0
  146. package/src/vendor/datastar.js.map +7 -0
@@ -2,120 +2,235 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-
2
2
  /**
3
3
  * Dashboard Settings Routes
4
4
  */ import { Hono } from "hono";
5
- import { useLingui } from "../../i18n/index.js";
5
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
6
6
  import { DashLayout } from "../../theme/layouts/index.js";
7
+ import { sse } from "../../lib/sse.js";
7
8
  export const settingsRoutes = new Hono();
8
- function SettingsContent({ siteName, siteDescription, siteLanguage }) {
9
- const { t } = useLingui();
9
+ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
10
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
11
+ const generalSignals = JSON.stringify({
12
+ siteName,
13
+ siteDescription,
14
+ siteLanguage
15
+ }).replace(/</g, "\\u003c");
10
16
  return /*#__PURE__*/ _jsxs(_Fragment, {
11
17
  children: [
12
18
  /*#__PURE__*/ _jsx("h1", {
13
19
  class: "text-2xl font-semibold mb-6",
14
- children: t({
15
- message: "Settings",
16
- comment: "@context: Dashboard heading"
20
+ children: $__i18n._({
21
+ id: "Tz0i8g",
22
+ message: "Settings"
17
23
  })
18
24
  }),
19
- /*#__PURE__*/ _jsxs("form", {
20
- method: "post",
21
- action: "/dash/settings",
25
+ saved && /*#__PURE__*/ _jsx("div", {
26
+ id: "settings-saved-toast",
27
+ class: "mb-4 max-w-lg rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 transition-opacity duration-300 dark:border-green-800 dark:bg-green-950 dark:text-green-200",
28
+ "data-init": `console.log('[toast] init fired at', Date.now()); history.replaceState({}, '', '/dash/settings'); setTimeout(() => { console.log('[toast] hiding at', Date.now()); const el = document.getElementById('settings-saved-toast'); if (el) { el.style.opacity = '0'; setTimeout(() => el.remove(), 300) } }, 3000)`,
29
+ children: $__i18n._({
30
+ id: "T0bsor",
31
+ message: "Settings saved successfully."
32
+ })
33
+ }),
34
+ /*#__PURE__*/ _jsxs("div", {
22
35
  class: "flex flex-col gap-6 max-w-lg",
23
36
  children: [
24
- /*#__PURE__*/ _jsxs("div", {
25
- class: "card",
37
+ /*#__PURE__*/ _jsxs("form", {
38
+ "data-signals": generalSignals,
39
+ "data-on:submit__prevent": "@post('/dash/settings')",
26
40
  children: [
27
- /*#__PURE__*/ _jsx("header", {
28
- children: /*#__PURE__*/ _jsx("h2", {
29
- children: t({
30
- message: "General",
31
- comment: "@context: Settings section heading"
32
- })
33
- })
41
+ /*#__PURE__*/ _jsx("div", {
42
+ id: "settings-message"
34
43
  }),
35
- /*#__PURE__*/ _jsxs("section", {
36
- class: "flex flex-col gap-4",
44
+ /*#__PURE__*/ _jsxs("div", {
45
+ class: "card",
37
46
  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
47
+ /*#__PURE__*/ _jsx("header", {
48
+ children: /*#__PURE__*/ _jsx("h2", {
49
+ children: $__i18n._({
50
+ id: "Weq9zb",
51
+ message: "General"
54
52
  })
55
- ]
53
+ })
56
54
  }),
57
- /*#__PURE__*/ _jsxs("div", {
58
- class: "field",
55
+ /*#__PURE__*/ _jsxs("section", {
56
+ class: "flex flex-col gap-4",
59
57
  children: [
60
- /*#__PURE__*/ _jsx("label", {
61
- class: "label",
62
- children: t({
63
- message: "Site Description",
64
- comment: "@context: Settings form field"
65
- })
58
+ /*#__PURE__*/ _jsxs("div", {
59
+ class: "field",
60
+ children: [
61
+ /*#__PURE__*/ _jsx("label", {
62
+ class: "label",
63
+ children: $__i18n._({
64
+ id: "SJmfuf",
65
+ message: "Site Name"
66
+ })
67
+ }),
68
+ /*#__PURE__*/ _jsx("input", {
69
+ type: "text",
70
+ "data-bind": "siteName",
71
+ class: "input",
72
+ required: true
73
+ })
74
+ ]
66
75
  }),
67
- /*#__PURE__*/ _jsx("textarea", {
68
- name: "siteDescription",
69
- class: "textarea",
70
- rows: 3,
71
- children: siteDescription
76
+ /*#__PURE__*/ _jsxs("div", {
77
+ class: "field",
78
+ children: [
79
+ /*#__PURE__*/ _jsx("label", {
80
+ class: "label",
81
+ children: $__i18n._({
82
+ id: "u2f7vd",
83
+ message: "Site Description"
84
+ })
85
+ }),
86
+ /*#__PURE__*/ _jsx("textarea", {
87
+ "data-bind": "siteDescription",
88
+ class: "textarea",
89
+ rows: 3,
90
+ children: siteDescription
91
+ })
92
+ ]
93
+ }),
94
+ /*#__PURE__*/ _jsxs("div", {
95
+ class: "field",
96
+ children: [
97
+ /*#__PURE__*/ _jsx("label", {
98
+ class: "label",
99
+ children: $__i18n._({
100
+ id: "vXIe7J",
101
+ message: "Language"
102
+ })
103
+ }),
104
+ /*#__PURE__*/ _jsxs("select", {
105
+ "data-bind": "siteLanguage",
106
+ class: "select",
107
+ children: [
108
+ /*#__PURE__*/ _jsx("option", {
109
+ value: "en",
110
+ selected: siteLanguage === "en",
111
+ children: "English"
112
+ }),
113
+ /*#__PURE__*/ _jsx("option", {
114
+ value: "zh-Hans",
115
+ selected: siteLanguage === "zh-Hans",
116
+ children: "简体中文"
117
+ }),
118
+ /*#__PURE__*/ _jsx("option", {
119
+ value: "zh-Hant",
120
+ selected: siteLanguage === "zh-Hant",
121
+ children: "繁體中文"
122
+ })
123
+ ]
124
+ })
125
+ ]
72
126
  })
73
127
  ]
128
+ })
129
+ ]
130
+ }),
131
+ /*#__PURE__*/ _jsx("button", {
132
+ type: "submit",
133
+ class: "btn mt-4",
134
+ children: $__i18n._({
135
+ id: "UGT5vp",
136
+ message: "Save Settings"
137
+ })
138
+ })
139
+ ]
140
+ }),
141
+ /*#__PURE__*/ _jsxs("form", {
142
+ "data-signals": "{currentPassword: '', newPassword: '', confirmPassword: ''}",
143
+ "data-on:submit__prevent": "@post('/dash/settings/password')",
144
+ children: [
145
+ /*#__PURE__*/ _jsx("div", {
146
+ id: "password-message"
147
+ }),
148
+ /*#__PURE__*/ _jsxs("div", {
149
+ class: "card",
150
+ children: [
151
+ /*#__PURE__*/ _jsx("header", {
152
+ children: /*#__PURE__*/ _jsx("h2", {
153
+ children: $__i18n._({
154
+ id: "VhMDMg",
155
+ message: "Change Password"
156
+ })
157
+ })
74
158
  }),
75
- /*#__PURE__*/ _jsxs("div", {
76
- class: "field",
159
+ /*#__PURE__*/ _jsxs("section", {
160
+ class: "flex flex-col gap-4",
77
161
  children: [
78
- /*#__PURE__*/ _jsx("label", {
79
- class: "label",
80
- children: t({
81
- message: "Language",
82
- comment: "@context: Settings form field"
83
- })
162
+ /*#__PURE__*/ _jsxs("div", {
163
+ class: "field",
164
+ children: [
165
+ /*#__PURE__*/ _jsx("label", {
166
+ class: "label",
167
+ children: $__i18n._({
168
+ id: "DCKkhU",
169
+ message: "Current Password"
170
+ })
171
+ }),
172
+ /*#__PURE__*/ _jsx("input", {
173
+ type: "password",
174
+ "data-bind": "currentPassword",
175
+ class: "input",
176
+ required: true,
177
+ autocomplete: "current-password"
178
+ })
179
+ ]
84
180
  }),
85
- /*#__PURE__*/ _jsxs("select", {
86
- name: "siteLanguage",
87
- class: "select",
181
+ /*#__PURE__*/ _jsxs("div", {
182
+ class: "field",
88
183
  children: [
89
- /*#__PURE__*/ _jsx("option", {
90
- value: "en",
91
- selected: siteLanguage === "en",
92
- children: "English"
184
+ /*#__PURE__*/ _jsx("label", {
185
+ class: "label",
186
+ children: $__i18n._({
187
+ id: "7vhWI8",
188
+ message: "New Password"
189
+ })
93
190
  }),
94
- /*#__PURE__*/ _jsx("option", {
95
- value: "zh-Hans",
96
- selected: siteLanguage === "zh-Hans",
97
- children: "简体中文"
191
+ /*#__PURE__*/ _jsx("input", {
192
+ type: "password",
193
+ "data-bind": "newPassword",
194
+ class: "input",
195
+ required: true,
196
+ minlength: 8,
197
+ autocomplete: "new-password"
198
+ })
199
+ ]
200
+ }),
201
+ /*#__PURE__*/ _jsxs("div", {
202
+ class: "field",
203
+ children: [
204
+ /*#__PURE__*/ _jsx("label", {
205
+ class: "label",
206
+ children: $__i18n._({
207
+ id: "yjkELF",
208
+ message: "Confirm New Password"
209
+ })
98
210
  }),
99
- /*#__PURE__*/ _jsx("option", {
100
- value: "zh-Hant",
101
- selected: siteLanguage === "zh-Hant",
102
- children: "繁體中文"
211
+ /*#__PURE__*/ _jsx("input", {
212
+ type: "password",
213
+ "data-bind": "confirmPassword",
214
+ class: "input",
215
+ required: true,
216
+ minlength: 8,
217
+ autocomplete: "new-password"
103
218
  })
104
219
  ]
105
220
  })
106
221
  ]
107
222
  })
108
223
  ]
224
+ }),
225
+ /*#__PURE__*/ _jsx("button", {
226
+ type: "submit",
227
+ class: "btn mt-4",
228
+ children: $__i18n._({
229
+ id: "VhMDMg",
230
+ message: "Change Password"
231
+ })
109
232
  })
110
233
  ]
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
234
  })
120
235
  ]
121
236
  })
@@ -124,9 +239,11 @@ function SettingsContent({ siteName, siteDescription, siteLanguage }) {
124
239
  }
125
240
  // Settings page
126
241
  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";
242
+ const all = await c.var.services.settings.getAll();
243
+ const siteName = all["SITE_NAME"] ?? "Jant";
244
+ const siteDescription = all["SITE_DESCRIPTION"] ?? "";
245
+ const siteLanguage = all["SITE_LANGUAGE"] ?? "en";
246
+ const saved = c.req.query("saved") !== undefined;
130
247
  return c.html(/*#__PURE__*/ _jsx(DashLayout, {
131
248
  c: c,
132
249
  title: "Settings",
@@ -135,20 +252,59 @@ settingsRoutes.get("/", async (c)=>{
135
252
  children: /*#__PURE__*/ _jsx(SettingsContent, {
136
253
  siteName: siteName,
137
254
  siteDescription: siteDescription,
138
- siteLanguage: siteLanguage
255
+ siteLanguage: siteLanguage,
256
+ saved: saved
139
257
  })
140
258
  }));
141
259
  });
142
260
  // Update settings
143
261
  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");
262
+ const body = await c.req.json();
263
+ const oldLanguage = await c.var.services.settings.get("SITE_LANGUAGE") ?? "en";
148
264
  await c.var.services.settings.setMany({
149
- SITE_NAME: siteName,
150
- SITE_DESCRIPTION: siteDescription,
151
- SITE_LANGUAGE: siteLanguage
265
+ SITE_NAME: body.siteName,
266
+ SITE_DESCRIPTION: body.siteDescription,
267
+ SITE_LANGUAGE: body.siteLanguage
268
+ });
269
+ const languageChanged = oldLanguage !== body.siteLanguage;
270
+ return sse(c, async (stream)=>{
271
+ if (languageChanged) {
272
+ // Language changed - full reload needed to update all UI text
273
+ await stream.redirect("/dash/settings?saved");
274
+ } else {
275
+ // No language change - show inline success message
276
+ await stream.patchElements('<div id="settings-message"><div class="rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200 mb-4 transition-opacity duration-300" data-init="setTimeout(() => { el.style.opacity = \'0\'; setTimeout(() => el.remove(), 300) }, 3000)">Settings saved successfully.</div></div>');
277
+ }
278
+ });
279
+ });
280
+ // Change password
281
+ settingsRoutes.post("/password", async (c)=>{
282
+ const body = await c.req.json();
283
+ if (body.newPassword !== body.confirmPassword) {
284
+ return sse(c, async (stream)=>{
285
+ await stream.patchElements('<div id="password-message"><div class="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200 mb-4">Passwords do not match.</div></div>');
286
+ });
287
+ }
288
+ try {
289
+ await c.var.auth.api.changePassword({
290
+ body: {
291
+ currentPassword: body.currentPassword,
292
+ newPassword: body.newPassword,
293
+ revokeOtherSessions: false
294
+ },
295
+ headers: c.req.raw.headers
296
+ });
297
+ } catch {
298
+ return sse(c, async (stream)=>{
299
+ await stream.patchElements('<div id="password-message"><div class="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200 mb-4">Current password is incorrect.</div></div>');
300
+ });
301
+ }
302
+ return sse(c, async (stream)=>{
303
+ await stream.patchElements('<div id="password-message"><div class="rounded-md border border-green-200 bg-green-50 p-3 text-sm text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200 mb-4">Password changed successfully.</div></div>');
304
+ await stream.patchSignals({
305
+ currentPassword: "",
306
+ newPassword: "",
307
+ confirmPassword: ""
308
+ });
152
309
  });
153
- return c.redirect("/dash/settings?saved=1");
154
310
  });
@@ -6,8 +6,9 @@ import * as time from "../../lib/time.js";
6
6
  export const rssRoutes = new Hono();
7
7
  // RSS 2.0 Feed - main feed at /feed
8
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") ?? "";
9
+ const all = await c.var.services.settings.getAll();
10
+ const siteName = all["SITE_NAME"] ?? "Jant";
11
+ const siteDescription = all["SITE_DESCRIPTION"] ?? "";
11
12
  const siteUrl = c.env.SITE_URL;
12
13
  const posts = await c.var.services.posts.list({
13
14
  visibility: [
@@ -48,8 +49,9 @@ rssRoutes.get("/", async (c)=>{
48
49
  });
49
50
  // Atom Feed
50
51
  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") ?? "";
52
+ const all = await c.var.services.settings.getAll();
53
+ const siteName = all["SITE_NAME"] ?? "Jant";
54
+ const siteDescription = all["SITE_DESCRIPTION"] ?? "";
53
55
  const siteUrl = c.env.SITE_URL;
54
56
  const posts = await c.var.services.posts.list({
55
57
  visibility: [
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
4
4
  *
5
5
  * Shows all posts, optionally filtered by type
6
6
  */ import { Hono } from "hono";
7
- import { useLingui } from "../../i18n/index.js";
7
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
8
8
  import { BaseLayout } from "../../theme/layouts/index.js";
9
9
  import { Pagination } from "../../theme/components/index.js";
10
10
  import { POST_TYPES } from "../../types.js";
@@ -13,61 +13,61 @@ import * as time from "../../lib/time.js";
13
13
  const PAGE_SIZE = 50;
14
14
  export const archiveRoutes = new Hono();
15
15
  function getTypeLabel(type) {
16
- const { t } = useLingui();
16
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
17
17
  const labels = {
18
- note: t({
19
- message: "Note",
20
- comment: "@context: Post type label - note"
18
+ note: $__i18n._({
19
+ id: "KiJn9B",
20
+ message: "Note"
21
21
  }),
22
- article: t({
23
- message: "Article",
24
- comment: "@context: Post type label - article"
22
+ article: $__i18n._({
23
+ id: "f6e0Ry",
24
+ message: "Article"
25
25
  }),
26
- link: t({
27
- message: "Link",
28
- comment: "@context: Post type label - link"
26
+ link: $__i18n._({
27
+ id: "yzF66j",
28
+ message: "Link"
29
29
  }),
30
- quote: t({
31
- message: "Quote",
32
- comment: "@context: Post type label - quote"
30
+ quote: $__i18n._({
31
+ id: "ZhhOwV",
32
+ message: "Quote"
33
33
  }),
34
- image: t({
35
- message: "Image",
36
- comment: "@context: Post type label - image"
34
+ image: $__i18n._({
35
+ id: "hG89Ed",
36
+ message: "Image"
37
37
  }),
38
- page: t({
39
- message: "Page",
40
- comment: "@context: Post type label - page"
38
+ page: $__i18n._({
39
+ id: "6WdDG7",
40
+ message: "Page"
41
41
  })
42
42
  };
43
43
  return labels[type] ?? type;
44
44
  }
45
45
  function getTypeLabelPlural(type) {
46
- const { t } = useLingui();
46
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
47
47
  const labels = {
48
- note: t({
49
- message: "Notes",
50
- comment: "@context: Post type label plural - notes"
48
+ note: $__i18n._({
49
+ id: "1DBGsz",
50
+ message: "Notes"
51
51
  }),
52
- article: t({
53
- message: "Articles",
54
- comment: "@context: Post type label plural - articles"
52
+ article: $__i18n._({
53
+ id: "Tt5T6+",
54
+ message: "Articles"
55
55
  }),
56
- link: t({
57
- message: "Links",
58
- comment: "@context: Post type label plural - links"
56
+ link: $__i18n._({
57
+ id: "Rj01Fz",
58
+ message: "Links"
59
59
  }),
60
- quote: t({
61
- message: "Quotes",
62
- comment: "@context: Post type label plural - quotes"
60
+ quote: $__i18n._({
61
+ id: "eWLklq",
62
+ message: "Quotes"
63
63
  }),
64
- image: t({
65
- message: "Images",
66
- comment: "@context: Post type label plural - images"
64
+ image: $__i18n._({
65
+ id: "an5hVd",
66
+ message: "Images"
67
67
  }),
68
- page: t({
69
- message: "Pages",
70
- comment: "@context: Post type label plural - pages"
68
+ page: $__i18n._({
69
+ id: "wRR604",
70
+ message: "Pages"
71
71
  })
72
72
  };
73
73
  return labels[type] ?? `${type}s`;
@@ -82,10 +82,10 @@ function formatYearMonth(yearMonth) {
82
82
  });
83
83
  }
84
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"
85
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
86
+ const title = type ? getTypeLabelPlural(type) : $__i18n._({
87
+ id: "B495Gs",
88
+ message: "Archive"
89
89
  });
90
90
  return /*#__PURE__*/ _jsxs("div", {
91
91
  class: "container py-8",
@@ -103,9 +103,9 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
103
103
  /*#__PURE__*/ _jsx("a", {
104
104
  href: "/archive",
105
105
  class: `badge ${!type ? "badge-primary" : "badge-outline"}`,
106
- children: t({
107
- message: "All",
108
- comment: "@context: Archive filter - all types"
106
+ children: $__i18n._({
107
+ id: "N40H+G",
108
+ message: "All"
109
109
  })
110
110
  }),
111
111
  POST_TYPES.filter((t)=>t !== "page").map((typeKey)=>/*#__PURE__*/ _jsx("a", {
@@ -120,9 +120,9 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
120
120
  /*#__PURE__*/ _jsx("main", {
121
121
  children: displayPosts.length === 0 ? /*#__PURE__*/ _jsx("p", {
122
122
  class: "text-muted-foreground",
123
- children: t({
124
- message: "No posts found.",
125
- comment: "@context: Archive empty state"
123
+ children: $__i18n._({
124
+ id: "Hzi9AA",
125
+ message: "No posts found."
126
126
  })
127
127
  }) : Array.from(grouped.entries()).map(([yearMonth, monthPosts])=>/*#__PURE__*/ _jsxs("section", {
128
128
  class: "mb-8",
@@ -159,15 +159,12 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
159
159
  class: "ml-2 text-xs text-muted-foreground",
160
160
  children: [
161
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
- }
162
+ replyCount === 1 ? $__i18n._({
163
+ id: "TxE+Mj",
164
+ message: "1 reply"
165
+ }) : $__i18n._({
166
+ id: "90Luob",
167
+ message: "{count} replies"
171
168
  }),
172
169
  ")"
173
170
  ]
@@ -192,10 +189,11 @@ function ArchiveContent({ displayPosts, hasMore, nextCursor, type, grouped, repl
192
189
  href: "/",
193
190
  class: "text-sm hover:underline",
194
191
  children: [
195
- "← ",
196
- t({
197
- message: "Back to home",
198
- comment: "@context: Navigation link back to home page"
192
+ "←",
193
+ " ",
194
+ $__i18n._({
195
+ id: "x4RuFo",
196
+ message: "Back to home"
199
197
  })
200
198
  ]
201
199
  })