@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
@@ -14,7 +14,7 @@ dashRoute.get("/", async (c) => {
14
14
  return c.html(
15
15
  <I18nProvider c={c}>
16
16
  <YourApp />
17
- </I18nProvider>
17
+ </I18nProvider>,
18
18
  );
19
19
  });
20
20
  ```
@@ -77,8 +77,11 @@ function DashboardContent({ postCount }: { postCount: number }) {
77
77
  {/* 2. With variables */}
78
78
  <p>
79
79
  {t(
80
- { message: "You have {count} posts", comment: "@context: Post count message" },
81
- { count: postCount }
80
+ {
81
+ message: "You have {count} posts",
82
+ comment: "@context: Post count message",
83
+ },
84
+ { count: postCount },
82
85
  )}
83
86
  </p>
84
87
 
@@ -102,7 +105,7 @@ dashRoute.get("/", async (c) => {
102
105
  return c.html(
103
106
  <I18nProvider c={c}>
104
107
  <DashboardContent postCount={posts.length} />
105
- </I18nProvider>
108
+ </I18nProvider>,
106
109
  );
107
110
  });
108
111
  ```
@@ -122,7 +125,7 @@ dashRoute.get("/", async (c) => {
122
125
  return c.html(
123
126
  <Layout title={i18n._({ message: "Dashboard", comment: "@context: ..." })}>
124
127
  <MyComponent c={c} /> {/* Need to pass c prop */}
125
- </Layout>
128
+ </Layout>,
126
129
  );
127
130
  });
128
131
 
@@ -143,7 +146,7 @@ dashRoute.get("/", async (c) => {
143
146
  <Layout>
144
147
  <MyComponent /> {/* No need to pass c prop */}
145
148
  </Layout>
146
- </I18nProvider>
149
+ </I18nProvider>,
147
150
  );
148
151
  });
149
152
 
@@ -175,7 +178,7 @@ t({ message: "Dashboard" });
175
178
  c.html(
176
179
  <I18nProvider c={c}>
177
180
  <App />
178
- </I18nProvider>
181
+ </I18nProvider>,
179
182
  );
180
183
 
181
184
  // ❌ Wrong - useLingui() will throw error
@@ -204,10 +207,17 @@ dashRoute.get("/", async (c) => {
204
207
  const { t } = useLingui();
205
208
 
206
209
  // ✅ Correct - values as second parameter
207
- t({ message: "Hello {name}", comment: "@context: Greeting" }, { name: "Alice" });
210
+ t(
211
+ { message: "Hello {name}", comment: "@context: Greeting" },
212
+ { name: "Alice" },
213
+ );
208
214
 
209
215
  // ❌ Wrong - values inside first parameter (not supported)
210
- t({ message: "Hello {name}", comment: "@context: Greeting", values: { name: "Alice" } });
216
+ t({
217
+ message: "Hello {name}",
218
+ comment: "@context: Greeting",
219
+ values: { name: "Alice" },
220
+ });
211
221
  ```
212
222
 
213
223
  ---
@@ -79,14 +79,11 @@ export function useLingui() {
79
79
  if (!currentI18n) {
80
80
  throw new Error(
81
81
  "useLingui() called outside of I18nProvider. " +
82
- "Make sure your component is wrapped in <I18nProvider c={c}>...</I18nProvider>"
82
+ "Make sure your component is wrapped in <I18nProvider c={c}>...</I18nProvider>",
83
83
  );
84
84
  }
85
85
 
86
- // Create translation function that accepts both pre-macro and post-macro formats
87
86
  const translate = (descriptor: TranslationDescriptor) => {
88
- // The macro will add the id, or it's already present
89
- // At runtime, we pass it to i18n._ which handles the descriptor with values
90
87
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- currentI18n is checked above
91
88
  return currentI18n!._(descriptor as MessageDescriptor);
92
89
  };
@@ -2,10 +2,7 @@
2
2
  * Language Detection Utilities
3
3
  */
4
4
 
5
- import type { Context } from "hono";
6
- import { locales, baseLocale, isLocale, type Locale } from "./locales.js";
7
-
8
- export const LANGUAGE_COOKIE_NAME = "lang";
5
+ import { locales, isLocale, type Locale } from "./locales.js";
9
6
 
10
7
  /**
11
8
  * Get display name for a language code
@@ -35,66 +32,3 @@ export function getSupportedLanguages(): Array<{ code: Locale; name: string }> {
35
32
  export function isValidLanguage(lang: unknown): lang is Locale {
36
33
  return isLocale(lang);
37
34
  }
38
-
39
- /**
40
- * Parse Accept-Language header and return best matching locale
41
- */
42
- export function parseAcceptLanguage(header: string | null): Locale {
43
- if (!header) return baseLocale;
44
-
45
- // Parse "en-US,en;q=0.9,zh-CN;q=0.8" format
46
- const languages = header
47
- .split(",")
48
- .map((part) => {
49
- const [lang, qPart] = part.trim().split(";");
50
- const q = qPart ? parseFloat(qPart.replace("q=", "")) : 1;
51
- return { lang: lang?.trim() ?? "", q };
52
- })
53
- .sort((a, b) => b.q - a.q);
54
-
55
- for (const { lang } of languages) {
56
- // Direct match
57
- if (isLocale(lang)) {
58
- return lang;
59
- }
60
-
61
- // Map common variants
62
- const normalized = lang.toLowerCase();
63
- if (normalized.startsWith("zh-cn") || normalized.startsWith("zh-hans")) {
64
- return "zh-Hans";
65
- }
66
- if (
67
- normalized.startsWith("zh-tw") ||
68
- normalized.startsWith("zh-hk") ||
69
- normalized.startsWith("zh-hant")
70
- ) {
71
- return "zh-Hant";
72
- }
73
- if (normalized.startsWith("zh")) {
74
- return "zh-Hans"; // Default Chinese to Simplified
75
- }
76
- if (normalized.startsWith("en")) {
77
- return "en";
78
- }
79
- }
80
-
81
- return baseLocale;
82
- }
83
-
84
- /**
85
- * Detect user's preferred language from Hono context
86
- * Priority: Cookie > Accept-Language header > Default
87
- */
88
- export function detectLanguage(c: Context): Locale {
89
- // 1. Check cookie (using getCookie helper)
90
- const cookies = c.req.raw.headers.get("Cookie") ?? "";
91
- const cookieMatch = cookies.match(new RegExp(`${LANGUAGE_COOKIE_NAME}=([^;]+)`));
92
- const cookieLang = cookieMatch?.[1];
93
- if (cookieLang && isLocale(cookieLang)) {
94
- return cookieLang;
95
- }
96
-
97
- // 2. Check Accept-Language header
98
- const acceptLang = c.req.header("Accept-Language") ?? null;
99
- return parseAcceptLanguage(acceptLang);
100
- }
package/src/i18n/i18n.ts CHANGED
@@ -1,21 +1,12 @@
1
1
  /**
2
- * i18n Runtime using @lingui/core with Lingui macros
2
+ * i18n Runtime using @lingui/core
3
3
  *
4
- * Usage:
5
- * import { msg } from "@lingui/core/macro";
6
- * import { bindI18n } from "@/i18n";
7
- *
8
- * const { i18n } = bindI18n(c.get("i18n"));
9
- *
10
- * // Simple message
11
- * i18n._(msg({ message: "Hello", comment: "@context: Greeting" }))
12
- *
13
- * // With interpolation
14
- * i18n._(msg({ message: "Welcome, {name}!", comment: "@context: Welcome" }), { name })
15
- *
16
- * The msg macro generates hash-based IDs at compile time, which match the compiled catalogs.
4
+ * The SWC Lingui plugin adds hash-based IDs to t() calls when imports come
5
+ * from @lingui/react/macro. The runtimeConfigModule setting rewrites those
6
+ * imports to our custom Hono JSX implementation at build time.
17
7
  */
18
8
 
9
+ import type { Messages } from "@lingui/core";
19
10
  import { I18n } from "@lingui/core";
20
11
  import { locales, baseLocale, isLocale, type Locale } from "./locales.js";
21
12
  import { messages as messagesEn } from "./locales/en.js";
@@ -27,6 +18,13 @@ export { locales, baseLocale, isLocale, type Locale };
27
18
  // Export I18n type for convenience
28
19
  export type { I18n };
29
20
 
21
+ // Pre-compute merged catalogs at module load time (done once, not per request)
22
+ // For non-English locales, merge English as fallback so missing translations
23
+ // fall back to English rather than showing hash IDs.
24
+ const catalogEn: Messages = messagesEn;
25
+ const catalogZhHans: Messages = { ...messagesEn, ...messagesZhHans };
26
+ const catalogZhHant: Messages = { ...messagesEn, ...messagesZhHant };
27
+
30
28
  /**
31
29
  * Create a new i18n instance for a specific locale.
32
30
  * IMPORTANT: In Cloudflare Workers (concurrent environment), we must create
@@ -35,12 +33,10 @@ export type { I18n };
35
33
  export function createI18n(locale: Locale): I18n {
36
34
  const i18n = new I18n({});
37
35
 
38
- // Load all catalogs with English as fallback
39
- i18n.load("en", messagesEn);
40
- i18n.load("zh-Hans", { ...messagesEn, ...messagesZhHans });
41
- i18n.load("zh-Hant", { ...messagesEn, ...messagesZhHant });
36
+ i18n.load("en", catalogEn);
37
+ i18n.load("zh-Hans", catalogZhHans);
38
+ i18n.load("zh-Hant", catalogZhHant);
42
39
 
43
- // Activate locale after loading messages to avoid warnings
44
40
  i18n.activate(locale);
45
41
 
46
42
  return i18n;
package/src/i18n/index.ts CHANGED
@@ -53,12 +53,9 @@ export { Trans } from "./Trans.js";
53
53
 
54
54
  // Language detection utilities
55
55
  export {
56
- detectLanguage,
57
56
  isValidLanguage,
58
- parseAcceptLanguage,
59
57
  getLanguageDisplayName,
60
58
  getSupportedLanguages,
61
- LANGUAGE_COOKIE_NAME,
62
59
  } from "./detect.js";
63
60
 
64
61
  // Hono middleware
@@ -4,8 +4,7 @@
4
4
 
5
5
  import type { MiddlewareHandler } from "hono";
6
6
  import type { I18n } from "@lingui/core";
7
- import { detectLanguage } from "./detect.js";
8
- import { createI18n, isLocale, type Locale } from "./i18n.js";
7
+ import { createI18n, isLocale, baseLocale, type Locale } from "./i18n.js";
9
8
  import type { Services } from "../services/index.js";
10
9
 
11
10
  declare module "hono" {
@@ -19,33 +18,22 @@ declare module "hono" {
19
18
  * Hono middleware for internationalization.
20
19
  * Creates a per-request i18n instance to avoid race conditions in concurrent environments.
21
20
  *
22
- * Language detection priority:
23
- * 1. Cookie (user preference)
24
- * 2. Database SITE_LANGUAGE setting (site default)
25
- * 3. Accept-Language header
26
- * 4. Default locale (en)
21
+ * Language is determined by the database SITE_LANGUAGE setting (single source of truth).
22
+ * Falls back to the default locale (en) if not set.
27
23
  */
28
24
  export function i18nMiddleware(): MiddlewareHandler {
29
25
  return async (c, next) => {
30
- // First try cookie and Accept-Language header
31
- let lang = detectLanguage(c);
26
+ let lang: Locale = baseLocale;
32
27
 
33
- // If no cookie is set, check database SITE_LANGUAGE setting
34
- const cookies = c.req.raw.headers.get("Cookie") ?? "";
35
- const hasCookie = cookies.includes("lang=");
36
-
37
- if (!hasCookie) {
38
- // Check database setting
39
- const services = c.get("services") as Services | undefined;
40
- if (services) {
41
- try {
42
- const siteLang = await services.settings.get("SITE_LANGUAGE");
43
- if (siteLang && isLocale(siteLang)) {
44
- lang = siteLang;
45
- }
46
- } catch {
47
- // Ignore errors, fall back to detected language
28
+ const services = c.get("services") as Services | undefined;
29
+ if (services) {
30
+ try {
31
+ const siteLang = await services.settings.get("SITE_LANGUAGE");
32
+ if (siteLang && isLocale(siteLang)) {
33
+ lang = siteLang;
48
34
  }
35
+ } catch {
36
+ // Ignore errors, fall back to default locale
49
37
  }
50
38
  }
51
39
 
@@ -64,4 +64,5 @@ export const ONBOARDING_STATUS = {
64
64
  COMPLETED: "completed",
65
65
  } as const;
66
66
 
67
- export type OnboardingStatus = (typeof ONBOARDING_STATUS)[keyof typeof ONBOARDING_STATUS];
67
+ export type OnboardingStatus =
68
+ (typeof ONBOARDING_STATUS)[keyof typeof ONBOARDING_STATUS];
@@ -53,7 +53,10 @@ function readExifOrientation(buffer: ArrayBuffer): number {
53
53
  const exifOffset = offset + 4;
54
54
 
55
55
  // Check for "Exif\0\0"
56
- if (view.getUint32(exifOffset) !== 0x45786966 || view.getUint16(exifOffset + 4) !== 0x0000) {
56
+ if (
57
+ view.getUint32(exifOffset) !== 0x45786966 ||
58
+ view.getUint16(exifOffset + 4) !== 0x0000
59
+ ) {
57
60
  return 1;
58
61
  }
59
62
 
@@ -112,7 +115,7 @@ function calculateDimensions(
112
115
  width: number,
113
116
  height: number,
114
117
  maxWidth: number,
115
- maxHeight: number
118
+ maxHeight: number,
116
119
  ): { width: number; height: number } {
117
120
  if (width <= maxWidth && height <= maxHeight) {
118
121
  return { width, height };
@@ -128,7 +131,10 @@ function calculateDimensions(
128
131
  /**
129
132
  * Process image file
130
133
  */
131
- async function process(file: File, options: ProcessOptions = {}): Promise<Blob> {
134
+ async function process(
135
+ file: File,
136
+ options: ProcessOptions = {},
137
+ ): Promise<Blob> {
132
138
  const opts = { ...DEFAULT_OPTIONS, ...options };
133
139
 
134
140
  // Read file buffer for EXIF
@@ -145,7 +151,12 @@ async function process(file: File, options: ProcessOptions = {}): Promise<Blob>
145
151
  const srcHeight = isRotated ? img.width : img.height;
146
152
 
147
153
  // Calculate output size
148
- const { width, height } = calculateDimensions(srcWidth, srcHeight, opts.maxWidth, opts.maxHeight);
154
+ const { width, height } = calculateDimensions(
155
+ srcWidth,
156
+ srcHeight,
157
+ opts.maxWidth,
158
+ opts.maxHeight,
159
+ );
149
160
 
150
161
  // Create canvas
151
162
  const canvas = document.createElement("canvas");
@@ -184,7 +195,7 @@ async function process(file: File, options: ProcessOptions = {}): Promise<Blob>
184
195
  }
185
196
  },
186
197
  opts.mimeType,
187
- opts.quality
198
+ opts.quality,
188
199
  );
189
200
  });
190
201
  }
@@ -192,7 +203,10 @@ async function process(file: File, options: ProcessOptions = {}): Promise<Blob>
192
203
  /**
193
204
  * Process file and create a new File object
194
205
  */
195
- async function processToFile(file: File, options: ProcessOptions = {}): Promise<File> {
206
+ async function processToFile(
207
+ file: File,
208
+ options: ProcessOptions = {},
209
+ ): Promise<File> {
196
210
  const blob = await process(file, options);
197
211
 
198
212
  // Generate new filename with .webp extension
@@ -206,5 +220,7 @@ export const ImageProcessor = { process, processToFile };
206
220
 
207
221
  // Expose globally for inline scripts
208
222
  if (typeof window !== "undefined") {
209
- (window as unknown as { ImageProcessor: typeof ImageProcessor }).ImageProcessor = ImageProcessor;
223
+ (
224
+ window as unknown as { ImageProcessor: typeof ImageProcessor }
225
+ ).ImageProcessor = ImageProcessor;
210
226
  }
package/src/lib/image.ts CHANGED
@@ -51,7 +51,7 @@ export interface ImageOptions {
51
51
  export function getImageUrl(
52
52
  originalUrl: string,
53
53
  transformUrl?: string,
54
- options?: ImageOptions
54
+ options?: ImageOptions,
55
55
  ): string {
56
56
  if (!transformUrl || !options || Object.keys(options).length === 0) {
57
57
  return originalUrl;
@@ -93,7 +93,11 @@ export function getImageUrl(
93
93
  * // Returns: "https://cdn.example.com/uploads/file.webp"
94
94
  * ```
95
95
  */
96
- export function getMediaUrl(mediaId: string, r2Key: string, r2PublicUrl?: string): string {
96
+ export function getMediaUrl(
97
+ mediaId: string,
98
+ r2Key: string,
99
+ r2PublicUrl?: string,
100
+ ): string {
97
101
  if (r2PublicUrl) {
98
102
  return `${r2PublicUrl}/${r2Key}`;
99
103
  }
@@ -62,7 +62,11 @@ export const UpdatePostSchema = CreatePostSchema.partial();
62
62
  * // type is PostType, throws if invalid
63
63
  * ```
64
64
  */
65
- export function parseFormData<T>(formData: FormData, key: string, schema: z.ZodSchema<T>): T {
65
+ export function parseFormData<T>(
66
+ formData: FormData,
67
+ key: string,
68
+ schema: z.ZodSchema<T>,
69
+ ): T {
66
70
  const value = formData.get(key);
67
71
  if (value === null) {
68
72
  throw new Error(`Missing required field: ${key}`);
@@ -82,7 +86,7 @@ export function parseFormData<T>(formData: FormData, key: string, schema: z.ZodS
82
86
  export function parseFormDataOptional<T>(
83
87
  formData: FormData,
84
88
  key: string,
85
- schema: z.ZodSchema<T>
89
+ schema: z.ZodSchema<T>,
86
90
  ): T | undefined {
87
91
  const value = formData.get(key);
88
92
  if (value === null || value === "") {