1package markdown
2
3import (
4 "bytes"
5 "io"
6
7 "github.com/gomarkdown/markdown/ast"
8 "github.com/gomarkdown/markdown/html"
9 "github.com/gomarkdown/markdown/parser"
10)
11
12// Renderer is an interface for implementing custom renderers.
13type Renderer interface {
14 // RenderNode renders markdown node to w.
15 // It's called once for a leaf node.
16 // It's called twice for non-leaf nodes:
17 // * first with entering=true
18 // * then with entering=false
19 //
20 // Return value is a way to tell the calling walker to adjust its walk
21 // pattern: e.g. it can terminate the traversal by returning Terminate. Or it
22 // can ask the walker to skip a subtree of this node by returning SkipChildren.
23 // The typical behavior is to return GoToNext, which asks for the usual
24 // traversal to the next node.
25 RenderNode(w io.Writer, node ast.Node, entering bool) ast.WalkStatus
26
27 // RenderHeader is a method that allows the renderer to produce some
28 // content preceding the main body of the output document. The header is
29 // understood in the broad sense here. For example, the default HTML
30 // renderer will write not only the HTML document preamble, but also the
31 // table of contents if it was requested.
32 //
33 // The method will be passed an entire document tree, in case a particular
34 // implementation needs to inspect it to produce output.
35 //
36 // The output should be written to the supplied writer w. If your
37 // implementation has no header to write, supply an empty implementation.
38 RenderHeader(w io.Writer, ast ast.Node)
39
40 // RenderFooter is a symmetric counterpart of RenderHeader.
41 RenderFooter(w io.Writer, ast ast.Node)
42}
43
44// Parse parsers a markdown document using provided parser. If parser is nil,
45// we use parser configured with parser.CommonExtensions.
46//
47// It returns AST (abstract syntax tree) that can be converted to another
48// format using Render function.
49func Parse(markdown []byte, p *parser.Parser) ast.Node {
50 if p == nil {
51 p = parser.New()
52 }
53 return p.Parse(markdown)
54}
55
56// Render uses renderer to convert parsed markdown document into a different format.
57//
58// To convert to HTML, pass html.Renderer
59func Render(doc ast.Node, renderer Renderer) []byte {
60 var buf bytes.Buffer
61 renderer.RenderHeader(&buf, doc)
62 ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus {
63 return renderer.RenderNode(&buf, node, entering)
64 })
65 renderer.RenderFooter(&buf, doc)
66 return buf.Bytes()
67}
68
69// ToHTML converts markdownDoc to HTML.
70//
71// You can optionally pass a parser and renderer. This allows to customize
72// a parser, use a customized html render or use completely custom renderer.
73//
74// If you pass nil for both, we use parser configured with parser.CommonExtensions
75// and html.Renderer configured with html.CommonFlags.
76func ToHTML(markdown []byte, p *parser.Parser, renderer Renderer) []byte {
77 doc := Parse(markdown, p)
78 if renderer == nil {
79 opts := html.RendererOptions{
80 Flags: html.CommonFlags,
81 }
82 renderer = html.NewRenderer(opts)
83 }
84 return Render(doc, renderer)
85}