Merge pull request #2 from pdraim/staging
Fix styling not being saved and UI layout
4 files · +28 -5
M package.json +1 -1
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | { | |
| 2 | 2 | "name": "pdraim", | |
| 3 | 3 | "private": true, | |
| 4 | - | "version": "0.2.0", | |
| 4 | + | "version": "0.2.1", | |
| 5 | 5 | "type": "module", | |
| 6 | 6 | "engines": { | |
| 7 | 7 | "node": ">=22.13.0" | |
| @@ -1,7 +1,7 @@ | |||||
| 1 | { | 1 | { | ||
| 2 | "name": "pdraim", | 2 | "name": "pdraim", | ||
| 3 | "private": true, | 3 | "private": true, | ||
| 4 | - | "version": "0.2.0", | 4 | + | "version": "0.2.1", |
| 5 | "type": "module", | 5 | "type": "module", | ||
| 6 | "engines": { | 6 | "engines": { | ||
| 7 | "node": ">=22.13.0" | 7 | "node": ">=22.13.0" | ||
M src/lib/components/chat-room.svelte +10 -2
| @@ -575,7 +575,9 @@ function handleLoginSuccess() { | |||
| 575 | 575 | }}> | |
| 576 | 576 | <span class="nickname pointer-events-none">{message.user.nickname}:</span> | |
| 577 | 577 | </Tooltip> | |
| 578 | - | <FormattedMessage {message} allowFormatting={true} /> | |
| 578 | + | <span class="message-content"> | |
| 579 | + | <FormattedMessage {message} allowFormatting={true} /> | |
| 580 | + | </span> | |
| 579 | 581 | {/if} | |
| 580 | 582 | </div> | |
| 581 | 583 | {/each} | |
| @@ -674,7 +676,7 @@ function handleLoginSuccess() { | |||
| 674 | 676 | <style> | |
| 675 | 677 | .chat-area, .users-list { | |
| 676 | 678 | font-size: 1rem; | |
| 677 | - | font-family: "Pixelated MS Sans Serif", Arial, Verdana, Tahoma, sans-serif; | |
| 679 | + | font-family: Arial, "Pixelated MS Sans Serif", Verdana, Tahoma, sans-serif; | |
| 678 | 680 | } | |
| 679 | 681 | ||
| 680 | 682 | input:not(.styled-input) { | |
| @@ -734,6 +736,12 @@ function handleLoginSuccess() { | |||
| 734 | 736 | font-weight: bold; | |
| 735 | 737 | color: #2d31a6; | |
| 736 | 738 | cursor: help; | |
| 739 | + | flex-shrink: 0; | |
| 740 | + | } | |
| 741 | + | ||
| 742 | + | .message-content { | |
| 743 | + | flex: 1; | |
| 744 | + | min-width: 0; | |
| 737 | 745 | } | |
| 738 | 746 | ||
| 739 | 747 | .message .content { | |
| @@ -575,7 +575,9 @@ function handleLoginSuccess() { | |||||
| 575 | }}> | 575 | }}> | ||
| 576 | <span class="nickname pointer-events-none">{message.user.nickname}:</span> | 576 | <span class="nickname pointer-events-none">{message.user.nickname}:</span> | ||
| 577 | </Tooltip> | 577 | </Tooltip> | ||
| 578 | - | <FormattedMessage {message} allowFormatting={true} /> | 578 | + | <span class="message-content"> |
| 579 | + | <FormattedMessage {message} allowFormatting={true} /> | |||
| 580 | + | </span> | |||
| 579 | {/if} | 581 | {/if} | ||
| 580 | </div> | 582 | </div> | ||
| 581 | {/each} | 583 | {/each} | ||
| @@ -674,7 +676,7 @@ function handleLoginSuccess() { | |||||
| 674 | <style> | 676 | <style> | ||
| 675 | .chat-area, .users-list { | 677 | .chat-area, .users-list { | ||
| 676 | font-size: 1rem; | 678 | font-size: 1rem; | ||
| 677 | - | font-family: "Pixelated MS Sans Serif", Arial, Verdana, Tahoma, sans-serif; | 679 | + | font-family: Arial, "Pixelated MS Sans Serif", Verdana, Tahoma, sans-serif; |
| 678 | } | 680 | } | ||
| 679 | 681 | ||||
| 680 | input:not(.styled-input) { | 682 | input:not(.styled-input) { | ||
| @@ -734,6 +736,12 @@ function handleLoginSuccess() { | |||||
| 734 | font-weight: bold; | 736 | font-weight: bold; | ||
| 735 | color: #2d31a6; | 737 | color: #2d31a6; | ||
| 736 | cursor: help; | 738 | cursor: help; | ||
| 739 | + | flex-shrink: 0; | |||
| 740 | + | } | |||
| 741 | + | ||||
| 742 | + | .message-content { | |||
| 743 | + | flex: 1; | |||
| 744 | + | min-width: 0; | |||
| 737 | } | 745 | } | ||
| 738 | 746 | ||||
| 739 | .message .content { | 747 | .message .content { | ||
M src/lib/validation/text-formatting.ts +12 -1
| @@ -76,6 +76,17 @@ export function validateTextStyle(style: unknown): TextStyle | null { | |||
| 76 | 76 | export function sanitizeStyleData(styleData: unknown): TextStyle | undefined { | |
| 77 | 77 | if (!styleData) return undefined; | |
| 78 | 78 | ||
| 79 | - | const validated = validateTextStyle(styleData); | |
| 79 | + | // Handle JSON string input | |
| 80 | + | let parsedData: unknown = styleData; | |
| 81 | + | if (typeof styleData === 'string') { | |
| 82 | + | try { | |
| 83 | + | parsedData = JSON.parse(styleData); | |
| 84 | + | } catch (error) { | |
| 85 | + | console.warn('Failed to parse styleData JSON:', error); | |
| 86 | + | return undefined; | |
| 87 | + | } | |
| 88 | + | } | |
| 89 | + | ||
| 90 | + | const validated = validateTextStyle(parsedData); | |
| 80 | 91 | return validated || undefined; | |
| 81 | 92 | }⏎̸ | |
| @@ -76,6 +76,17 @@ export function validateTextStyle(style: unknown): TextStyle | null { | |||||
| 76 | export function sanitizeStyleData(styleData: unknown): TextStyle | undefined { | 76 | export function sanitizeStyleData(styleData: unknown): TextStyle | undefined { | ||
| 77 | if (!styleData) return undefined; | 77 | if (!styleData) return undefined; | ||
| 78 | 78 | ||||
| 79 | - | const validated = validateTextStyle(styleData); | 79 | + | // Handle JSON string input |
| 80 | + | let parsedData: unknown = styleData; | |||
| 81 | + | if (typeof styleData === 'string') { | |||
| 82 | + | try { | |||
| 83 | + | parsedData = JSON.parse(styleData); | |||
| 84 | + | } catch (error) { | |||
| 85 | + | console.warn('Failed to parse styleData JSON:', error); | |||
| 86 | + | return undefined; | |||
| 87 | + | } | |||
| 88 | + | } | |||
| 89 | + | ||||
| 90 | + | const validated = validateTextStyle(parsedData); | |||
| 80 | return validated || undefined; | 91 | return validated || undefined; | ||
| 81 | }⏎̸ | 92 | }⏎̸ | ||
M src/routes/api/chat/messages/+server.ts +5 -1
| @@ -197,10 +197,14 @@ export async function POST({ request, locals }: { request: Request, locals: App. | |||
| 197 | 197 | content: data.content, | |
| 198 | 198 | type: data.type || 'chat', | |
| 199 | 199 | timestamp: Date.now(), | |
| 200 | - | styleData: validatedStyleData, | |
| 200 | + | styleData: validatedStyleData ? JSON.stringify(validatedStyleData) : undefined, | |
| 201 | 201 | hasFormatting: Boolean(validatedStyleData) | |
| 202 | 202 | }; | |
| 203 | 203 | ||
| 204 | + | ||
| 205 | + | // debug style data content at this point | |
| 206 | + | log.debug('Style data content', { styleData: validatedStyleData }); | |
| 207 | + | ||
| 204 | 208 | // Save to DB | |
| 205 | 209 | await db.insert(messages).values(newMessage); | |
| 206 | 210 | log.debug('Message saved in DB', { messageId: newMessage.id, chatRoomId: newMessage.chatRoomId, type: newMessage.type, timestamp: newMessage.timestamp }); | |
| @@ -197,10 +197,14 @@ export async function POST({ request, locals }: { request: Request, locals: App. | |||||
| 197 | content: data.content, | 197 | content: data.content, | ||
| 198 | type: data.type || 'chat', | 198 | type: data.type || 'chat', | ||
| 199 | timestamp: Date.now(), | 199 | timestamp: Date.now(), | ||
| 200 | - | styleData: validatedStyleData, | 200 | + | styleData: validatedStyleData ? JSON.stringify(validatedStyleData) : undefined, |
| 201 | hasFormatting: Boolean(validatedStyleData) | 201 | hasFormatting: Boolean(validatedStyleData) | ||
| 202 | }; | 202 | }; | ||
| 203 | 203 | ||||
| 204 | + | ||||
| 205 | + | // debug style data content at this point | |||
| 206 | + | log.debug('Style data content', { styleData: validatedStyleData }); | |||
| 207 | + | ||||
| 204 | // Save to DB | 208 | // Save to DB | ||
| 205 | await db.insert(messages).values(newMessage); | 209 | await db.insert(messages).values(newMessage); | ||
| 206 | log.debug('Message saved in DB', { messageId: newMessage.id, chatRoomId: newMessage.chatRoomId, type: newMessage.type, timestamp: newMessage.timestamp }); | 210 | log.debug('Message saved in DB', { messageId: newMessage.id, chatRoomId: newMessage.chatRoomId, type: newMessage.type, timestamp: newMessage.timestamp }); | ||