diff --git a/ui/src/hooks/use-shared.ts b/ui/src/hooks/use-shared.ts index f1fb51f7..09a726b5 100644 --- a/ui/src/hooks/use-shared.ts +++ b/ui/src/hooks/use-shared.ts @@ -20,6 +20,11 @@ interface SharedItemContent { contentPath: string; } +interface SharedItemContentPayload { + content: string; + contentPath?: string; +} + function extractErrorFromPayload(payload: unknown, fallbackMessage: string): string { if ( typeof payload === 'object' && @@ -51,6 +56,23 @@ function looksLikeHtml(payloadText: string): boolean { return trimmed.startsWith('; + if (typeof candidate.content !== 'string') { + return false; + } + + if ('contentPath' in candidate && typeof candidate.contentPath !== 'string') { + return false; + } + + return true; +} + async function readJsonOrThrow(response: Response, fallbackMessage: string): Promise { const payloadText = await response.text(); const payload = parseJsonPayload(payloadText); @@ -111,7 +133,7 @@ export function useSharedItemContent( throw new Error(extractErrorFromPayload(payload, `Failed to fetch shared ${type} content`)); } - if (payload && typeof payload === 'object' && typeof payload.content === 'string') { + if (isSharedItemContentPayload(payload)) { return { content: payload.content, contentPath: diff --git a/ui/src/pages/shared.tsx b/ui/src/pages/shared.tsx index 9b9fcc0a..836816d9 100644 --- a/ui/src/pages/shared.tsx +++ b/ui/src/pages/shared.tsx @@ -399,8 +399,13 @@ interface MarkdownBlockParagraph { text: string; } -interface MarkdownBlockList { - type: 'unordered-list' | 'ordered-list'; +interface MarkdownBlockUnorderedList { + type: 'unordered-list'; + items: string[]; +} + +interface MarkdownBlockOrderedList { + type: 'ordered-list'; items: string[]; } @@ -413,7 +418,8 @@ interface MarkdownBlockCode { type MarkdownBlock = | MarkdownBlockHeading | MarkdownBlockParagraph - | MarkdownBlockList + | MarkdownBlockUnorderedList + | MarkdownBlockOrderedList | MarkdownBlockCode; interface MarkdownFrontmatterEntry {