Created
May 6, 2026 14:33
-
-
Save toofishes/ea7d6444d8194cfc421db708821e902d to your computer and use it in GitHub Desktop.
Golang backend with a Tiptap helper sidecar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package sidecar | |
| import ( | |
| "bytes" | |
| "context" | |
| "encoding/json" | |
| "errors" | |
| "net/http" | |
| "os" | |
| ) | |
| // Mark represents a text mark in TipTap editor - mirroring the Typescript type. | |
| type Mark struct { | |
| Type string `json:"type"` | |
| Attrs map[string]any `json:"attrs,omitempty"` | |
| } | |
| // JSONContent represents the structure of the content in TipTap editor - mirroring the Typescript type. | |
| type JSONContent struct { | |
| Type string `json:"type,omitempty"` | |
| Attrs map[string]any `json:"attrs,omitempty"` | |
| Content []JSONContent `json:"content,omitempty"` | |
| Marks []Mark `json:"marks,omitempty"` | |
| Text *string `json:"text,omitempty"` | |
| } | |
| func sidecarURL() string { | |
| sidecarUrl := "http://localhost:9889" | |
| if envUrl, ok := os.LookupEnv("SIDECAR_URL"); ok { | |
| sidecarUrl = envUrl | |
| } | |
| return sidecarUrl | |
| } | |
| func postSidecarJSON[Req any, Resp any](ctx context.Context, client *http.Client, path string, reqBody Req, errPrefix string) (*Resp, error) { | |
| if client == nil { | |
| client = http.DefaultClient | |
| } | |
| body, err := json.Marshal(reqBody) | |
| if err != nil { | |
| return nil, err | |
| } | |
| req, err := http.NewRequestWithContext(ctx, http.MethodPost, sidecarURL()+path, bytes.NewReader(body)) | |
| if err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| req.Header.Set("Accept", "application/json") | |
| resp, err := client.Do(req) | |
| if err != nil { | |
| return nil, err | |
| } | |
| defer func() { _ = resp.Body.Close() }() | |
| if resp.StatusCode != http.StatusOK { | |
| return nil, errors.New(errPrefix + ": " + resp.Status) | |
| } | |
| var decoded Resp | |
| if err := json.NewDecoder(resp.Body).Decode(&decoded); err != nil { | |
| return nil, err | |
| } | |
| return &decoded, nil | |
| } | |
| type RenderTiptapResponse struct { | |
| HTML string `json:"html"` | |
| Markdown string `json:"markdown"` | |
| } | |
| func (c *JSONContent) RenderTiptap(ctx context.Context, client *http.Client, content *JSONContent) (*RenderTiptapResponse, error) { | |
| if content == nil { | |
| return nil, errors.New("content is nil") | |
| } | |
| return postSidecarJSON[*JSONContent, RenderTiptapResponse]( | |
| ctx, client, "/render-tiptap", content, "failed to render tiptap content") | |
| } | |
| type MarkdownToTiptapRequest struct { | |
| Markdown string `json:"markdown"` | |
| } | |
| type MarkdownToTiptapResponse struct { | |
| Tiptap JSONContent `json:"tiptap"` | |
| } | |
| func MarkdownToTiptap(ctx context.Context, client *http.Client, markdown string) (*JSONContent, error) { | |
| reqBody := MarkdownToTiptapRequest{ | |
| Markdown: markdown, | |
| } | |
| convertResponse, err := postSidecarJSON[MarkdownToTiptapRequest, MarkdownToTiptapResponse]( | |
| ctx, client, "/markdown-to-tiptap", reqBody, "failed to convert markdown to tiptap content") | |
| if err != nil { | |
| return nil, err | |
| } | |
| return &convertResponse.Tiptap, nil | |
| } | |
| type SanitizeHTMLRequest struct { | |
| HTML string `json:"html"` | |
| } | |
| type SanitizeHTMLResponse struct { | |
| SanitizedHTML string `json:"sanitized"` | |
| } | |
| func SanitizeHTML(ctx context.Context, client *http.Client, html string) (string, error) { | |
| reqBody := SanitizeHTMLRequest{ | |
| HTML: html, | |
| } | |
| sanitizeResponse, err := postSidecarJSON[SanitizeHTMLRequest, SanitizeHTMLResponse]( | |
| ctx, client, "/sanitize-html", reqBody, "failed to sanitize HTML") | |
| if err != nil { | |
| return "", err | |
| } | |
| return sanitizeResponse.SanitizedHTML, nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment