From 28ffc9c77be4ebe9e575d85c50a192a4d314e420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=CC=81scar=20M=2E=20Lage?= Date: Fri, 11 Oct 2024 22:44:16 +0200 Subject: [PATCH] Add markdown utils --- utils/markdown.go | 133 ++++++++++++++++++++++++++++++++++++++++++++++ utils/utils.go | 17 ------ 2 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 utils/markdown.go diff --git a/utils/markdown.go b/utils/markdown.go new file mode 100644 index 0000000..2a63441 --- /dev/null +++ b/utils/markdown.go @@ -0,0 +1,133 @@ +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"` + 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) + + // Define regex patterns to match specific fields in the frontmatter + fieldPatterns := map[string]string{ + "title": fmt.Sprintf(`(?m)^title: "(.*)"`), + "progress": fmt.Sprintf(`(?m)^progress: "(.*)"`), + "date": fmt.Sprintf(`(?m)^date: (\d+)$`), + "rate": fmt.Sprintf(`(?m)^rate: (\d+\.?\d*)$`), + } + + // Replace the relevant fields in the frontmatter using regex substitution + fileContent = updateFieldInFrontmatter(fileContent, "title", frontmatter.Title, fieldPatterns["title"]) + fileContent = updateFieldInFrontmatter(fileContent, "progress", frontmatter.Progress, fieldPatterns["progress"]) + fileContent = updateFieldInFrontmatter(fileContent, "date", fmt.Sprintf("%d", frontmatter.Date), fieldPatterns["date"]) + 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 +} + +// Helper function to update a specific field in the frontmatter +func updateFieldInFrontmatter(fileContent, field, newValue, pattern string) string { + re := regexp.MustCompile(pattern) + updatedContent := re.ReplaceAllString(fileContent, fmt.Sprintf("%s: \"%s\"", field, newValue)) + return updatedContent +} + +// 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 +} diff --git a/utils/utils.go b/utils/utils.go index 82d3db1..0ea6d96 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,13 +1,11 @@ package utils import ( - "bytes" "encoding/json" "fmt" "os" "regexp" "strings" - "text/template" "unicode" ) @@ -18,21 +16,6 @@ func CreateDirIfNotExists(dir string) error { return nil } -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) -} - func Debug(v interface{}, args ...string) { // utils.Debug(variable) debug, err := json.MarshalIndent(v, "", " ")