claude-web-chat/fragments.go
djuka 3283888738
All checks were successful
Tests / unit-tests (push) Successful in 51s
Inicijalna implementacija Claude Web Chat (Faza 1 - CLI mod)
- Login sa session cookie autentifikacijom
- Lista projekata iz filesystem-a
- Chat sa Claude CLI preko WebSocket-a
- Streaming NDJSON parsiranje iz CLI stdout-a
- Sesija zivi nezavisno od browsera (reconnect replay)
- Sidebar sa .md fajlovima i markdown renderovanjem
- Dark tema, htmx + Go templates
- 47 unit testova

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:03:40 +00:00

72 lines
3.0 KiB
Go

package main
import (
"fmt"
"html"
"strings"
)
// FragmentUserMessage returns an HTML fragment for a user message.
func FragmentUserMessage(text string) string {
escaped := html.EscapeString(text)
return fmt.Sprintf(`<div id="chat-messages" hx-swap-oob="beforeend"><div class="message message-user">%s</div></div>`, escaped)
}
// FragmentAssistantStart returns the opening tag for an assistant message with streaming.
func FragmentAssistantStart(msgID string) string {
return fmt.Sprintf(`<div id="chat-messages" hx-swap-oob="beforeend"><div class="message message-assistant" id="%s"><div class="content"></div></div></div>`, msgID)
}
// FragmentAssistantChunk appends text to an existing assistant message.
func FragmentAssistantChunk(msgID, textChunk string) string {
escaped := html.EscapeString(textChunk)
return fmt.Sprintf(`<div id="%s" hx-swap-oob="beforeend:.content">%s</div>`, msgID, escaped)
}
// FragmentAssistantComplete replaces the content of an assistant message with final rendered content.
func FragmentAssistantComplete(msgID, htmlContent string) string {
return fmt.Sprintf(`<div id="%s" hx-swap-oob="innerHTML:.content">%s</div>`, msgID, htmlContent)
}
// FragmentToolCall returns an HTML fragment for a tool use notification.
func FragmentToolCall(toolName string, toolInput string) string {
escapedName := html.EscapeString(toolName)
escapedInput := html.EscapeString(toolInput)
if len(escapedInput) > 200 {
escapedInput = escapedInput[:200] + "..."
}
return fmt.Sprintf(`<div id="chat-messages" hx-swap-oob="beforeend"><div class="message message-tool"><div class="tool-name">%s</div><div>%s</div></div></div>`, escapedName, escapedInput)
}
// FragmentSystemMessage returns an HTML fragment for a system message.
func FragmentSystemMessage(text string) string {
escaped := html.EscapeString(text)
return fmt.Sprintf(`<div id="chat-messages" hx-swap-oob="beforeend"><div class="message message-system">%s</div></div>`, escaped)
}
// FragmentTypingIndicator shows or hides the typing indicator.
func FragmentTypingIndicator(show bool) string {
if show {
return `<div id="typing-indicator" hx-swap-oob="innerHTML"><span class="typing-indicator">Claude razmišlja<span class="dots">...</span></span></div>`
}
return `<div id="typing-indicator" hx-swap-oob="innerHTML"></div>`
}
// FragmentStatus updates the connection status indicator.
func FragmentStatus(connected bool) string {
if connected {
return `<span id="ws-status" hx-swap-oob="innerHTML" class="status connected">Povezan</span>`
}
return `<span id="ws-status" hx-swap-oob="innerHTML" class="status">Nepovezan</span>`
}
// FragmentClearInput clears the message input field.
func FragmentClearInput() string {
return `<textarea id="message-input" hx-swap-oob="outerHTML" name="message" class="chat-input" placeholder="Pošalji poruku..." rows="1"></textarea>`
}
// FragmentCombine joins multiple fragments into a single response.
func FragmentCombine(fragments ...string) string {
return strings.Join(fragments, "\n")
}