1// Package goldmark implements functions to convert markdown text to a desired format.
  2package goldmark
  3
  4import (
  5	"github.com/yuin/goldmark/parser"
  6	"github.com/yuin/goldmark/renderer"
  7	"github.com/yuin/goldmark/renderer/html"
  8	"github.com/yuin/goldmark/text"
  9	"github.com/yuin/goldmark/util"
 10	"io"
 11)
 12
 13// DefaultParser returns a new Parser that is configured by default values.
 14func DefaultParser() parser.Parser {
 15	return parser.NewParser(parser.WithBlockParsers(parser.DefaultBlockParsers()...),
 16		parser.WithInlineParsers(parser.DefaultInlineParsers()...),
 17		parser.WithParagraphTransformers(parser.DefaultParagraphTransformers()...),
 18	)
 19}
 20
 21// DefaultRenderer returns a new Renderer that is configured by default values.
 22func DefaultRenderer() renderer.Renderer {
 23	return renderer.NewRenderer(renderer.WithNodeRenderers(util.Prioritized(html.NewRenderer(), 1000)))
 24}
 25
 26var defaultMarkdown = New()
 27
 28// Convert interprets a UTF-8 bytes source in Markdown and
 29// write rendered contents to a writer w.
 30func Convert(source []byte, w io.Writer, opts ...parser.ParseOption) error {
 31	return defaultMarkdown.Convert(source, w, opts...)
 32}
 33
 34// A Markdown interface offers functions to convert Markdown text to
 35// a desired format.
 36type Markdown interface {
 37	// Convert interprets a UTF-8 bytes source in Markdown and write rendered
 38	// contents to a writer w.
 39	Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error
 40
 41	// Parser returns a Parser that will be used for conversion.
 42	Parser() parser.Parser
 43
 44	// SetParser sets a Parser to this object.
 45	SetParser(parser.Parser)
 46
 47	// Parser returns a Renderer that will be used for conversion.
 48	Renderer() renderer.Renderer
 49
 50	// SetRenderer sets a Renderer to this object.
 51	SetRenderer(renderer.Renderer)
 52}
 53
 54// Option is a functional option type for Markdown objects.
 55type Option func(*markdown)
 56
 57// WithExtensions adds extensions.
 58func WithExtensions(ext ...Extender) Option {
 59	return func(m *markdown) {
 60		m.extensions = append(m.extensions, ext...)
 61	}
 62}
 63
 64// WithParser allows you to override the default parser.
 65func WithParser(p parser.Parser) Option {
 66	return func(m *markdown) {
 67		m.parser = p
 68	}
 69}
 70
 71// WithParserOptions applies options for the parser.
 72func WithParserOptions(opts ...parser.Option) Option {
 73	return func(m *markdown) {
 74		m.parser.AddOptions(opts...)
 75	}
 76}
 77
 78// WithRenderer allows you to override the default renderer.
 79func WithRenderer(r renderer.Renderer) Option {
 80	return func(m *markdown) {
 81		m.renderer = r
 82	}
 83}
 84
 85// WithRendererOptions applies options for the renderer.
 86func WithRendererOptions(opts ...renderer.Option) Option {
 87	return func(m *markdown) {
 88		m.renderer.AddOptions(opts...)
 89	}
 90}
 91
 92type markdown struct {
 93	parser     parser.Parser
 94	renderer   renderer.Renderer
 95	extensions []Extender
 96}
 97
 98// New returns a new Markdown with given options.
 99func New(options ...Option) Markdown {
100	md := &markdown{
101		parser:     DefaultParser(),
102		renderer:   DefaultRenderer(),
103		extensions: []Extender{},
104	}
105	for _, opt := range options {
106		opt(md)
107	}
108	for _, e := range md.extensions {
109		e.Extend(md)
110	}
111	return md
112}
113
114func (m *markdown) Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error {
115	reader := text.NewReader(source)
116	doc := m.parser.Parse(reader, opts...)
117	return m.renderer.Render(writer, source, doc)
118}
119
120func (m *markdown) Parser() parser.Parser {
121	return m.parser
122}
123
124func (m *markdown) SetParser(v parser.Parser) {
125	m.parser = v
126}
127
128func (m *markdown) Renderer() renderer.Renderer {
129	return m.renderer
130}
131
132func (m *markdown) SetRenderer(v renderer.Renderer) {
133	m.renderer = v
134}
135
136// An Extender interface is used for extending Markdown.
137type Extender interface {
138	// Extend extends the Markdown.
139	Extend(Markdown)
140}