api cleanup
This commit is contained in:
parent
3e7e625051
commit
d81cfa5e67
|
|
@ -190,15 +190,19 @@ func windowMode(args []string) error {
|
||||||
|
|
||||||
// Update frontmatter if applicable
|
// Update frontmatter if applicable
|
||||||
if supportsFrontmatter && len(body) > 0 {
|
if supportsFrontmatter && len(body) > 0 {
|
||||||
// Create new frontmatter
|
// Parse existing frontmatter to preserve Identifier and FileType
|
||||||
fm := &metadata.FrontMatter{
|
existing, err := metadata.ParseFrontMatter(string(body), ext)
|
||||||
Title: title,
|
if err != nil {
|
||||||
Tags: tags,
|
return fmt.Errorf("failed to parse existing frontmatter: %w", err)
|
||||||
Signature: signature,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update frontmatter in content
|
// Update only the fields that changed from rename
|
||||||
newContent, err := metadata.UpdateFrontMatter(string(body), fm)
|
existing.Title = title
|
||||||
|
existing.Tags = tags
|
||||||
|
existing.Signature = signature
|
||||||
|
|
||||||
|
// Apply updated frontmatter to content
|
||||||
|
newContent, err := metadata.Apply(string(body), existing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update frontmatter: %w", err)
|
return fmt.Errorf("failed to update frontmatter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,14 @@ func HandleUpdateEvent(f *client.Fsys, identifier, denoteDir string) error {
|
||||||
// Only update frontmatter if file exists (skip if not yet created via Put)
|
// Only update frontmatter if file exists (skip if not yet created via Put)
|
||||||
if _, err := os.Stat(path); err == nil && SupportsFrontMatter(path) {
|
if _, err := os.Stat(path); err == nil && SupportsFrontMatter(path) {
|
||||||
ext := strings.ToLower(filepath.Ext(path))
|
ext := strings.ToLower(filepath.Ext(path))
|
||||||
var fileType string
|
var fileType metadata.FileType
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".org":
|
case ".org":
|
||||||
fileType = "org"
|
fileType = metadata.FileTypeOrg
|
||||||
case ".md":
|
case ".md":
|
||||||
fileType = "md-yaml"
|
fileType = metadata.FileTypeMdYaml
|
||||||
case ".txt":
|
case ".txt":
|
||||||
fileType = "txt"
|
fileType = metadata.FileTypeTxt
|
||||||
}
|
}
|
||||||
|
|
||||||
fm := &metadata.FrontMatter{
|
fm := &metadata.FrontMatter{
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,10 @@ func UpdateFrontMatter(path string, fm *metadata.FrontMatter) error {
|
||||||
return fmt.Errorf("failed to read file: %w", err)
|
return fmt.Errorf("failed to read file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update front matter (pure function)
|
// Apply front matter to content
|
||||||
newContent, err := metadata.UpdateFrontMatter(string(content), fm)
|
newContent, err := metadata.Apply(string(content), fm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update front matter: %w", err)
|
return fmt.Errorf("failed to apply front matter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write back to file
|
// Write back to file
|
||||||
|
|
|
||||||
11
main.go
11
main.go
|
|
@ -2,9 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"denote/internal/disk"
|
"denote/internal/disk"
|
||||||
"denote/pkg/metadata"
|
|
||||||
p9client "denote/internal/p9/client"
|
p9client "denote/internal/p9/client"
|
||||||
p9server "denote/internal/p9/server"
|
p9server "denote/internal/p9/server"
|
||||||
|
"denote/pkg/metadata"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -21,7 +21,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
wname = "/Denote/"
|
wname = "/Denote/"
|
||||||
ftype = "md-yaml"
|
ftype = metadata.FileTypeMdYaml
|
||||||
)
|
)
|
||||||
|
|
||||||
var denoteDir = os.Getenv("HOME") + "/doc"
|
var denoteDir = os.Getenv("HOME") + "/doc"
|
||||||
|
|
@ -112,7 +112,12 @@ func handleNewEvent(f *client.Fsys, identifier, denoteDir string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, content := metadata.GenerateNote(targetDir, title, signature, tags, ftype)
|
newIdentifier := metadata.GenerateIdentifier()
|
||||||
|
ext := metadata.GetExtension(ftype)
|
||||||
|
filename := metadata.BuildFilename(newIdentifier, signature, title, tags, ext)
|
||||||
|
path := filepath.Join(targetDir, filename)
|
||||||
|
fm := metadata.NewFrontMatter(title, signature, tags, ftype, newIdentifier)
|
||||||
|
content := string(fm.Bytes())
|
||||||
|
|
||||||
if err := p9client.WriteFile(f, "n/"+identifier+"/path", path); err != nil {
|
if err := p9client.WriteFile(f, "n/"+identifier+"/path", path); err != nil {
|
||||||
return fmt.Errorf("failed to update path in metadata: %w", err)
|
return fmt.Errorf("failed to update path in metadata: %w", err)
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Templates for denote frontmatter (org, md, txt)
|
// Templates for denote frontmatter (org, md, txt)
|
||||||
var templates = map[string]string{
|
var templates = map[FileType]string{
|
||||||
"org": `#+title: %s
|
FileTypeOrg: `#+title: %s
|
||||||
#+date: %s
|
#+date: %s
|
||||||
#+filetags: %s
|
#+filetags: %s
|
||||||
#+identifier: %s
|
#+identifier: %s
|
||||||
#+signature: %s
|
#+signature: %s
|
||||||
|
|
||||||
`,
|
`,
|
||||||
"md-yaml": `---
|
FileTypeMdYaml: `---
|
||||||
title: %s
|
title: %s
|
||||||
date: %s
|
date: %s
|
||||||
tags: %s
|
tags: %s
|
||||||
|
|
@ -25,7 +25,7 @@ signature: %s
|
||||||
---
|
---
|
||||||
|
|
||||||
`,
|
`,
|
||||||
"md-toml": `+++
|
FileTypeMdToml: `+++
|
||||||
title = %s
|
title = %s
|
||||||
date = %s
|
date = %s
|
||||||
tags = %s
|
tags = %s
|
||||||
|
|
@ -34,7 +34,7 @@ signature = %s
|
||||||
+++
|
+++
|
||||||
|
|
||||||
`,
|
`,
|
||||||
"txt": `title: %s
|
FileTypeTxt: `title: %s
|
||||||
date: %s
|
date: %s
|
||||||
tags: %s
|
tags: %s
|
||||||
identifier: %s
|
identifier: %s
|
||||||
|
|
@ -44,24 +44,39 @@ signature: %s
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileType represents supported file formats for denote notes
|
||||||
|
type FileType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FileTypeOrg FileType = "org"
|
||||||
|
FileTypeMdYaml FileType = "md-yaml"
|
||||||
|
FileTypeMdToml FileType = "md-toml"
|
||||||
|
FileTypeTxt FileType = "txt"
|
||||||
|
)
|
||||||
|
|
||||||
// fileExtensions contains the list of file extensions
|
// fileExtensions contains the list of file extensions
|
||||||
// for which Denote should add front matter.
|
// for which Denote should add front matter.
|
||||||
var fileExtensions = map[string]string{
|
var fileExtensions = map[FileType]string{
|
||||||
"org": ".org",
|
FileTypeOrg: ".org",
|
||||||
"md-yaml": ".md",
|
FileTypeMdYaml: ".md",
|
||||||
"md-toml": ".md",
|
FileTypeMdToml: ".md",
|
||||||
"txt": ".txt",
|
FileTypeTxt: ".txt",
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExtension returns the file extension for a given file type.
|
||||||
|
func GetExtension(fileType FileType) string {
|
||||||
|
return fileExtensions[fileType]
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatTags formats tags according to file type
|
// FormatTags formats tags according to file type
|
||||||
func FormatTags(tags []string, fileType string) string {
|
func FormatTags(tags []string, fileType FileType) string {
|
||||||
if len(tags) == 0 {
|
if len(tags) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch fileType {
|
switch fileType {
|
||||||
case "org":
|
case FileTypeOrg:
|
||||||
return ":" + strings.Join(tags, ":") + ":"
|
return ":" + strings.Join(tags, ":") + ":"
|
||||||
case "md-yaml", "md-toml":
|
case FileTypeMdYaml, FileTypeMdToml:
|
||||||
return "[" + strings.Join(tags, ", ") + "]"
|
return "[" + strings.Join(tags, ", ") + "]"
|
||||||
default:
|
default:
|
||||||
return strings.Join(tags, " ")
|
return strings.Join(tags, " ")
|
||||||
|
|
@ -74,7 +89,22 @@ type FrontMatter struct {
|
||||||
Tags []string
|
Tags []string
|
||||||
Identifier string
|
Identifier string
|
||||||
Signature string
|
Signature string
|
||||||
FileType string // org, md-yaml, md-toml, txt
|
FileType FileType
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the formatted frontmatter content as bytes
|
||||||
|
func (fm *FrontMatter) Bytes() []byte {
|
||||||
|
template := templates[fm.FileType]
|
||||||
|
dateStr := time.Now().Format("2006-01-02 Mon 15:04")
|
||||||
|
|
||||||
|
// For org-mode, wrap date in brackets for timestamp
|
||||||
|
if fm.FileType == FileTypeOrg {
|
||||||
|
dateStr = "[" + dateStr + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
keywordsStr := FormatTags(fm.Tags, fm.FileType)
|
||||||
|
content := fmt.Sprintf(template, fm.Title, dateStr, keywordsStr, fm.Identifier, fm.Signature)
|
||||||
|
return []byte(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseFrontMatter extracts front matter from file content.
|
// ParseFrontMatter extracts front matter from file content.
|
||||||
|
|
@ -87,7 +117,7 @@ func ParseFrontMatter(content string, ext string) (*FrontMatter, error) {
|
||||||
|
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".org":
|
case ".org":
|
||||||
fm.FileType = "org"
|
fm.FileType = FileTypeOrg
|
||||||
if m := regexp.MustCompile(`(?m)^#\+title:[ \t]*(.+)$`).FindStringSubmatch(text); m != nil {
|
if m := regexp.MustCompile(`(?m)^#\+title:[ \t]*(.+)$`).FindStringSubmatch(text); m != nil {
|
||||||
fm.Title = strings.TrimSpace(m[1])
|
fm.Title = strings.TrimSpace(m[1])
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +135,7 @@ func ParseFrontMatter(content string, ext string) (*FrontMatter, error) {
|
||||||
// Try YAML first
|
// Try YAML first
|
||||||
yamlRe := regexp.MustCompile(`(?ms)^---\n(.*?)\n---`)
|
yamlRe := regexp.MustCompile(`(?ms)^---\n(.*?)\n---`)
|
||||||
if m := yamlRe.FindStringSubmatch(text); m != nil {
|
if m := yamlRe.FindStringSubmatch(text); m != nil {
|
||||||
fm.FileType = "md-yaml"
|
fm.FileType = FileTypeMdYaml
|
||||||
yamlContent := m[1]
|
yamlContent := m[1]
|
||||||
if m := regexp.MustCompile(`(?m)^title:[ \t]*["']?(.+?)["']?$`).FindStringSubmatch(yamlContent); m != nil {
|
if m := regexp.MustCompile(`(?m)^title:[ \t]*["']?(.+?)["']?$`).FindStringSubmatch(yamlContent); m != nil {
|
||||||
fm.Title = strings.TrimSpace(m[1])
|
fm.Title = strings.TrimSpace(m[1])
|
||||||
|
|
@ -127,7 +157,7 @@ func ParseFrontMatter(content string, ext string) (*FrontMatter, error) {
|
||||||
// Try TOML
|
// Try TOML
|
||||||
tomlRe := regexp.MustCompile(`(?ms)^\+\+\+\n(.*?)\n\+\+\+`)
|
tomlRe := regexp.MustCompile(`(?ms)^\+\+\+\n(.*?)\n\+\+\+`)
|
||||||
if m := tomlRe.FindStringSubmatch(text); m != nil {
|
if m := tomlRe.FindStringSubmatch(text); m != nil {
|
||||||
fm.FileType = "md-toml"
|
fm.FileType = FileTypeMdToml
|
||||||
tomlContent := m[1]
|
tomlContent := m[1]
|
||||||
if m := regexp.MustCompile(`(?m)^title[ \t]*=[ \t]*["']?(.+?)["']?$`).FindStringSubmatch(tomlContent); m != nil {
|
if m := regexp.MustCompile(`(?m)^title[ \t]*=[ \t]*["']?(.+?)["']?$`).FindStringSubmatch(tomlContent); m != nil {
|
||||||
fm.Title = strings.TrimSpace(m[1])
|
fm.Title = strings.TrimSpace(m[1])
|
||||||
|
|
@ -149,7 +179,7 @@ func ParseFrontMatter(content string, ext string) (*FrontMatter, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case ".txt":
|
case ".txt":
|
||||||
fm.FileType = "txt"
|
fm.FileType = FileTypeTxt
|
||||||
if m := regexp.MustCompile(`(?m)^title:[ \t]*(.+)$`).FindStringSubmatch(text); m != nil {
|
if m := regexp.MustCompile(`(?m)^title:[ \t]*(.+)$`).FindStringSubmatch(text); m != nil {
|
||||||
fm.Title = strings.TrimSpace(m[1])
|
fm.Title = strings.TrimSpace(m[1])
|
||||||
}
|
}
|
||||||
|
|
@ -167,25 +197,15 @@ func ParseFrontMatter(content string, ext string) (*FrontMatter, error) {
|
||||||
return fm, nil
|
return fm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFrontMatter updates front matter in file content and returns the new content.
|
// Apply applies front matter to file content, replacing existing front matter if present.
|
||||||
// originalContent is the current file content, fm is the new front matter to apply.
|
// originalContent is the current file content, fm is the new front matter to apply.
|
||||||
func UpdateFrontMatter(originalContent string, fm *FrontMatter) (string, error) {
|
func Apply(originalContent string, fm *FrontMatter) (string, error) {
|
||||||
text := originalContent
|
text := originalContent
|
||||||
|
newFrontMatter := string(fm.Bytes())
|
||||||
dateStr := time.Now().Format("2006-01-02 Mon 15:04")
|
|
||||||
keywordsStr := FormatTags(fm.Tags, fm.FileType)
|
|
||||||
|
|
||||||
// For org-mode, wrap date in brackets for timestamp
|
|
||||||
if fm.FileType == "org" {
|
|
||||||
dateStr = "[" + dateStr + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
template := templates[fm.FileType]
|
|
||||||
newFrontMatter := fmt.Sprintf(template, fm.Title, dateStr, keywordsStr, fm.Identifier, fm.Signature)
|
|
||||||
|
|
||||||
var newText string
|
var newText string
|
||||||
switch fm.FileType {
|
switch fm.FileType {
|
||||||
case "org":
|
case FileTypeOrg:
|
||||||
// Find end of front matter (first blank line or non-#+ line)
|
// Find end of front matter (first blank line or non-#+ line)
|
||||||
lines := strings.Split(text, "\n")
|
lines := strings.Split(text, "\n")
|
||||||
endIdx := 0
|
endIdx := 0
|
||||||
|
|
@ -205,7 +225,7 @@ func UpdateFrontMatter(originalContent string, fm *FrontMatter) (string, error)
|
||||||
newText = newFrontMatter + text
|
newText = newFrontMatter + text
|
||||||
}
|
}
|
||||||
|
|
||||||
case "md-yaml":
|
case FileTypeMdYaml:
|
||||||
// Replace YAML front matter (match trailing blank lines to avoid duplication)
|
// Replace YAML front matter (match trailing blank lines to avoid duplication)
|
||||||
re := regexp.MustCompile(`(?s)^---\n.*?\n---\n\n*`)
|
re := regexp.MustCompile(`(?s)^---\n.*?\n---\n\n*`)
|
||||||
if re.MatchString(text) {
|
if re.MatchString(text) {
|
||||||
|
|
@ -214,7 +234,7 @@ func UpdateFrontMatter(originalContent string, fm *FrontMatter) (string, error)
|
||||||
newText = newFrontMatter + text
|
newText = newFrontMatter + text
|
||||||
}
|
}
|
||||||
|
|
||||||
case "md-toml":
|
case FileTypeMdToml:
|
||||||
// Replace TOML front matter (match trailing blank lines to avoid duplication)
|
// Replace TOML front matter (match trailing blank lines to avoid duplication)
|
||||||
re := regexp.MustCompile(`(?s)^\+\+\+\n.*?\n\+\+\+\n\n*`)
|
re := regexp.MustCompile(`(?s)^\+\+\+\n.*?\n\+\+\+\n\n*`)
|
||||||
if re.MatchString(text) {
|
if re.MatchString(text) {
|
||||||
|
|
@ -223,7 +243,7 @@ func UpdateFrontMatter(originalContent string, fm *FrontMatter) (string, error)
|
||||||
newText = newFrontMatter + text
|
newText = newFrontMatter + text
|
||||||
}
|
}
|
||||||
|
|
||||||
case "txt":
|
case FileTypeTxt:
|
||||||
// Replace text front matter (match trailing blank lines to avoid duplication)
|
// Replace text front matter (match trailing blank lines to avoid duplication)
|
||||||
re := regexp.MustCompile(`(?s)^title:.*?\n-+\n\n*`)
|
re := regexp.MustCompile(`(?s)^title:.*?\n-+\n\n*`)
|
||||||
if re.MatchString(text) {
|
if re.MatchString(text) {
|
||||||
|
|
@ -238,16 +258,13 @@ func UpdateFrontMatter(originalContent string, fm *FrontMatter) (string, error)
|
||||||
return newText, nil
|
return newText, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate generates front matter content for given parameters
|
// NewFrontMatter creates a new FrontMatter struct from given parameters
|
||||||
func Generate(title, signature string, tags []string, fileType, identifier string) string {
|
func NewFrontMatter(title, signature string, tags []string, fileType FileType, identifier string) *FrontMatter {
|
||||||
template := templates[fileType]
|
return &FrontMatter{
|
||||||
dateStr := time.Now().Format("2006-01-02 Mon 15:04")
|
Title: title,
|
||||||
|
Tags: tags,
|
||||||
// For org-mode, wrap date in brackets for timestamp
|
Identifier: identifier,
|
||||||
if fileType == "org" {
|
Signature: signature,
|
||||||
dateStr = "[" + dateStr + "]"
|
FileType: fileType,
|
||||||
}
|
}
|
||||||
|
|
||||||
keywordsStr := FormatTags(tags, fileType)
|
|
||||||
return fmt.Sprintf(template, title, dateStr, keywordsStr, identifier, signature)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,73 +12,73 @@ func TestFormatTags(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
tags []string
|
tags []string
|
||||||
fileType string
|
fileType FileType
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "org with multiple tags",
|
name: "org with multiple tags",
|
||||||
tags: []string{"tag1", "tag2"},
|
tags: []string{"tag1", "tag2"},
|
||||||
fileType: "org",
|
fileType: FileTypeOrg,
|
||||||
want: ":tag1:tag2:",
|
want: ":tag1:tag2:",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "org with single tag",
|
name: "org with single tag",
|
||||||
tags: []string{"single"},
|
tags: []string{"single"},
|
||||||
fileType: "org",
|
fileType: FileTypeOrg,
|
||||||
want: ":single:",
|
want: ":single:",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "org with empty tags",
|
name: "org with empty tags",
|
||||||
tags: []string{},
|
tags: []string{},
|
||||||
fileType: "org",
|
fileType: FileTypeOrg,
|
||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-yaml with multiple tags",
|
name: "md-yaml with multiple tags",
|
||||||
tags: []string{"tag1", "tag2"},
|
tags: []string{"tag1", "tag2"},
|
||||||
fileType: "md-yaml",
|
fileType: FileTypeMdYaml,
|
||||||
want: "[tag1, tag2]",
|
want: "[tag1, tag2]",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-yaml with single tag",
|
name: "md-yaml with single tag",
|
||||||
tags: []string{"single"},
|
tags: []string{"single"},
|
||||||
fileType: "md-yaml",
|
fileType: FileTypeMdYaml,
|
||||||
want: "[single]",
|
want: "[single]",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-yaml with empty tags",
|
name: "md-yaml with empty tags",
|
||||||
tags: []string{},
|
tags: []string{},
|
||||||
fileType: "md-yaml",
|
fileType: FileTypeMdYaml,
|
||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-toml with multiple tags",
|
name: "md-toml with multiple tags",
|
||||||
tags: []string{"tag1", "tag2"},
|
tags: []string{"tag1", "tag2"},
|
||||||
fileType: "md-toml",
|
fileType: FileTypeMdToml,
|
||||||
want: "[tag1, tag2]",
|
want: "[tag1, tag2]",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-toml with empty tags",
|
name: "md-toml with empty tags",
|
||||||
tags: []string{},
|
tags: []string{},
|
||||||
fileType: "md-toml",
|
fileType: FileTypeMdToml,
|
||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt with multiple tags",
|
name: "txt with multiple tags",
|
||||||
tags: []string{"tag1", "tag2"},
|
tags: []string{"tag1", "tag2"},
|
||||||
fileType: "txt",
|
fileType: FileTypeTxt,
|
||||||
want: "tag1 tag2",
|
want: "tag1 tag2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt with single tag",
|
name: "txt with single tag",
|
||||||
tags: []string{"single"},
|
tags: []string{"single"},
|
||||||
fileType: "txt",
|
fileType: FileTypeTxt,
|
||||||
want: "single",
|
want: "single",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt with empty tags",
|
name: "txt with empty tags",
|
||||||
tags: []string{},
|
tags: []string{},
|
||||||
fileType: "txt",
|
fileType: FileTypeTxt,
|
||||||
want: "",
|
want: "",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -93,22 +93,22 @@ func TestFormatTags(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGenerate validates front matter generation for all file types
|
// TestFrontMatterBytes validates front matter formatting for all file types
|
||||||
// Maps to dt-denote--format-front-matter from original tests
|
// Maps to dt-denote--format-front-matter from original tests
|
||||||
func TestGenerate(t *testing.T) {
|
func TestFrontMatterBytes(t *testing.T) {
|
||||||
identifier := "20240101T120000"
|
identifier := "20240101T120000"
|
||||||
title := "Test Note"
|
title := "Test Note"
|
||||||
tags := []string{"tag1", "tag2"}
|
tags := []string{"tag1", "tag2"}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fileType string
|
fileType FileType
|
||||||
wantContains []string
|
wantContains []string
|
||||||
wantNotContains []string
|
wantNotContains []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "org format",
|
name: "org format",
|
||||||
fileType: "org",
|
fileType: FileTypeOrg,
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"#+title: Test Note",
|
"#+title: Test Note",
|
||||||
"#+filetags: :tag1:tag2:",
|
"#+filetags: :tag1:tag2:",
|
||||||
|
|
@ -118,7 +118,7 @@ func TestGenerate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-yaml format",
|
name: "md-yaml format",
|
||||||
fileType: "md-yaml",
|
fileType: FileTypeMdYaml,
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"---",
|
"---",
|
||||||
"title: Test Note",
|
"title: Test Note",
|
||||||
|
|
@ -129,7 +129,7 @@ func TestGenerate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-toml format",
|
name: "md-toml format",
|
||||||
fileType: "md-toml",
|
fileType: FileTypeMdToml,
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"+++",
|
"+++",
|
||||||
"title = Test Note",
|
"title = Test Note",
|
||||||
|
|
@ -140,7 +140,7 @@ func TestGenerate(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt format",
|
name: "txt format",
|
||||||
fileType: "txt",
|
fileType: FileTypeTxt,
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"title: Test Note",
|
"title: Test Note",
|
||||||
"tags: tag1 tag2",
|
"tags: tag1 tag2",
|
||||||
|
|
@ -153,64 +153,64 @@ func TestGenerate(t *testing.T) {
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got := Generate(title, "", tags, tt.fileType, identifier)
|
fm := NewFrontMatter(title, "", tags, tt.fileType, identifier)
|
||||||
|
got := string(fm.Bytes())
|
||||||
|
|
||||||
for _, want := range tt.wantContains {
|
for _, want := range tt.wantContains {
|
||||||
if !strings.Contains(got, want) {
|
if !strings.Contains(got, want) {
|
||||||
t.Errorf("Generate(%q, %v, %q, %q) missing %q\nGot:\n%s",
|
t.Errorf("FrontMatter.Bytes() missing %q\nGot:\n%s", want, got)
|
||||||
title, tags, tt.fileType, identifier, want, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, notWant := range tt.wantNotContains {
|
for _, notWant := range tt.wantNotContains {
|
||||||
if strings.Contains(got, notWant) {
|
if strings.Contains(got, notWant) {
|
||||||
t.Errorf("Generate(%q, %v, %q, %q) should not contain %q\nGot:\n%s",
|
t.Errorf("FrontMatter.Bytes() should not contain %q\nGot:\n%s", notWant, got)
|
||||||
title, tags, tt.fileType, identifier, notWant, got)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGenerateEmptyTags validates front matter generation with no tags
|
// TestFrontMatterBytesEmptyTags validates front matter formatting with no tags
|
||||||
func TestGenerateEmptyTags(t *testing.T) {
|
func TestFrontMatterBytesEmptyTags(t *testing.T) {
|
||||||
identifier := "20240101T120000"
|
identifier := "20240101T120000"
|
||||||
title := "Test Note"
|
title := "Test Note"
|
||||||
tags := []string{}
|
tags := []string{}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
fileType string
|
fileType FileType
|
||||||
wantTags string
|
wantTags string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "org with empty tags",
|
name: "org with empty tags",
|
||||||
fileType: "org",
|
fileType: FileTypeOrg,
|
||||||
wantTags: "#+filetags:",
|
wantTags: "#+filetags:",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-yaml with empty tags",
|
name: "md-yaml with empty tags",
|
||||||
fileType: "md-yaml",
|
fileType: FileTypeMdYaml,
|
||||||
wantTags: "tags:",
|
wantTags: "tags:",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "md-toml with empty tags",
|
name: "md-toml with empty tags",
|
||||||
fileType: "md-toml",
|
fileType: FileTypeMdToml,
|
||||||
wantTags: "tags =",
|
wantTags: "tags =",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt with empty tags",
|
name: "txt with empty tags",
|
||||||
fileType: "txt",
|
fileType: FileTypeTxt,
|
||||||
wantTags: "tags:",
|
wantTags: "tags:",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got := Generate(title, "", tags, tt.fileType, identifier)
|
fm := NewFrontMatter(title, "", tags, tt.fileType, identifier)
|
||||||
|
got := string(fm.Bytes())
|
||||||
|
|
||||||
if !strings.Contains(got, tt.wantTags) {
|
if !strings.Contains(got, tt.wantTags) {
|
||||||
t.Errorf("Generate() with empty tags should contain %q\nGot:\n%s",
|
t.Errorf("FrontMatter.Bytes() with empty tags should contain %q\nGot:\n%s",
|
||||||
tt.wantTags, got)
|
tt.wantTags, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -226,7 +226,7 @@ func TestParseFrontMatter(t *testing.T) {
|
||||||
wantTitle string
|
wantTitle string
|
||||||
wantTags []string
|
wantTags []string
|
||||||
wantIdentifier string
|
wantIdentifier string
|
||||||
wantFileType string
|
wantFileType FileType
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "org format",
|
name: "org format",
|
||||||
|
|
@ -240,7 +240,7 @@ func TestParseFrontMatter(t *testing.T) {
|
||||||
wantTitle: "Org Note",
|
wantTitle: "Org Note",
|
||||||
wantTags: []string{"work", "emacs"},
|
wantTags: []string{"work", "emacs"},
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "org",
|
wantFileType: FileTypeOrg,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "org with single tag",
|
name: "org with single tag",
|
||||||
|
|
@ -251,7 +251,7 @@ func TestParseFrontMatter(t *testing.T) {
|
||||||
wantTitle: "Single Tag",
|
wantTitle: "Single Tag",
|
||||||
wantTags: []string{"single"},
|
wantTags: []string{"single"},
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "org",
|
wantFileType: FileTypeOrg,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "org without tags",
|
name: "org without tags",
|
||||||
|
|
@ -261,7 +261,7 @@ func TestParseFrontMatter(t *testing.T) {
|
||||||
wantTitle: "No Tags",
|
wantTitle: "No Tags",
|
||||||
wantTags: nil,
|
wantTags: nil,
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "org",
|
wantFileType: FileTypeOrg,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "markdown yaml",
|
name: "markdown yaml",
|
||||||
|
|
@ -277,7 +277,7 @@ identifier: 20240101T120000
|
||||||
wantTitle: "Markdown Note",
|
wantTitle: "Markdown Note",
|
||||||
wantTags: []string{"work", "personal"},
|
wantTags: []string{"work", "personal"},
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "md-yaml",
|
wantFileType: FileTypeMdYaml,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "markdown yaml with quoted title",
|
name: "markdown yaml with quoted title",
|
||||||
|
|
@ -290,7 +290,7 @@ identifier: 20240101T120000
|
||||||
wantTitle: "Quoted Title",
|
wantTitle: "Quoted Title",
|
||||||
wantTags: []string{"test"},
|
wantTags: []string{"test"},
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "md-yaml",
|
wantFileType: FileTypeMdYaml,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "markdown toml",
|
name: "markdown toml",
|
||||||
|
|
@ -306,7 +306,7 @@ Content`,
|
||||||
wantTitle: "TOML Note",
|
wantTitle: "TOML Note",
|
||||||
wantTags: []string{"rust", "go"},
|
wantTags: []string{"rust", "go"},
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "md-toml",
|
wantFileType: FileTypeMdToml,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt format",
|
name: "txt format",
|
||||||
|
|
@ -321,7 +321,7 @@ Content here`,
|
||||||
wantTitle: "Plain Text",
|
wantTitle: "Plain Text",
|
||||||
wantTags: []string{"simple", "plain"},
|
wantTags: []string{"simple", "plain"},
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "txt",
|
wantFileType: FileTypeTxt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "txt without tags",
|
name: "txt without tags",
|
||||||
|
|
@ -332,7 +332,7 @@ identifier: 20240101T120000
|
||||||
wantTitle: "No Tags Text",
|
wantTitle: "No Tags Text",
|
||||||
wantTags: nil,
|
wantTags: nil,
|
||||||
wantIdentifier: "20240101T120000",
|
wantIdentifier: "20240101T120000",
|
||||||
wantFileType: "txt",
|
wantFileType: FileTypeTxt,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,8 +385,8 @@ date: 2024-01-01
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestUpdateFrontMatter validates front matter updates
|
// TestApply validates front matter updates
|
||||||
func TestUpdateFrontMatter(t *testing.T) {
|
func TestApply(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
original string
|
original string
|
||||||
|
|
@ -407,7 +407,7 @@ This should be preserved`,
|
||||||
Title: "New Title",
|
Title: "New Title",
|
||||||
Tags: []string{"new", "updated"},
|
Tags: []string{"new", "updated"},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "org",
|
FileType: FileTypeOrg,
|
||||||
},
|
},
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"#+title: New Title",
|
"#+title: New Title",
|
||||||
|
|
@ -431,7 +431,7 @@ Content preserved`,
|
||||||
Title: "New Title",
|
Title: "New Title",
|
||||||
Tags: []string{"new"},
|
Tags: []string{"new"},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "md-yaml",
|
FileType: FileTypeMdYaml,
|
||||||
},
|
},
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"---",
|
"---",
|
||||||
|
|
@ -455,7 +455,7 @@ Content here`,
|
||||||
Title: "New Title",
|
Title: "New Title",
|
||||||
Tags: []string{"updated"},
|
Tags: []string{"updated"},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "md-toml",
|
FileType: FileTypeMdToml,
|
||||||
},
|
},
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"+++",
|
"+++",
|
||||||
|
|
@ -477,7 +477,7 @@ Text content`,
|
||||||
Title: "New Title",
|
Title: "New Title",
|
||||||
Tags: []string{"new"},
|
Tags: []string{"new"},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "txt",
|
FileType: FileTypeTxt,
|
||||||
},
|
},
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"title: New Title",
|
"title: New Title",
|
||||||
|
|
@ -494,7 +494,7 @@ Text content`,
|
||||||
Title: "Added Title",
|
Title: "Added Title",
|
||||||
Tags: []string{"added"},
|
Tags: []string{"added"},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "org",
|
FileType: FileTypeOrg,
|
||||||
},
|
},
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"#+title: Added Title",
|
"#+title: Added Title",
|
||||||
|
|
@ -510,7 +510,7 @@ Text content`,
|
||||||
Title: "Added Title",
|
Title: "Added Title",
|
||||||
Tags: []string{"added"},
|
Tags: []string{"added"},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "md-yaml",
|
FileType: FileTypeMdYaml,
|
||||||
},
|
},
|
||||||
wantContains: []string{
|
wantContains: []string{
|
||||||
"---",
|
"---",
|
||||||
|
|
@ -524,27 +524,27 @@ Text content`,
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got, err := UpdateFrontMatter(tt.original, tt.fm)
|
got, err := Apply(tt.original, tt.fm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("UpdateFrontMatter() error = %v", err)
|
t.Fatalf("Apply() error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, want := range tt.wantContains {
|
for _, want := range tt.wantContains {
|
||||||
if !strings.Contains(got, want) {
|
if !strings.Contains(got, want) {
|
||||||
t.Errorf("UpdateFrontMatter() missing %q\nGot:\n%s", want, got)
|
t.Errorf("Apply() missing %q\nGot:\n%s", want, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify original content is preserved
|
// Verify original content is preserved
|
||||||
if !strings.Contains(got, tt.wantPreserve) {
|
if !strings.Contains(got, tt.wantPreserve) {
|
||||||
t.Errorf("UpdateFrontMatter() didn't preserve %q\nGot:\n%s", tt.wantPreserve, got)
|
t.Errorf("Apply() didn't preserve %q\nGot:\n%s", tt.wantPreserve, got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestUpdateFrontMatterEmptyTags validates updating with empty tags
|
// TestApplyEmptyTags validates updating with empty tags
|
||||||
func TestUpdateFrontMatterEmptyTags(t *testing.T) {
|
func TestApplyEmptyTags(t *testing.T) {
|
||||||
original := `---
|
original := `---
|
||||||
title: Test
|
title: Test
|
||||||
tags: [old, tags]
|
tags: [old, tags]
|
||||||
|
|
@ -557,27 +557,27 @@ Content`
|
||||||
Title: "Test",
|
Title: "Test",
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
Identifier: "20240101T120000",
|
Identifier: "20240101T120000",
|
||||||
FileType: "md-yaml",
|
FileType: FileTypeMdYaml,
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := UpdateFrontMatter(original, fm)
|
got, err := Apply(original, fm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("UpdateFrontMatter() error = %v", err)
|
t.Fatalf("Apply() error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should have empty tags field, not omit it
|
// Should have empty tags field, not omit it
|
||||||
if !strings.Contains(got, "tags:") {
|
if !strings.Contains(got, "tags:") {
|
||||||
t.Errorf("UpdateFrontMatter() should include tags field even when empty")
|
t.Errorf("Apply() should include tags field even when empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content should be preserved
|
// Content should be preserved
|
||||||
if !strings.Contains(got, "Content") {
|
if !strings.Contains(got, "Content") {
|
||||||
t.Errorf("UpdateFrontMatter() should preserve content")
|
t.Errorf("Apply() should preserve content")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestUpdateFrontMatterUnsupportedType validates error handling
|
// TestApplyUnsupportedType validates error handling
|
||||||
func TestUpdateFrontMatterUnsupportedType(t *testing.T) {
|
func TestApplyUnsupportedType(t *testing.T) {
|
||||||
fm := &FrontMatter{
|
fm := &FrontMatter{
|
||||||
Title: "Test",
|
Title: "Test",
|
||||||
Tags: []string{"test"},
|
Tags: []string{"test"},
|
||||||
|
|
@ -585,36 +585,33 @@ func TestUpdateFrontMatterUnsupportedType(t *testing.T) {
|
||||||
FileType: "unsupported",
|
FileType: "unsupported",
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := UpdateFrontMatter("content", fm)
|
_, err := Apply("content", fm)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("UpdateFrontMatter() should error on unsupported file type")
|
t.Error("Apply() should error on unsupported file type")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), "unsupported file type") {
|
if !strings.Contains(err.Error(), "unsupported file type") {
|
||||||
t.Errorf("UpdateFrontMatter() error = %v, want 'unsupported file type'", err)
|
t.Errorf("Apply() error = %v, want 'unsupported file type'", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestFileExtensions validates file extension mapping
|
// TestGetExtension validates file extension mapping
|
||||||
func TestFileExtensions(t *testing.T) {
|
func TestGetExtension(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
fileType string
|
fileType FileType
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{"org", ".org"},
|
{FileTypeOrg, ".org"},
|
||||||
{"md-yaml", ".md"},
|
{FileTypeMdYaml, ".md"},
|
||||||
{"md-toml", ".md"},
|
{FileTypeMdToml, ".md"},
|
||||||
{"txt", ".txt"},
|
{FileTypeTxt, ".txt"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.fileType, func(t *testing.T) {
|
t.Run(string(tt.fileType), func(t *testing.T) {
|
||||||
got, ok := fileExtensions[tt.fileType]
|
got := GetExtension(tt.fileType)
|
||||||
if !ok {
|
|
||||||
t.Errorf("fileExtensions[%q] not found", tt.fileType)
|
|
||||||
}
|
|
||||||
if got != tt.want {
|
if got != tt.want {
|
||||||
t.Errorf("fileExtensions[%q] = %q, want %q", tt.fileType, got, tt.want)
|
t.Errorf("GetExtension(%q) = %q, want %q", tt.fileType, got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -622,18 +619,19 @@ func TestFileExtensions(t *testing.T) {
|
||||||
|
|
||||||
// TestFrontMatterRoundTrip validates generate -> parse -> update cycle
|
// TestFrontMatterRoundTrip validates generate -> parse -> update cycle
|
||||||
func TestFrontMatterRoundTrip(t *testing.T) {
|
func TestFrontMatterRoundTrip(t *testing.T) {
|
||||||
fileTypes := []string{"org", "md-yaml", "md-toml", "txt"}
|
fileTypes := []FileType{FileTypeOrg, FileTypeMdYaml, FileTypeMdToml, FileTypeTxt}
|
||||||
title := "Test Note"
|
title := "Test Note"
|
||||||
tags := []string{"tag1", "tag2"}
|
tags := []string{"tag1", "tag2"}
|
||||||
identifier := "20240101T120000"
|
identifier := "20240101T120000"
|
||||||
|
|
||||||
for _, fileType := range fileTypes {
|
for _, fileType := range fileTypes {
|
||||||
t.Run(fileType, func(t *testing.T) {
|
t.Run(string(fileType), func(t *testing.T) {
|
||||||
// Generate front matter
|
// Generate front matter
|
||||||
content := Generate(title, "", tags, fileType, identifier)
|
fm := NewFrontMatter(title, "", tags, fileType, identifier)
|
||||||
|
content := string(fm.Bytes())
|
||||||
|
|
||||||
// Parse it back
|
// Parse it back
|
||||||
ext := fileExtensions[fileType]
|
ext := GetExtension(fileType)
|
||||||
fm, err := ParseFrontMatter(content, ext)
|
fm, err := ParseFrontMatter(content, ext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ParseFrontMatter() error = %v", err)
|
t.Fatalf("ParseFrontMatter() error = %v", err)
|
||||||
|
|
@ -659,9 +657,9 @@ func TestFrontMatterRoundTrip(t *testing.T) {
|
||||||
fm.Title = newTitle
|
fm.Title = newTitle
|
||||||
fm.Tags = newTags
|
fm.Tags = newTags
|
||||||
|
|
||||||
updated, err := UpdateFrontMatter(content, fm)
|
updated, err := Apply(content, fm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("UpdateFrontMatter() error = %v", err)
|
t.Fatalf("Apply() error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse again and verify
|
// Parse again and verify
|
||||||
|
|
|
||||||
|
|
@ -236,13 +236,3 @@ func BuildFilename(identifier, signature, title string, keywords []string, ext s
|
||||||
return fmt.Sprintf("%s%s--%s%s%s", identifier, signaturePart, titleSlug, keywordsPart, ext)
|
return fmt.Sprintf("%s%s--%s%s%s", identifier, signaturePart, titleSlug, keywordsPart, ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateNote creates a new note with generated identifier and content.
|
|
||||||
// Returns (path, content).
|
|
||||||
func GenerateNote(dir, title, signature string, keywords []string, fileType string) (string, string) {
|
|
||||||
identifier := GenerateIdentifier()
|
|
||||||
ext := fileExtensions[fileType]
|
|
||||||
filename := BuildFilename(identifier, signature, title, keywords, ext)
|
|
||||||
path := filepath.Join(dir, filename)
|
|
||||||
content := Generate(title, signature, keywords, fileType, identifier)
|
|
||||||
return path, content
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package metadata
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -772,60 +771,3 @@ func TestResultsFromString(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGenerateNote validates note generation (integration test)
|
|
||||||
func TestGenerateNote(t *testing.T) {
|
|
||||||
t.Run("without signature", func(t *testing.T) {
|
|
||||||
dir := "/tmp/notes"
|
|
||||||
title := "Test Note"
|
|
||||||
signature := ""
|
|
||||||
keywords := []string{"test", "example"}
|
|
||||||
fileType := "md-yaml"
|
|
||||||
|
|
||||||
path, content := GenerateNote(dir, title, signature, keywords, fileType)
|
|
||||||
|
|
||||||
// Validate path format
|
|
||||||
if !strings.HasPrefix(path, dir+"/") {
|
|
||||||
t.Errorf("GenerateNote() path = %q, should start with %q", path, dir+"/")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate filename contains identifier and title
|
|
||||||
if !strings.Contains(path, "--test-note__test_example.md") {
|
|
||||||
t.Errorf("GenerateNote() path = %q, should contain proper filename", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate content has front matter
|
|
||||||
if !strings.Contains(content, "---") {
|
|
||||||
t.Errorf("GenerateNote() content should contain YAML front matter")
|
|
||||||
}
|
|
||||||
if !strings.Contains(content, "title:") {
|
|
||||||
t.Errorf("GenerateNote() content should contain title field")
|
|
||||||
}
|
|
||||||
if !strings.Contains(content, "[test, example]") {
|
|
||||||
t.Errorf("GenerateNote() content should contain formatted tags")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("with signature", func(t *testing.T) {
|
|
||||||
dir := "/tmp/notes"
|
|
||||||
title := "Test Note"
|
|
||||||
signature := "hello"
|
|
||||||
keywords := []string{"test"}
|
|
||||||
fileType := "md-yaml"
|
|
||||||
|
|
||||||
path, content := GenerateNote(dir, title, signature, keywords, fileType)
|
|
||||||
|
|
||||||
// Validate filename contains signature
|
|
||||||
if !strings.Contains(path, "==hello--test-note__test.md") {
|
|
||||||
t.Errorf("GenerateNote() path = %q, should contain signature ==hello", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate content has signature in front matter
|
|
||||||
if !strings.Contains(content, "signature:") {
|
|
||||||
t.Errorf("GenerateNote() content should contain signature field")
|
|
||||||
}
|
|
||||||
if !strings.Contains(content, "signature: hello") {
|
|
||||||
t.Errorf("GenerateNote() content should contain signature value")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue