package emdbed import ( "fmt" "io" "os" "path/filepath" "regexp" "strings" ) var ( start = regexp.MustCompile(`(?m)^$`) end = regexp.MustCompile(`(?m)^$`) ) // ConvertFile is a helper for converting a file on disk func ConvertFile(path string) (string, error) { fi, err := os.Open(path) if err != nil { return "", err } defer fi.Close() return Convert(filepath.Dir(path), fi) } // Convert converts an io.Reader with respect to a base directory func Convert(dir string, file io.Reader) (string, error) { data, err := io.ReadAll(file) if err != nil { return "", err } contents := string(data) var out strings.Builder starts := start.FindAllStringSubmatchIndex(contents, -1) ends := end.FindAllStringIndex(contents, -1) if len(starts) != len(ends) { return "", fmt.Errorf("start selectors (%d) != end selectors (%d)", len(starts), len(ends)) } var last int for idx, start := range starts { out.WriteString(contents[last:start[1]]) relPath := contents[start[2]:start[3]] fileContents, err := os.ReadFile(filepath.Join(dir, relPath)) if err != nil { return "", err } lang := strings.TrimPrefix(filepath.Ext(relPath), ".") if start[4] != -1 { lang = contents[start[4]+1 : start[5]] } var startSel string if start[6] != -1 { startSel = contents[start[6]:start[7]] } var endSel string if start[8] != -1 { endSel = contents[start[8]:start[9]] } e := emdbed{ name: relPath, contents: string(fileContents), language: lang, start: startSel, end: endSel, } sel, err := e.Selection() if err != nil { return "", err } out.WriteString(fmt.Sprintf("\n```%s\n%s\n```\n", e.language, sel)) last = ends[idx][0] } out.WriteString(contents[last:]) return out.String(), nil }