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) } title := readMetaLine(titleLine) description := readMetaLine(descriptionLine) tagsOneLine := readMetaLine(tagsLine) tags := strings.Split(tagsOneLine, ",") for i, tag := range tags { tags[i] = strings.TrimSpace(tag) } 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'}) } body := strings.TrimSuffix(buf.String(), "\n") post := Post{ Title: title, Description: description, Tags: tags, Body: body, } return post, nil }