package main import ( "bytes" "github.com/PuerkitoBio/goquery" "github.com/alecthomas/chroma" "github.com/alecthomas/chroma/styles" "github.com/alecthomas/chroma/lexers" "github.com/alecthomas/chroma/formatters/html" "io" "io/ioutil" "log" "os" "regexp" "strings" "fmt" ) // print CSS needed for colorizing the code parts func printCSS(w io.Writer, formatter, style string) { f := html.New(html.WithClasses(true), html.TabWidth(4)) s := styles.Get(style) if s == nil { s = styles.Fallback } println(f.WriteCSS(w, s)) } // Highlight some text. // Lexer, formatter and style may be empty, in which case a best-effort is made. func Highlight(w io.Writer, source, lexer, formatter, style string) error { // Determine lexer. l := lexers.Get(lexer) if l == nil { l = lexers.Analyse(source) } if l == nil { l = lexers.Fallback } l = chroma.Coalesce(l) f := html.New(html.WithClasses(true), html.TabWidth(4)) // Determine style. s := styles.Get(style) if s == nil { s = styles.Fallback } it, err := l.Tokenise(nil, source) if err != nil { return err } return f.Format(w, s, it) } func replaceCodeParts(mdFile []byte) (string, error) { byteReader := bytes.NewReader(mdFile) doc, err := goquery.NewDocumentFromReader(byteReader) if err != nil { return "", err } re := regexp.MustCompile("(
)")
	rp := strings.NewReplacer("
", "")

	langs := re.FindAllString(string(mdFile), -1)

	// find code-parts via css selector and replace them with highlighted versions
	doc.Find("pre").Each(func(i int, s *goquery.Selection) {
		lang := rp.Replace(string(langs[i]))

		if lang == "console" {
			lang = "bash"
		}

		buf := new(bytes.Buffer)

		err = Highlight(buf, s.Text(), lang, "html", "monokai")
		if err != nil {
			log.Fatal(err)
		}

		s.ReplaceWithHtml(string(buf.String()))
	})
	new, err := doc.Html()
	if err != nil {
		return "", err
	}

	// remove unnecessarily added html tags
	new = strings.Replace(new, "", "", 1)

	return new, nil
}

func main() {
	if len(os.Args) != 2 {
		log.Fatal("No file name provided")
	}

	args := os.Args[1:]
	html, err := ioutil.ReadFile(args[0])
	if err != nil {
		log.Fatal(err)
	}

	replaced, err := replaceCodeParts(html)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(replaced)
	// printCSS(os.Stdout, "html", "gruvbox")
}