143 lines
3.8 KiB
Go
143 lines
3.8 KiB
Go
package markdown
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
|
|
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
|
"github.com/yuin/goldmark"
|
|
highlighting "github.com/yuin/goldmark-highlighting/v2"
|
|
"github.com/yuin/goldmark/extension"
|
|
"github.com/yuin/goldmark/parser"
|
|
"github.com/yuin/goldmark/renderer/html"
|
|
|
|
"gobsidian/internal/config"
|
|
)
|
|
|
|
type Renderer struct {
|
|
md goldmark.Markdown
|
|
config *config.Config
|
|
}
|
|
|
|
func NewRenderer(cfg *config.Config) *Renderer {
|
|
md := goldmark.New(
|
|
goldmark.WithExtensions(
|
|
extension.GFM,
|
|
extension.Table,
|
|
extension.Strikethrough,
|
|
extension.TaskList,
|
|
highlighting.NewHighlighting(
|
|
highlighting.WithStyle("github-dark"),
|
|
highlighting.WithFormatOptions(
|
|
// Disable line numbers in code blocks for cleaner display
|
|
chromahtml.WithLineNumbers(false),
|
|
chromahtml.WithClasses(true),
|
|
),
|
|
),
|
|
),
|
|
goldmark.WithParserOptions(
|
|
parser.WithAutoHeadingID(),
|
|
),
|
|
goldmark.WithRendererOptions(
|
|
html.WithHardWraps(),
|
|
html.WithXHTML(),
|
|
html.WithUnsafe(),
|
|
),
|
|
)
|
|
|
|
return &Renderer{
|
|
md: md,
|
|
config: cfg,
|
|
}
|
|
}
|
|
|
|
func (r *Renderer) RenderMarkdown(content string, notePath string) (string, error) {
|
|
// Process Obsidian image syntax
|
|
content = r.processObsidianImages(content, notePath)
|
|
|
|
// Process Obsidian links
|
|
content = r.processObsidianLinks(content)
|
|
|
|
var buf bytes.Buffer
|
|
if err := r.md.Convert([]byte(content), &buf); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return buf.String(), nil
|
|
}
|
|
|
|
func (r *Renderer) processObsidianImages(content string, notePath string) string {
|
|
// Regex to match Obsidian image syntax: ![[image.png]] or ![[folder/image.png]]
|
|
obsidianImageRegex := regexp.MustCompile(`!\[\[([^\]]+\.(png|jpg|jpeg|gif|webp))\]\]`)
|
|
|
|
return obsidianImageRegex.ReplaceAllStringFunc(content, func(match string) string {
|
|
// Extract the image path from the match
|
|
submatch := obsidianImageRegex.FindStringSubmatch(match)
|
|
if len(submatch) < 2 {
|
|
return match
|
|
}
|
|
|
|
imagePath := submatch[1]
|
|
|
|
// Get storage info based on current note path
|
|
// storageInfo := utils.GetImageStorageInfo(notePath, r.config)
|
|
|
|
// Clean up the path
|
|
cleanPath := filepath.Clean(imagePath)
|
|
cleanPath = strings.ReplaceAll(cleanPath, "\\", "/")
|
|
cleanPath = strings.Trim(cleanPath, "/")
|
|
|
|
// Generate the appropriate URL based on storage mode
|
|
var imageURL string
|
|
|
|
switch r.config.ImageStorageMode {
|
|
case 2: // Mode 2: Specific storage folder - just the filename
|
|
imageURL = fmt.Sprintf("/serve_stored_image/%s", filepath.Base(cleanPath))
|
|
default: // For modes 1, 3, and 4
|
|
imageURL = fmt.Sprintf("/serve_attached_image/%s", cleanPath)
|
|
}
|
|
|
|
// Prefix with configured URL base
|
|
if bp := r.config.URLPrefix; bp != "" {
|
|
imageURL = bp + imageURL
|
|
}
|
|
|
|
// Convert to standard markdown image syntax
|
|
alt := filepath.Base(imagePath)
|
|
return fmt.Sprintf("", alt, imageURL)
|
|
})
|
|
}
|
|
|
|
func (r *Renderer) processObsidianLinks(content string) string {
|
|
// Regex to match Obsidian wiki-links: [[Note Name]] or [[Note Name|Display Text]]
|
|
obsidianLinkRegex := regexp.MustCompile(`\[\[([^\]|]+)(\|([^\]]+))?\]\]`)
|
|
|
|
return obsidianLinkRegex.ReplaceAllStringFunc(content, func(match string) string {
|
|
submatch := obsidianLinkRegex.FindStringSubmatch(match)
|
|
if len(submatch) < 2 {
|
|
return match
|
|
}
|
|
|
|
noteName := strings.TrimSpace(submatch[1])
|
|
displayText := noteName
|
|
|
|
// If there's custom display text (after |), use it
|
|
if len(submatch) >= 4 && submatch[3] != "" {
|
|
displayText = strings.TrimSpace(submatch[3])
|
|
}
|
|
|
|
// Convert note name to URL-friendly format
|
|
noteURL := strings.ReplaceAll(noteName, " ", "%20")
|
|
noteURL = fmt.Sprintf("/note/%s.md", noteURL)
|
|
if bp := r.config.URLPrefix; bp != "" {
|
|
noteURL = bp + noteURL
|
|
}
|
|
|
|
// Convert to standard markdown link syntax
|
|
return fmt.Sprintf("[%s](%s)", displayText, noteURL)
|
|
})
|
|
}
|