chore: style updates
03ddd53d
3 file(s) · +12 −14
| 53 | 53 | }, |
|
| 54 | 54 | body: JSON.stringify({ |
|
| 55 | 55 | title: title.trim(), |
|
| 56 | - | path: path.trim() || undefined, |
|
| 56 | + | path: path.trim() ? (path.trim().startsWith('/') ? path.trim() : `/${path.trim()}`) : undefined, |
|
| 57 | 57 | content: content.trim(), |
|
| 58 | 58 | }), |
|
| 59 | 59 | }); |
|
| 120 | 120 | Path |
|
| 121 | 121 | </label> |
|
| 122 | 122 | <div className="flex items-center gap-2"> |
|
| 123 | - | <span className="text-gray-400 text-sm">{SITE_URL}/now</span> |
|
| 124 | 123 | <input |
|
| 125 | 124 | id="path" |
|
| 126 | 125 | type="text" |
|
| 127 | 126 | value={path} |
|
| 128 | 127 | onChange={(e) => setPath(e.target.value)} |
|
| 129 | - | placeholder="/custom-path" |
|
| 128 | + | placeholder="custom-slug" |
|
| 130 | 129 | className="flex-1 bg-transparent p-3 border border-white text-white" |
|
| 131 | 130 | disabled={isSubmitting} |
|
| 132 | 131 | /> |
|
| 133 | 132 | </div> |
|
| 134 | - | <span className="text-xs text-gray-500"> |
|
| 135 | - | Optional. Leave empty to use auto-generated path. Must start with / |
|
| 136 | - | </span> |
|
| 137 | 133 | </div> |
|
| 138 | 134 | ||
| 139 | 135 | {/* Content Field */} |
|
| 3 | 3 | import { NowAdmin } from "@/components/post/NowAdmin"; |
|
| 4 | 4 | ||
| 5 | 5 | const meta = { |
|
| 6 | - | title: "Post Update", |
|
| 6 | + | title: "Make a Post", |
|
| 7 | 7 | description: "Create a new update", |
|
| 8 | 8 | }; |
|
| 9 | 9 | --- |
|
| 10 | 10 | <PageLayout meta={meta}> |
|
| 11 | 11 | <div class="space-y-6"> |
|
| 12 | - | <h1 class="title">Post Update</h1> |
|
| 12 | + | <h1 class="title">Make a Post</h1> |
|
| 13 | 13 | <p>Create a new update for the <a href="/now" class="text-link">Now</a> page.</p> |
|
| 14 | 14 | <NowAdmin client:load /> |
|
| 15 | 15 | </div> |
| 86 | 86 | return c.json({ error: "Content is required" }, 400); |
|
| 87 | 87 | } |
|
| 88 | 88 | ||
| 89 | - | // Validate path if provided |
|
| 90 | - | if (body.path) { |
|
| 91 | - | if (!body.path.startsWith("/")) { |
|
| 92 | - | return c.json({ error: "Path must start with /" }, 400); |
|
| 89 | + | // Normalize and validate path if provided |
|
| 90 | + | let normalizedPath = body.path; |
|
| 91 | + | if (normalizedPath) { |
|
| 92 | + | // Add leading / if missing |
|
| 93 | + | if (!normalizedPath.startsWith("/")) { |
|
| 94 | + | normalizedPath = `/${normalizedPath}`; |
|
| 93 | 95 | } |
|
| 94 | 96 | // Basic validation: no spaces, no special chars except dashes and underscores |
|
| 95 | - | if (!/^\/[a-zA-Z0-9\-_\/]*$/.test(body.path)) { |
|
| 97 | + | if (!/^\/[a-zA-Z0-9\-_\/]*$/.test(normalizedPath)) { |
|
| 96 | 98 | return c.json( |
|
| 97 | 99 | { |
|
| 98 | 100 | error: |
|
| 132 | 134 | }, |
|
| 133 | 135 | title: body.title.trim(), |
|
| 134 | 136 | site: "https://stevedylan.dev", |
|
| 135 | - | ...(body.path && { path: body.path.trim() }), |
|
| 137 | + | ...(normalizedPath && { path: normalizedPath.trim() }), |
|
| 136 | 138 | content: markdownContent, |
|
| 137 | 139 | textContent: textContent, |
|
| 138 | 140 | publishedAt: new Date().toISOString(), |
|