\n")
case "image":
url := ""
caption := ""
alt := ""
if u, ok := props["url"].(string); ok {
url = u
}
if c, ok := props["caption"].(string); ok {
caption = c
}
if a, ok := props["alt"].(string); ok {
alt = a
}
if alt == "" {
alt = caption
}
sb.WriteString(``)
fmt.Fprintf(&sb, ``, html.EscapeString(url), html.EscapeString(alt))
if caption != "" {
fmt.Fprintf(&sb, "%s", html.EscapeString(caption))
}
sb.WriteString("\n")
case "table":
sb.WriteString(`
`)
if tableContent, ok := block["content"].(map[string]any); ok {
if rows, ok := tableContent["rows"].([]any); ok && len(rows) > 0 {
renderTableRow := func(row any, isHeader bool) {
if rowMap, ok := row.(map[string]any); ok {
if cells, ok := rowMap["cells"].([]any); ok {
for _, cell := range cells {
cellTag := "td"
cellClass := "px-4 py-2 text-sm"
if isHeader {
cellTag = "th"
cellClass = "px-4 py-3 text-left text-sm font-semibold"
}
fmt.Fprintf(&sb, "<%s class=\"%s\">", cellTag, cellClass)
sb.WriteString(renderInlineContent(inlineContentFromRaw(cell)))
fmt.Fprintf(&sb, "%s>", cellTag)
}
}
}
}
sb.WriteString("
")
renderTableRow(rows[0], true)
sb.WriteString("
")
if len(rows) > 1 {
sb.WriteString("")
for _, row := range rows[1:] {
sb.WriteString("
")
renderTableRow(row, false)
sb.WriteString("
")
}
sb.WriteString("")
}
}
}
sb.WriteString("
\n")
case "references":
sb.WriteString("
\n")
sb.WriteString("
References
\n")
sb.WriteString("\n")
if itemsJSON, ok := props["items"].(string); ok && itemsJSON != "" {
var items []map[string]string
if err := json.Unmarshal([]byte(itemsJSON), &items); err == nil {
for _, item := range items {
text := html.EscapeString(item["text"])
url := item["url"]
if text == "" {
continue
}
if url != "" {
fmt.Fprintf(&sb, "