package utils import ( "bytes" "html" "io" "regexp" "strings" html_formatter "github.com/alecthomas/chroma/formatters/html" "github.com/alecthomas/chroma/lexers" "github.com/alecthomas/chroma/styles" ) // highlightSyntaxViaContent uses Chroma to lex code content and apply the appropriate tokenizer engine. // If it can't find one, it defaults to JavaScript syntax highlighting. func highlightSyntaxViaContent(content string, lang string) (htmlOut string) { content = html.UnescapeString(content) fallbackOut := html.EscapeString(content) lexer := lexers.Get(lang) if lexer == nil { lexer = lexers.Analyse(content) } if lexer == nil { lexer = lexers.Get(".js") } style := styles.Get("xcode") if style == nil { style = styles.Fallback } formatter := html_formatter.New(html_formatter.PreventSurroundingPre(true), html_formatter.WithClasses(true)) iterator, err := lexer.Tokenise(nil, content) if err != nil { htmlOut = fallbackOut return } b := bytes.NewBufferString("") w := io.Writer(b) err = formatter.Format(w, style, iterator) if err != nil { htmlOut = fallbackOut return } htmlOut = b.String() return } var preClassRegex = regexp.MustCompile(`(?s)
`)

// stripBlockTags takes an extracted code block from HTML and strips it of its pre and code tags.
// What's returned is just the code.
func stripBlockTags(content string) (result string) {
	// strip all "" tags
	content = strings.Replace(content, "", "", -1)
	content = strings.Replace(content, "", "", -1)
	// and the 
	content = strings.Replace(content, "
", "", -1)
	content = strings.Replace(content, "
", "", -1) content = preClassRegex.ReplaceAllString(content, "") result = content return } var codeBlockRegex = regexp.MustCompile(`(?s)]+?lang-(.+?)[\s"'])?.*?>(.*?)<\/code><\/pre>`) // HighlightCodeBlocks uses both highlightSyntaxViaContent stripCodeBlocks and returns the newly highlighted code HTML. func HighlightCodeBlocks(html string) string { // Replace each code block with the highlighted version highlightedHTML := codeBlockRegex.ReplaceAllStringFunc(html, func(codeBlock string) string { // Extract the code content from the code block matches := codeBlockRegex.FindStringSubmatch(codeBlock) lang, codeContent := matches[1], matches[2] codeContent = stripBlockTags(codeContent) // Highlight the code content highlightedCode := highlightSyntaxViaContent(codeContent, lang) // Replace the original code block with the highlighted version highlightedCodeBlock := "
" + highlightedCode + "
" return highlightedCodeBlock }) return highlightedHTML }