hugo-medialog/utils/markdown.go

132 lines
3.7 KiB
Go
Raw Normal View History

2024-10-11 20:44:16 +00:00
package utils
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
"text/template"
"gopkg.in/yaml.v2"
)
type FrontMatter struct {
Title string `yaml:"title"`
Rate float64 `yaml:"rate"`
Progress string `yaml:"progress"`
2024-10-14 11:43:41 +00:00
Episode string `yaml:"episode"`
2024-10-11 20:44:16 +00:00
Date string `yaml:"date"`
}
func GenerateMarkdown(templatePath string, outputPath string, data map[string]interface{}) error {
tmpl, err := template.ParseFiles(templatePath)
if err != nil {
return err
}
var output bytes.Buffer
err = tmpl.Execute(&output, data)
if err != nil {
return err
}
return os.WriteFile(outputPath, output.Bytes(), 0644)
}
// LoadMarkdown loads the frontmatter and content from an existing markdown file
func LoadMarkdown(filepath string) (FrontMatter, string, error) {
var frontmatter FrontMatter
var contentBuilder strings.Builder
inFrontmatter := false
frontmatterComplete := false
file, err := os.Open(filepath)
if err != nil {
return frontmatter, "", err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
// Detect the start and end of the frontmatter block
if line == "---" && !inFrontmatter {
inFrontmatter = true
continue
} else if line == "---" && inFrontmatter {
frontmatterComplete = true
continue
}
if inFrontmatter && !frontmatterComplete {
// Continue reading the frontmatter
contentBuilder.WriteString(line + "\n")
} else if frontmatterComplete {
// Read the rest of the markdown content
contentBuilder.WriteString(line + "\n")
}
}
// Unmarshal frontmatter into the struct
if err := yaml.Unmarshal([]byte(contentBuilder.String()), &frontmatter); err != nil {
return frontmatter, "", fmt.Errorf("error unmarshalling frontmatter: %v", err)
}
// Read the markdown content
contentBytes, err := ioutil.ReadAll(file)
if err != nil {
return frontmatter, "", err
}
return frontmatter, string(contentBytes), nil
}
// SaveUpdatedMarkdown updates only the specific fields in the frontmatter without altering the content
func SaveUpdatedMarkdown(filepath string, frontmatter FrontMatter, content string) error {
// Read the entire file as a string
fileBytes, err := ioutil.ReadFile(filepath)
if err != nil {
return err
}
// Convert file content to string
fileContent := string(fileBytes)
fieldPatterns := map[string]string{
2024-10-14 11:43:41 +00:00
"progress": `(?m)^progress: "(.*)%"$`,
"episode": `(?m)^episode: "(.*)"$`,
"date": `(?m)^date: "(.*)"$`,
"rate": `(?m)^rate: (\d+\.?\d*)$`,
2024-10-11 20:44:16 +00:00
}
2024-10-14 11:43:41 +00:00
// Fields replacement
fileContent = updateFieldInFrontmatter(fileContent, "progress", fmt.Sprintf("\"%s\"", frontmatter.Progress), fieldPatterns["progress"])
fileContent = updateFieldInFrontmatter(fileContent, "episode", fmt.Sprintf("\"%s\"", frontmatter.Episode), fieldPatterns["episode"])
fileContent = updateFieldInFrontmatter(fileContent, "date", fmt.Sprintf("\"%s\"", frontmatter.Date), fieldPatterns["date"])
2024-10-11 20:44:16 +00:00
fileContent = updateFieldInFrontmatterFloat(fileContent, "rate", frontmatter.Rate, fieldPatterns["rate"])
// Write the updated content back to the file
err = ioutil.WriteFile(filepath, []byte(fileContent), 0644)
if err != nil {
return err
}
return nil
}
2024-10-14 11:43:41 +00:00
func updateFieldInFrontmatter(content, field, newValue, pattern string) string {
2024-10-11 20:44:16 +00:00
re := regexp.MustCompile(pattern)
2024-10-14 11:43:41 +00:00
return re.ReplaceAllString(content, fmt.Sprintf("%s: %s", field, newValue))
2024-10-11 20:44:16 +00:00
}
// Helper function to update a float64 field in the frontmatter (for numerical values like rate)
func updateFieldInFrontmatterFloat(fileContent string, field string, newValue float64, pattern string) string {
re := regexp.MustCompile(pattern)
updatedContent := re.ReplaceAllString(fileContent, fmt.Sprintf("%s: %.1f", field, newValue))
return updatedContent
}