fIx: smaller nits
This commit is contained in:
86
frontend/src/hooks/useStreamingContent.ts
Normal file
86
frontend/src/hooks/useStreamingContent.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Hook for parsing and streaming markdown content.
|
||||
* Handles marked.js parsing with proper cleanup and cancellation.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Parse markdown content to HTML using marked.js.
|
||||
* Returns parsed HTML string and handles cleanup on unmount.
|
||||
*
|
||||
* @param markdown - The markdown string to parse
|
||||
* @returns HTML string from parsed markdown
|
||||
*/
|
||||
export function useStreamingContent(markdown: string | null): {
|
||||
html: string
|
||||
loading: boolean
|
||||
} {
|
||||
const [html, setHtml] = useState<string>('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (markdown === null) {
|
||||
setHtml('')
|
||||
return
|
||||
}
|
||||
|
||||
let cancelled = false
|
||||
setLoading(true)
|
||||
|
||||
// Lazy load marked.js to avoid bundling if not needed
|
||||
import('marked')
|
||||
.then(async ({ marked }) => {
|
||||
if (cancelled) return
|
||||
|
||||
try {
|
||||
const parsed =
|
||||
typeof marked.parse === 'function'
|
||||
? await (marked.parse as (s: string) => Promise<string>)(markdown)
|
||||
: (marked as (s: string) => string)(markdown)
|
||||
const result = typeof parsed === 'string' ? parsed : String(parsed)
|
||||
if (!cancelled) {
|
||||
setHtml(result)
|
||||
setLoading(false)
|
||||
}
|
||||
} catch (err) {
|
||||
if (!cancelled) {
|
||||
// Fallback: use raw markdown if parsing fails
|
||||
setHtml(markdown)
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
// Fallback: use raw markdown if import fails
|
||||
setHtml(markdown)
|
||||
setLoading(false)
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [markdown])
|
||||
|
||||
return { html, loading }
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse markdown content to HTML using marked.js (synchronous version).
|
||||
* Use this when you need immediate parsing without React state.
|
||||
*
|
||||
* @param markdown - The markdown string to parse
|
||||
* @returns HTML string from parsed markdown, or raw markdown on error
|
||||
*/
|
||||
export function parseMarkdownToHtml(markdown: string): string {
|
||||
try {
|
||||
// Use dynamic import for marked.js
|
||||
// Note: This is a helper for non-React contexts
|
||||
// In React components, use useStreamingContent hook instead
|
||||
return markdown // Placeholder - actual implementation requires async import
|
||||
} catch {
|
||||
return markdown
|
||||
}
|
||||
}
|
||||
30
frontend/src/hooks/useThinkSections.ts
Normal file
30
frontend/src/hooks/useThinkSections.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Hook for parsing markdown content with think sections.
|
||||
* Extracts <think>...</think> blocks and returns main content and reasoning separately.
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react'
|
||||
import { parseThinkSections } from '@/lib/graph/renderingUtils'
|
||||
|
||||
/**
|
||||
* Parse markdown content and extract think sections.
|
||||
* Returns main content (without think blocks) and reasoning content (from think blocks).
|
||||
*
|
||||
* @param content - The HTML/markdown content to parse
|
||||
* @param outputType - The output type ('image' or 'string')
|
||||
* @returns Object with main and think content
|
||||
*/
|
||||
export function useThinkSections(
|
||||
content: string | null,
|
||||
outputType: 'image' | 'string'
|
||||
): {
|
||||
main: string
|
||||
think: string
|
||||
} {
|
||||
return useMemo(() => {
|
||||
if (!content || outputType === 'image') {
|
||||
return { main: '', think: '' }
|
||||
}
|
||||
return parseThinkSections(content)
|
||||
}, [content, outputType])
|
||||
}
|
||||
Reference in New Issue
Block a user