goldmark-hashtag is an extension for the goldmark Markdown parser
that adds support for tagging documents with #hashtag
s.
Demo: A web-based demonstration of the extension is available at https://abhinav.github.io/goldmark-hashtag/demo/.
go get go.abhg.dev/goldmark/hashtag@latest
To use goldmark-hashtag, import the hashtag
package.
import "go.abhg.dev/goldmark/hashtag"
Then include the hashtag.Extender
in the list of extensions you build your
goldmark.Markdown
with.
goldmark.New(
goldmark.WithExtensions(
&hashtag.Extender{},
),
// ...
).Convert(src, out)
This alone has little effect
besides adding <span class="hashtag">...</span>
around hashtags in your Markdown document.
You must supply a hashtag.Resolver
to render hashtags as links.
Supply a hashtag.Resolver
to the hashtag.Extender
to render hashtags as links:
goldmark.New(
goldmark.WithExtensions(
&hashtag.Extender{
Resolver: hashtagResolver,
},
),
// ...
).Convert(src, out)
Hashtags must always begin with a "#". The characters that follow that depend on the variant you have chosen. goldmark-hashtag supports the following variants:
- Default: Hashtags must begin with a letter, and may contain letters,
numbers and any of the following symbols:
/_-
. goldmark-hashtag uses this variant if you do not specify one. - Obsidian: Hashtags can begin with and contain letters, numbers, emoji, and
any of the following symbols:
/_-
, but must not contain only numbers.
You can specify the variant by setting the Variant
property of the
hashtag.Extender
.
&hashtag.Extender{
// ...
Variant: hashtag.ObsidianVariant,
}
To collect all hashtags from a Markdown document, use Goldmark's ast.Walk
function after parsing the document.
For example, the following will populate the hashtags
map with all hashtags
found in the document.
markdown := goldmark.New(
goldmark.WithExtensions(
&hashtag.Extender{
Resolver: hashtagResolver,
},
),
// ...
)
// Parse the Markdown document.
doc := markdown.Parser().Parse(text.NewReader(src))
// List the tags.
hashtags := make(map[string]struct{})
ast.Walk(doc, func(node ast.Node, enter bool) (ast.WalkStatus, error) {
if n, ok := node.(*hashtag.Node); ok && enter {
hashtags[string(n.Tag)] = struct{}{}
}
return ast.WalkContinue, nil
})