readysite / readysite.org / internal / sharing / markdown.go
1.5 KB
markdown.go
package sharing

import (
	"bytes"

	"github.com/microcosm-cc/bluemonday"
	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/extension"
	gmhtml "github.com/yuin/goldmark/renderer/html"
)

// sanitizer is a shared bluemonday policy for sanitizing rendered HTML.
// UGCPolicy allows safe formatting (p, h1-h6, a, img, code, pre, table, etc.)
// but strips script, onclick, iframe, style, and other dangerous elements.
var sanitizer = bluemonday.UGCPolicy()

// RenderMarkdown converts markdown content to sanitized HTML.
// Uses goldmark with WithUnsafe() so HTML in markdown is preserved for
// bluemonday to selectively filter, rather than being escaped wholesale.
func RenderMarkdown(content string) string {
	if content == "" {
		return ""
	}

	md := goldmark.New(
		goldmark.WithExtensions(extension.GFM),
		goldmark.WithRendererOptions(gmhtml.WithUnsafe()),
	)

	var buf bytes.Buffer
	if err := md.Convert([]byte(content), &buf); err != nil {
		return content // Return raw content on error
	}
	return sanitizer.Sanitize(buf.String())
}

// GetReadme returns the README.md content from the repository.
func GetReadme() (string, error) {
	return GetFile("README.md")
}

// GetReadmeHTML returns the README.md content rendered as HTML.
func GetReadmeHTML() string {
	content, err := GetReadme()
	if err != nil {
		return ""
	}
	return RenderMarkdown(content)
}

// HasReadme returns true if a README.md exists in the repository.
func HasReadme() bool {
	_, err := GetFile("README.md")
	return err == nil
}
← Back