feat: server-side Markdown rendering with goldmark v1.6.0
- Implement renderMarkdown() in http.go using goldmark - Add goldmark extension: GFM, TaskList, Typographer - Remove frontend regex-based markdown processing - Update go.mod/go.sum with goldmark dependency
This commit is contained in:
parent
efeedfcaae
commit
2e8d29bb96
4 changed files with 27 additions and 8 deletions
1
go.mod
1
go.mod
|
|
@ -17,6 +17,7 @@ require (
|
||||||
github.com/slack-go/slack v0.17.3
|
github.com/slack-go/slack v0.17.3
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/tencent-connect/botgo v0.2.1
|
github.com/tencent-connect/botgo v0.2.1
|
||||||
|
github.com/yuin/goldmark v1.6.0
|
||||||
golang.org/x/oauth2 v0.35.0
|
golang.org/x/oauth2 v0.35.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -149,6 +149,8 @@ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3i
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
||||||
|
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
golang.org/x/arch v0.24.0 h1:qlJ3M9upxvFfwRM51tTg3Yl+8CP9vCC1E7vlFpgv99Y=
|
golang.org/x/arch v0.24.0 h1:qlJ3M9upxvFfwRM51tTg3Yl+8CP9vCC1E7vlFpgv99Y=
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/yuin/goldmark"
|
||||||
|
"github.com/yuin/goldmark/extension"
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/pkg/bus"
|
"github.com/sipeed/picoclaw/pkg/bus"
|
||||||
"github.com/sipeed/picoclaw/pkg/config"
|
"github.com/sipeed/picoclaw/pkg/config"
|
||||||
|
|
@ -128,9 +131,12 @@ func (c *HTTPChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render Markdown to HTML before sending
|
||||||
|
renderedContent := renderMarkdown(msg.Content)
|
||||||
|
|
||||||
wsMsg := WSMessage{
|
wsMsg := WSMessage{
|
||||||
Type: "response",
|
Type: "response",
|
||||||
Content: msg.Content,
|
Content: renderedContent,
|
||||||
ChatID: msg.ChatID,
|
ChatID: msg.ChatID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,3 +279,20 @@ func (c *HTTPChannel) removeSession(chatID string) {
|
||||||
func generateChatID(r *http.Request) string {
|
func generateChatID(r *http.Request) string {
|
||||||
return fmt.Sprintf("web_%d", time.Now().UnixNano())
|
return fmt.Sprintf("web_%d", time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renderMarkdown converts Markdown to HTML using goldmark
|
||||||
|
func renderMarkdown(input string) string {
|
||||||
|
md := goldmark.New(
|
||||||
|
goldmark.WithExtensions(
|
||||||
|
extension.GFM,
|
||||||
|
extension.TaskList,
|
||||||
|
extension.Typographer,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
var buf strings.Builder
|
||||||
|
if err := md.Convert([]byte(input), &buf); err != nil {
|
||||||
|
return input // fallback to plain text on error
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
@ -247,13 +247,6 @@
|
||||||
function addMessage(content, type) {
|
function addMessage(content, type) {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.className = `message ${type}`;
|
div.className = `message ${type}`;
|
||||||
|
|
||||||
// Simple markdown-like formatting for code blocks
|
|
||||||
content = content.replace(/```(\w*)\n?([\s\S]*?)```/g, '<pre><code>$2</code></pre>');
|
|
||||||
content = content.replace(/`([^`]+)`/g, '<code>$1</code>');
|
|
||||||
content = content.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
||||||
content = content.replace(/\n/g, '<br>');
|
|
||||||
|
|
||||||
div.innerHTML = content;
|
div.innerHTML = content;
|
||||||
chatContainer.appendChild(div);
|
chatContainer.appendChild(div);
|
||||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue