From 9e06d63bdc1b9a600a2e2f8012f16b36045717c7 Mon Sep 17 00:00:00 2001 From: Brad Erickson Date: Sun, 20 Dec 2020 08:47:53 -0800 Subject: [PATCH] refactor: consistent structure 1. Extension 2. NodeKind 3. Parse/Transform 4. HTML Renderer --- README.md | 2 +- wikilink.go | 115 +++++++++++++++++++++++++---------------------- wikilink_test.go | 2 +- 3 files changed, 64 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 075b6a5..dea9462 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # goldmark-wikilink -goldmark-embed is an extension for the [goldmark][goldmark] library that extends +goldmark-wikilink is an extension for the [goldmark][goldmark] library that extends Markdown to support `[[title]]` [Wikilink][help-link] style links with a new AST type and HTML Renderer. diff --git a/wikilink.go b/wikilink.go index 6458d65..40db3b9 100644 --- a/wikilink.go +++ b/wikilink.go @@ -13,14 +13,66 @@ import ( "github.com/yuin/goldmark/util" ) +type wlExtension struct{} + +// Option is a functional option type for this extension. +type Option func(*wlExtension) + +// New returns a new Wikilink extension. +func New(opts ...Option) goldmark.Extender { + e := &wlExtension{} + for _, opt := range opts { + opt(e) + } + return e +} + +// Extend adds a wikilink parser to a Goldmark parser +func (wl *wlExtension) Extend(m goldmark.Markdown) { + m.Parser().AddOptions( + parser.WithInlineParsers( + util.Prioritized(NewParser(), 102), + ), + ) + m.Renderer().AddOptions( + renderer.WithNodeRenderers( + util.Prioritized(NewHTMLRenderer(), 500), + ), + ) +} + +// Wikilink struct represents a Wikilink of the Markdown text. +type Wikilink struct { + ast.Link +} + +// KindWikilink is a NodeKind of the Wikilink node. +var KindWikilink = ast.NewNodeKind("Wikilink") + +// Kind implements Node.Kind. +func (n *Wikilink) Kind() ast.NodeKind { + return KindWikilink +} + +// NewWikilink returns a new Wikilink node. +func NewWikilink(l *ast.Link) *Wikilink { + c := &Wikilink{ + Link: *l, + } + c.Destination = l.Destination // AKA Target + c.Title = l.Title + + return c +} + // FilenameNormalizer is a plugin which takes link text and converts the text given to // a filename which can be linked to in the final format of your file. type FilenameNormalizer interface { Normalize(linkText string) string } -// wikilinksParser keeps track of the plugins used for processing wikilinks. -type wikilinksParser struct { +// Parser keeps track of the plugins used for processing wikilinks. +type Parser struct { normalizer FilenameNormalizer } @@ -31,27 +83,26 @@ func (t *linkNormalizer) Normalize(linkText string) string { return url.PathEscape(linkText) + ".html" } -var defaultWikilinksParser = &wikilinksParser{ - normalizer: &linkNormalizer{}, -} - // NewParser gives you back a parser that you can use to process wikilinks. -func NewParser() *wikilinksParser { - return defaultWikilinksParser +func NewParser() *Parser { + return &Parser{ + normalizer: &linkNormalizer{}, + } } // WithNormalizer is the fluent interface for replacing the default normalizer plugin. -func (p *wikilinksParser) WithNormalizer(fn FilenameNormalizer) *wikilinksParser { +func (p *Parser) WithNormalizer(fn FilenameNormalizer) *Parser { p.normalizer = fn return p } // Trigger looks for the [[ beginning of wikilinks. -func (p *wikilinksParser) Trigger() []byte { +func (p *Parser) Trigger() []byte { return []byte{'[', '['} } -func (p *wikilinksParser) Parse(parent ast.Node, block text.Reader, pc parser.Context) ast.Node { +// Parse implements the parser.Parser interface for Wikilinks in markdown +func (p *Parser) Parse(parent ast.Node, block text.Reader, pc parser.Context) ast.Node { line, segment := block.PeekLine() // Must specifically confirm the second '['. if line[1] != '[' { @@ -94,48 +145,6 @@ func (p *wikilinksParser) Parse(parent ast.Node, block text.Reader, pc parser.Co return wl } -type wlExtension struct { -} - -// Extension is the default extension instance. -var Extension = &wlExtension{} - -// Extend adds a wikilink parser to a Goldmark parser -func (wl *wlExtension) Extend(m goldmark.Markdown) { - m.Parser().AddOptions( - parser.WithInlineParsers(util.Prioritized(defaultWikilinksParser, 102)), - ) - m.Renderer().AddOptions( - renderer.WithNodeRenderers( - util.Prioritized(NewHTMLRenderer(), 500), - ), - ) -} - -// Wikilink struct represents a Wikilink of the Markdown text. -type Wikilink struct { - ast.Link -} - -// KindWikilink is a NodeKind of the Wikilink node. -var KindWikilink = ast.NewNodeKind("Wikilink") - -// Kind implements Node.Kind. -func (n *Wikilink) Kind() ast.NodeKind { - return KindWikilink -} - -// NewWikilink returns a new Wikilink node. -func NewWikilink(l *ast.Link) *Wikilink { - c := &Wikilink{ - Link: *l, - } - c.Destination = l.Destination // AKA Target - c.Title = l.Title - - return c -} - // HTMLRenderer struct is a renderer.NodeRenderer implementation for the extension. type HTMLRenderer struct{} diff --git a/wikilink_test.go b/wikilink_test.go index 831834e..b496c2d 100644 --- a/wikilink_test.go +++ b/wikilink_test.go @@ -15,7 +15,7 @@ func TestWikilink(t *testing.T) { html.WithUnsafe(), ), goldmark.WithExtensions( - wikilink.Extension, + wikilink.New(), ), )