package main import ( "fmt" "io/ioutil" "log" "os" "path/filepath" "regexp" "strings" ) type link struct { full string title string url string } func procAudio(fileContent string, audioRegex *regexp.Regexp) string { audios := audioRegex.FindAllStringSubmatch(fileContent, -1) if audios != nil { for i := range audios { full := audios[i][0] url := audios[i][1] link := link{full, "audio", url} replacement := fmt.Sprintf("=> %s", link.url) fileContent = strings.Replace(fileContent, link.full, replacement, 1) } } return fileContent } func procVideos(fileContent string, videoRegex *regexp.Regexp) string { videos := videoRegex.FindAllStringSubmatch(fileContent, -1) if videos != nil { for i := range videos { full := videos[i][0] url := videos[i][1] url = fmt.Sprintf("%s.webm", url) link := link{full, "video", url} replacement := fmt.Sprintf("=> %s", link.url) fileContent = strings.Replace(fileContent, link.full, replacement, 1) } } return fileContent } func procImages(fileContent string, imgRegex *regexp.Regexp) string { images := imgRegex.FindAllStringSubmatch(fileContent, -1) if images != nil { for i := range images { full := images[i][1] title := images[i][2] url := images[i][3] urlParts := strings.Split(url, " ") link := link{full, title, urlParts[0]} replacement := fmt.Sprintf("%s\n=> %s", link.title, link.url) fileContent = strings.Replace(fileContent, link.full, replacement, 1) } } return fileContent } func procLinks(fileContent string, linkRegex *regexp.Regexp) string { links := linkRegex.FindAllStringSubmatch(fileContent, -1) linkUrls := make([]link, len(links)) if links != nil { for i := range links { full := links[i][1] title := links[i][2] url := links[i][3] link := link{full, title, url} replacement := fmt.Sprintf("*%s*", link.title) fileContent = strings.Replace(fileContent, link.full, replacement, 1) linkUrls[i] = link } } var sb strings.Builder for _, link := range linkUrls { fmtLink := fmt.Sprintf("=> %s %s\n", link.url, link.title) sb.WriteString(fmtLink) } fmtLinks := sb.String() fileContent += fmt.Sprintf("\n%s", fmtLinks) return fileContent } func procFile(src string, linkRegex *regexp.Regexp, imgRegex *regexp.Regexp, videoRegex *regexp.Regexp, audioRegex *regexp.Regexp) (string, error) { fileData, err := ioutil.ReadFile(src) if err != nil { return "", err } fileContent := string(fileData) fileContent = procLinks(fileContent, linkRegex) fileContent = procImages(fileContent, imgRegex) fileContent = procVideos(fileContent, videoRegex) fileContent = procAudio(fileContent, audioRegex) return fileContent, nil } func procFiles(srcDir string, destDir string) error { libRegex := regexp.MustCompile("^.+\\.(md)$") linkRegex := regexp.MustCompile("[^!](\\[(.+?)\\]\\((.+?)\\))") imgRegex := regexp.MustCompile("([!]\\[(.+?)\\]\\((.+?)\\))") videoRegex := regexp.MustCompile("{{< video src=\"(.*)\" >}}") audioRegex := regexp.MustCompile("{{< audio src=\"(.*)\" >}}") srcDir, err := filepath.Abs(srcDir) if err != nil { return err } destDir, err = filepath.Abs(destDir) if err != nil { return err } err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error { if err == nil && libRegex.MatchString(info.Name()) { processedFile, err := procFile(path, linkRegex, imgRegex, videoRegex, audioRegex) if err != nil { return err } path, err = filepath.Abs(path) if err != nil { return err } srcFile := strings.Replace(path, srcDir, "", 1) destFile := filepath.Join(destDir, srcFile) destDir := filepath.Dir(destFile) err = os.MkdirAll(destDir, os.ModePerm) if err != nil { return err } err = ioutil.WriteFile(destFile, []byte(processedFile), 0644) if err != nil { return err } log.Printf("processed %s", path) } return nil }) return err } func main() { if len(os.Args) < 2 { log.Fatal("no source directory specified") os.Exit(1) } if len(os.Args) < 3 { log.Fatal("no dest directory specified") os.Exit(1) } srcDir := os.Args[1] srcInfo, err := os.Stat(srcDir) if os.IsNotExist(err) { log.Fatalf("source directory %s does not exist", srcDir) os.Exit(1) } if !srcInfo.IsDir() { log.Fatalf("%s is not a directory", srcDir) os.Exit(1) } destDir := os.Args[2] err = procFiles(srcDir, destDir) if err != nil { log.Fatal(err) os.Exit(1) } }