init
This commit is contained in:
133
internal/markdown/renderer.go
Normal file
133
internal/markdown/renderer.go
Normal file
@@ -0,0 +1,133 @@
|
||||
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(
|
||||
chromahtml.WithLineNumbers(true),
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// Convert to standard markdown link syntax
|
||||
return fmt.Sprintf("[%s](%s)", displayText, noteURL)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user