github.com/brandur/modulir@v0.0.0-20240305213423-94ee82929cbd/modules/myaml/myaml.go (about) 1 package myaml 2 3 import ( 4 "bytes" 5 "errors" 6 "os" 7 8 "golang.org/x/xerrors" 9 "gopkg.in/yaml.v2" 10 11 "github.com/brandur/modulir" 12 ) 13 14 // ParseFile is a shortcut from parsing a source file as YAML. 15 func ParseFile(c *modulir.Context, source string, v interface{}) error { 16 raw, err := os.ReadFile(source) 17 if err != nil { 18 return xerrors.Errorf("error reading file: %w", err) 19 } 20 21 err = yaml.Unmarshal(raw, v) 22 if err != nil { 23 return xerrors.Errorf("error unmarshaling YAML: %w", err) 24 } 25 26 c.Log.Debugf("myaml: Parsed file: %s", source) 27 return nil 28 } 29 30 // ParseFileFrontmatter is a shortcut from parsing a source file's frontmatter 31 // (i.e. data at the top between `---` lines) as YAML. 32 func ParseFileFrontmatter(c *modulir.Context, source string, v interface{}) ([]byte, error) { 33 data, err := os.ReadFile(source) 34 if err != nil { 35 return nil, xerrors.Errorf("error reading file: %w", err) 36 } 37 38 frontmatter, content, err := splitFrontmatter(data) 39 if err != nil { 40 return nil, err 41 } 42 43 err = yaml.Unmarshal(frontmatter, v) 44 if err != nil { 45 return nil, xerrors.Errorf("error unmarshaling YAML frontmatter: %w", err) 46 } 47 48 c.Log.Debugf("myaml: Parsed file frontmatter: %s", source) 49 return content, nil 50 } 51 52 // 53 // Private 54 // 55 56 var errBadFrontmatter = errors.New("error splitting YAML frontmatter") 57 58 func splitFrontmatter(data []byte) ([]byte, []byte, error) { 59 parts := bytes.Split(data, []byte("---\n")) 60 61 switch { 62 case len(parts) > 1 && !bytes.Equal(parts[0], []byte("")): 63 return nil, nil, errBadFrontmatter 64 case len(parts) == 2: 65 return nil, bytes.TrimSpace(parts[1]), nil 66 case len(parts) == 3: 67 return bytes.TrimSpace(parts[1]), bytes.TrimSpace(parts[2]), nil 68 } 69 70 return nil, bytes.TrimSpace(parts[0]), nil 71 }