renderer.go (2402B)
1 package database 2 3 import ( 4 "dkforest/pkg/bfchroma" 5 bf "dkforest/pkg/blackfriday/v2" 6 "github.com/alecthomas/chroma/formatters/html" 7 html2 "html" 8 "io" 9 "regexp" 10 "strings" 11 ) 12 13 func MyRenderer(db *DkfDB, withLineNumbers, lineNumbersInTable bool) *Renderer { 14 // Defines the HTML rendering flags that are used 15 var flags = bf.UseXHTML | bf.SkipImages 16 17 r := &Renderer{ 18 DB: db, 19 Base: bfchroma.NewRenderer( 20 bfchroma.WithoutAutodetect(), 21 bfchroma.ChromaOptions( 22 html.WithLineNumbers(withLineNumbers), 23 html.LineNumbersInTable(lineNumbersInTable), 24 ), 25 bfchroma.Extend( 26 bf.NewHTMLRenderer(bf.HTMLRendererParameters{ 27 Flags: flags, 28 }), 29 ), 30 ), 31 } 32 return r 33 } 34 35 func MyRendererForum(db *DkfDB, withLineNumbers, lineNumbersInTable bool) *Renderer { 36 // Defines the HTML rendering flags that are used 37 var flags = bf.UseXHTML 38 39 r := &Renderer{ 40 DB: db, 41 Base: bfchroma.NewRenderer( 42 bfchroma.WithoutAutodetect(), 43 bfchroma.ChromaOptions( 44 html.WithLineNumbers(withLineNumbers), 45 html.LineNumbersInTable(lineNumbersInTable), 46 ), 47 bfchroma.Extend( 48 bf.NewHTMLRenderer(bf.HTMLRendererParameters{ 49 Flags: flags, 50 }), 51 ), 52 ), 53 } 54 return r 55 } 56 57 type Renderer struct { 58 DB *DkfDB 59 Base *bfchroma.Renderer 60 } 61 62 var roomNameF = `\w{3,50}` 63 var roomTagRgx = regexp.MustCompile(`#(` + roomNameF + `)`) 64 65 func (r Renderer) RenderNode(w io.Writer, node *bf.Node, entering bool) bf.WalkStatus { 66 switch node.Type { 67 case bf.Text: 68 if node.Parent.Type != bf.Link { 69 node.Literal = []byte(html2.UnescapeString(string(node.Literal))) 70 71 if roomTagRgx.MatchString(string(node.Literal)) { 72 node.Literal = []byte(roomTagRgx.ReplaceAllStringFunc(string(node.Literal), func(s string) string { 73 if room, err := r.DB.GetChatRoomByName(strings.TrimPrefix(s, "#")); err == nil { 74 return `<a href="/chat/` + room.Name + `" target="_top">` + s + `</a>` 75 } 76 return s 77 })) 78 _, _ = w.Write(node.Literal) 79 return bf.GoToNext 80 } 81 } 82 case bf.Code: 83 node.Literal = []byte(html2.UnescapeString(string(node.Literal))) 84 case bf.CodeBlock: 85 node.Literal = []byte(html2.UnescapeString(string(node.Literal))) 86 default: 87 } 88 return r.Base.RenderNode(w, node, entering) 89 } 90 91 func (r Renderer) RenderHeader(w io.Writer, ast *bf.Node) { 92 r.Base.RenderHeader(w, ast) 93 } 94 95 func (r Renderer) RenderFooter(w io.Writer, ast *bf.Node) { 96 r.Base.RenderFooter(w, ast) 97 }