Skip to content

Commit

Permalink
Added an ability to ignore nodes, custom options
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew-Morozko committed Sep 13, 2024
1 parent 7f3c761 commit b9c47ce
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 53 deletions.
53 changes: 17 additions & 36 deletions internal/mdrenderer/node_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
east "github.com/yuin/goldmark/extension/ast"
"github.com/yuin/goldmark/renderer"

"github.com/blackstork-io/goldmark-markdown/internal/noderenderer"
"github.com/blackstork-io/goldmark-markdown/internal/options"
"github.com/blackstork-io/goldmark-markdown/noderenderer"
)

// TODO: add the ability to register new node renderers
Expand Down Expand Up @@ -43,8 +43,9 @@ func renderHelper(n ast.Node, fn noderenderer.RenderFunc) (err error) {
}

// NewRenderer returns a new renderer. Use [goldmark.WithRenderer] to add it to a goldmark instance.
func NewRenderer() *Renderer {
func NewRenderer(opts ...options.Option) *Renderer {
return &Renderer{
opts: opts,
config: options.DefaultConfig(),
previousLineBlank: true, // document (conceptually) starts with a blank line
wasAtNL: true,
Expand All @@ -62,6 +63,7 @@ type bufs []buf
// Renderer renders markdown nodes to a writer.
type Renderer struct {
config options.Config
opts []options.Option
initOnce sync.Once
nodeRendererFuncs []noderenderer.RenderFunc

Expand All @@ -86,11 +88,9 @@ var _ goldmark.Extender = &Renderer{}

// Extend implements goldmark.Extender.
func (r *Renderer) Extend(md goldmark.Markdown) {
r.AddOptions(
renderer.WithOption(options.OptParser, options.ParserOpt{
Parser: md.Parser(),
}),
)
options.ParserOpt{
Parser: md.Parser(),
}.Apply(&r.config)
md.SetRenderer(r)
}

Expand Down Expand Up @@ -129,34 +129,8 @@ func (r *Renderer) getRenderer(kind ast.NodeKind) noderenderer.RenderFunc {
//
// You can call this method directly or use [goldmark.WithRendererOptions].
func (r *Renderer) AddOptions(opts ...renderer.Option) {
r.initOnce.Do(r.init)

config := renderer.NewConfig()
for _, opt := range opts {
opt.SetConfig(config)
}
if opt, found := config.Options[options.OptParser]; found {
delete(config.Options, options.OptParser)
opt.(options.Option).Apply(&r.config)
}
for name, val := range config.Options {
if opt, ok := val.(options.Option); ok {
opt.Apply(&r.config)
} else {
r.config.Errs = append(r.config.Errs, fmt.Errorf("%w: %s", options.ErrUnsupportedOption, name))
}
}

config.NodeRenderers.Sort()
l := len(config.NodeRenderers)
for i := l - 1; i >= 0; i-- {
v := config.NodeRenderers[i]
nr, ok := v.Value.(noderenderer.NodeRenderer)
if !ok {
continue
}
r.setRenderer(nr.Kind, nr.Fn)
}
// ignore standard options
return
}

// Render renders the given AST node to the given writer.
Expand Down Expand Up @@ -220,6 +194,13 @@ func (r *Renderer) init() {
r.setRenderer(east.KindTableCell, r.renderTableCell)
r.setRenderer(east.KindStrikethrough, r.renderStrikethrough)
r.setRenderer(east.KindTaskCheckBox, r.renderTaskCheckBox)

for _, opt := range r.opts {
opt.Apply(&r.config)
}
for _, kind := range r.config.IgnoredNodes {
r.setRenderer(kind, noderenderer.NoopRenderer)
}
}

// appends new line if the previous line is not empty
Expand All @@ -246,7 +227,7 @@ func (r *Renderer) endLine() {
}

func (r *Renderer) flush() error {
if len(r.positionStack) != 0 || len(r.emphStack) != 0 || len(r.bufs) == 0 || r.table != nil {
if len(r.positionStack) != 0 || len(r.emphStack) != 0 || r.table != nil || len(r.bufs) == 0 {
return nil
}

Expand Down
19 changes: 19 additions & 0 deletions internal/options/ignore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package options

import (
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
)

const OptIgnore renderer.OptionName = "IgnoreNodeKinds"

type IgnoreOpt struct {
Kinds []ast.NodeKind
}

// Apply implements Option.
func (t IgnoreOpt) Apply(c *Config) {
c.IgnoredNodes = append(c.IgnoredNodes, t.Kinds...)
}

var _ Option = IgnoreOpt{}
1 change: 1 addition & 0 deletions internal/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Config struct {
LinkTitleQuote []byte
CheckedCheckbox []byte
UncheckedCheckbox []byte
IgnoredNodes []ast.NodeKind
}

func DefaultConfig() Config {
Expand Down
2 changes: 1 addition & 1 deletion markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func roundtrip(t testing.TB, source, expectedHTMLOverride []byte) {

mdToMd := goldmark.New(
goldmark.WithParser(mdToHtml.Parser()),
goldmark.WithRenderer(NewRenderer()),
goldmark.WithExtensions(NewRenderer()),
)

expectedHtmlBuf := &bytes.Buffer{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import "github.com/yuin/goldmark/ast"

type RenderFunc func(n ast.Node, entering bool) error

func NoopRenderer(n ast.Node, entering bool) error {
return nil
}

type NodeRenderer struct {
Kind ast.NodeKind
Fn RenderFunc
Expand Down
21 changes: 8 additions & 13 deletions options.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package markdown

import (
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer"

"github.com/blackstork-io/goldmark-markdown/internal/options"
"github.com/yuin/goldmark/ast"
)

var (
Expand All @@ -13,18 +11,15 @@ var (
)

// WithThematicBreaks sets the thematic break tags to use, in the order of preference
func WithThematicBreaks(breaks ...string) renderer.Option {
return renderer.WithOption(
options.OptThematicBreaks,
options.ThematicBreaksOpt(breaks),
)
func WithThematicBreaks(breaks ...string) options.Option {
return options.ThematicBreaksOpt(breaks)
}

// WithParser sets the markdown parser used to verify other options's validity/applicability
func WithParser(p parser.Parser) renderer.Option {
return renderer.WithOption(options.OptParser, options.ParserOpt{
Parser: p,
})
// WithIgnoredNodes sets up the renderer to ignore a node, proceeding to render its children
func WithIgnoredNodes(kind ...ast.NodeKind) options.Option {
return options.IgnoreOpt{
Kinds: kind,
}
}

// TODO: Create more options
7 changes: 4 additions & 3 deletions renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package markdown

import (
"github.com/blackstork-io/goldmark-markdown/internal/mdrenderer"
"github.com/blackstork-io/goldmark-markdown/internal/options"
)

// NewRenderer returns a new renderer. Use [goldmark.WithRenderer] to add it to a goldmark instance.
func NewRenderer() *mdrenderer.Renderer {
return mdrenderer.NewRenderer()
// NewRenderer returns a new renderer. Use [goldmark.WithExtensions] to add it to a goldmark instance.
func NewRenderer(opts ...options.Option) *mdrenderer.Renderer {
return mdrenderer.NewRenderer(opts...)
}

0 comments on commit b9c47ce

Please sign in to comment.