improved frontmatter processing, added tests

This commit is contained in:
Daniel Fichtinger 2025-01-02 01:47:49 -05:00
parent 587085df86
commit 4d27581f0a
No known key found for this signature in database
GPG key ID: D1B0947B25420214
4 changed files with 111 additions and 29 deletions

View file

@ -0,0 +1,81 @@
package builder
import (
"bufio"
"bytes"
"errors"
"fmt"
"os"
"gopkg.in/yaml.v3"
)
func processFrontmatter(p string) (Metadata, int, error) {
f, l, err := readFrontmatter(p)
if err != nil {
return nil, l, err
}
var meta Metadata
// Parse YAML
if err := yaml.Unmarshal(f, &meta); err != nil {
return nil, l, fmt.Errorf("yaml frontmatter could not be parsed: %w", err)
}
return meta, l, nil
}
// readFrontmatter reads the file at `path` and scans
// it for --- delimited frontmatter. It does not attempt
// to parse the data, it only scans for the delimiters.
// It returns the frontmatter contents as a byte array
// and its length in lines.
func readFrontmatter(path string) ([]byte, int, error) {
file, err := os.Open(path)
if err != nil {
return nil, 0, err
}
defer file.Close()
lines := make([]string, 0, 10)
s := bufio.NewScanner(file)
i := 0
delims := 0
for s.Scan() {
l := s.Text()
if l == `---` {
if i > 0 && delims == 0 {
// if --- is not the first line, we
// assume the file does not contain frontmatter
return nil, 0, nil
}
delims += 1
i += 1
if delims == 2 {
break
}
} else {
lines = append(lines, l)
i += 1
}
}
// check whether any errors occurred while scanning
if err := s.Err(); err != nil {
return nil, 0, err
}
if delims == 2 {
l := len(lines)
if l == 0 {
// no valid frontmatter
return nil, 0, errors.New("frontmatter cannot be empty")
}
// convert to byte array
var b bytes.Buffer
for _, line := range lines {
b.WriteString(line + "\n")
}
return b.Bytes(), l, nil
} else {
// not enough delimiters, don't
// treat as frontmatter
return nil, 0, errors.New("frontmatter is missing closing delimiter")
}
}