package examples import ( "bufio" "errors" "fmt" "os" "strings" ) type Example struct { // headers which lead to this example Path []string `json:"path"` // after - Name string `json:"name"` // after : Comment string `json:"comment"` // content of code fence Data string `json:"data"` } func ReadFile(file *os.File) ([]Example, error) { isCodeBlock := false var path []string sc := bufio.NewScanner(file) var currentDataLines []string var examples []Example currentExample := Example{} lineNum := 0 for sc.Scan() { lineNum += 1 line := sc.Text() // fmt.Printf("%q\n", line) if strings.HasPrefix(line, "```") { // begin or end of code block if isCodeBlock { // end currentExample.Data = strings.Join(currentDataLines, "\n") examples = append(examples, currentExample) currentExample = Example{} currentDataLines = nil } // otherwise start, don't do anything isCodeBlock = !isCodeBlock } else if isCodeBlock { currentDataLines = append(currentDataLines, line) } else if strings.HasPrefix(line, "#") { // header pathElem := strings.Trim(line, "# ") // replace headers count := strings.Count(line, "#") path = append(path[0:count-1], pathElem) } else if strings.HasPrefix(line, "- ") { line = strings.TrimPrefix(line, "- ") parts := strings.SplitN(line, ":", 2) name := parts[0] if !strings.HasPrefix(name, "`") || !strings.HasSuffix(name, "`") { return examples, errors.New( fmt.Sprintf( "bad syntax at line number %d: missing inline code for example name", lineNum, ), ) } name = strings.Trim(name, "`") comment := strings.Trim(parts[1], " .") currentExample.Name = name currentExample.Comment = comment currentExample.Path = append([]string{}, path...) // fmt.Printf("Header: %s\n", line) // fmt.Printf( // " - Name: %s, Comment: %q, Path: %v\n", // currentExample.Name, // currentExample.Comment, // currentExample.Path, // ) } } if isCodeBlock { return examples, errors.New(fmt.Sprintf("code block left open somewhere after %d examples", len(examples))) } return examples, nil }