package blogposts import ( "bufio" "io" "io/fs" "strings" ) type Post struct { Title, Description, Body string Tags []string } const ( titleLine = "Title: " descriptionLine = "Description: " tagsLine = "Tags: " tagSeparator = ", " bodySeparator = "---" ) func getPost(fileSystem fs.FS, fileName string) (Post, error) { postFile, err := fileSystem.Open(fileName) if err != nil { return Post{}, err } defer postFile.Close() return newPost(postFile) } // NOTE: Does newPost have to be coupled to an fs.File ? // Do we use all the methods and data from this type? What do we really need? func newPost(postFile io.Reader) (Post, error) { scanner := bufio.NewScanner(postFile) readMetaLine := func(tagName string) string { scanner.Scan() return strings.TrimPrefix(scanner.Text(), tagName) } post := Post{ Title: readMetaLine(titleLine), Description: readMetaLine(descriptionLine), Tags: strings.Split(readMetaLine(tagsLine), tagSeparator), Body: readBody(scanner), } return post, nil } func readBody(scanner *bufio.Scanner) string { for scanner.Scan() { if strings.TrimSpace(scanner.Text()) == bodySeparator { break } } // The rest is the body var buf strings.Builder for scanner.Scan() { buf.Write(scanner.Bytes()) buf.Write([]byte{'\n'}) } return strings.TrimSuffix(buf.String(), "\n") }