markdown.go

 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}