Documentation
¶
Overview ¶
Package markdown is a goldmark renderer that outputs markdown.
Example ¶
package main
import (
"bytes"
"fmt"
"log"
"regexp"
markdown "github.com/teekennedy/goldmark-markdown"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
)
// RegexpLinkTransformer is an AST Transformer that transforms markdown text that matches a regex
// pattern into a link.
type RegexpLinkTransformer struct {
LinkPattern *regexp.Regexp
ReplUrl []byte
}
// LinkifyText finds all LinkPattern matches in the given Text node and replaces them with Link
// nodes that point to ReplUrl.
func (t *RegexpLinkTransformer) LinkifyText(node *ast.Text, source []byte) {
parent := node.Parent()
tSegment := node.Segment
match := t.LinkPattern.FindIndex(tSegment.Value(source))
if match == nil {
return
}
// Create a text.Segment for the link text.
lSegment := text.NewSegment(tSegment.Start+match[0], tSegment.Start+match[1])
// Insert node for any text before the link
if lSegment.Start != tSegment.Start {
bText := ast.NewTextSegment(tSegment.WithStop(lSegment.Start))
parent.InsertBefore(parent, node, bText)
}
// Insert Link node
link := ast.NewLink()
link.AppendChild(link, ast.NewTextSegment(lSegment))
link.Destination = t.LinkPattern.ReplaceAll(lSegment.Value(source), t.ReplUrl)
parent.InsertBefore(parent, node, link)
// Update original node to represent the text after the link (may be empty)
node.Segment = tSegment.WithStart(lSegment.Stop)
// Linkify remaining text if not empty
if node.Segment.Len() > 0 {
t.LinkifyText(node, source)
}
}
// Transform implements goldmark.parser.ASTTransformer
func (t *RegexpLinkTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
source := reader.Source()
// Walk the AST in depth-first fashion and apply transformations
err := ast.Walk(node, func(node ast.Node, entering bool) (ast.WalkStatus, error) {
// Each node will be visited twice, once when it is first encountered (entering), and again
// after all the node's children have been visited (if any). Skip the latter.
if !entering {
return ast.WalkContinue, nil
}
// Skip the children of existing links to prevent double-transformation.
if node.Kind() == ast.KindLink || node.Kind() == ast.KindAutoLink {
return ast.WalkSkipChildren, nil
}
// Linkify any Text nodes encountered
if node.Kind() == ast.KindText {
textNode := node.(*ast.Text)
t.LinkifyText(textNode, source)
}
return ast.WalkContinue, nil
})
if err != nil {
log.Fatal("Error encountered while transforming AST:", err)
}
}
var source = `
Standup notes:
- Previous day:
- Gave feedback on TICKET-123.
- Outlined presentation on syntax-aware markdown transformations.
- Finished my part of TICKET-456 and assigned to Emily.
- Today:
- Add integration tests for TICKET-789.
- Create slides for presentation.
`
func main() {
// Instantiate our transformer
transformer := RegexpLinkTransformer{
LinkPattern: regexp.MustCompile(`TICKET-\d+`),
ReplUrl: []byte("https://example.com/TICKET?query=$0"),
}
// Goldmark supports multiple AST transformers and runs them sequentially in order of priority.
prioritizedTransformer := util.Prioritized(&transformer, 0)
// Setup goldmark with the markdown renderer and our transformer
gm := goldmark.New(
goldmark.WithRenderer(markdown.NewRenderer()),
goldmark.WithParserOptions(parser.WithASTTransformers(prioritizedTransformer)),
)
// Output buffer
buf := bytes.Buffer{}
// Convert parses the source, applies transformers, and renders output to the given io.Writer
err := gm.Convert([]byte(source), &buf)
if err != nil {
log.Fatalf("Encountered Markdown conversion error: %v", err)
}
fmt.Print(buf.String())
}
Output: Standup notes: - Previous day: - Gave feedback on [TICKET-123](https://example.com/TICKET?query=TICKET-123). - Outlined presentation on syntax-aware markdown transformations. - Finished my part of [TICKET-456](https://example.com/TICKET?query=TICKET-456) and assigned to Emily. - Today: - Add integration tests for [TICKET-789](https://example.com/TICKET?query=TICKET-789). - Create slides for presentation.
Index ¶
- Constants
- func WithHeadingStyle(style HeadingStyle) interface{ ... }
- func WithIndentStyle(style IndentStyle) interface{ ... }
- func WithThematicBreakLength(style ThematicBreakLength) interface{ ... }
- func WithThematicBreakStyle(style ThematicBreakStyle) interface{ ... }
- type Config
- type HeadingStyle
- type IndentStyle
- type Option
- type Renderer
- type ThematicBreakLength
- type ThematicBreakStyle
Examples ¶
Constants ¶
const ( // IndentStyleSpaces indents with 4 spaces. This is the default as well as the zero-value. IndentStyleSpaces = iota // IndentStyleTabs indents with tabs. IndentStyleTabs )
const ( // HeadingStyleATX is the #-based style. This is the default heading style and zero value. // Ex: ## Foo HeadingStyleATX = iota // HeadingStyleATXSurround adds closing #s after your header. // Ex: ## Foo ## HeadingStyleATXSurround // HeadingStyleSetext uses setext heading underlines ('===' or '---') for heading levels 1 and // 2, respectively. Other header levels continue to use ATX headings. // Ex: Foo Bar // --- HeadingStyleSetext // HeadingStyleFullWidthSetext extends setext heading underlines to the full width of the // header text. // Ex: Foo Bar // ------- HeadingStyleFullWidthSetext )
const ( // ThematicBreakStyleDashed uses '-' character for thematic breaks. This is the default and // zero value. // Ex: --- ThematicBreakStyleDashed = iota // ThematicBreakStyleStarred uses '*' character for thematic breaks. // Ex: *** ThematicBreakStyleStarred // ThematicBreakStyleUnderlined uses '_' character for thematic breaks. // Ex: ___ ThematicBreakStyleUnderlined )
const ( // ThematicBreakLengthMinimum is the minimum length of a thematic break. This is the default. // Any lengths less than this minimum are converted to the minimum. // Ex: --- ThematicBreakLengthMinimum = 3 )
Variables ¶
This section is empty.
Functions ¶
func WithHeadingStyle ¶
func WithHeadingStyle(style HeadingStyle) interface { renderer.Option Option }
WithHeadingStyle is a functional option that sets the style of markdown headings.
func WithIndentStyle ¶
func WithIndentStyle(style IndentStyle) interface { renderer.Option Option }
WithIndentStyle is a functional option that sets the string used to indent markdown blocks.
func WithThematicBreakLength ¶
func WithThematicBreakLength(style ThematicBreakLength) interface { renderer.Option Option }
WithThematicBreakLength is a functional option that sets the length of thematic breaks.
func WithThematicBreakStyle ¶
func WithThematicBreakStyle(style ThematicBreakStyle) interface { renderer.Option Option }
WithThematicBreakStyle is a functional option that sets the character used for thematic breaks.
Types ¶
type Config ¶
type Config struct {
IndentStyle IndentStyle
HeadingStyle HeadingStyle
ThematicBreakStyle ThematicBreakStyle
ThematicBreakLength ThematicBreakLength
}
Config struct holds configurations for the markdown based renderer.
func (*Config) SetOption ¶
func (c *Config) SetOption(name renderer.OptionName, value interface{})
SetOption implements renderer.SetOptioner.SetOption.
type HeadingStyle ¶
type HeadingStyle int
HeadingStyle is an enum expressing how markdown headings should look.
func (HeadingStyle) IsSetext ¶
func (i HeadingStyle) IsSetext() bool
IsSetext returns true if heading style is one of the Setext options
type IndentStyle ¶
type IndentStyle int
IndentStyle is an enum expressing how markdown blocks should be indented.
func (IndentStyle) Bytes ¶
func (i IndentStyle) Bytes() []byte
String returns the string representation of the indent style
type Option ¶
type Option interface {
renderer.Option
// SetMarkDownOption sets this option on the markdown renderer config
SetMarkdownOption(*Config)
}
Option is an interface that sets options for Markdown based renderers.
type Renderer ¶
type Renderer struct {
// contains filtered or unexported fields
}
Renderer is an implementation of renderer.Renderer that renders nodes as Markdown
func NewRenderer ¶
NewRenderer returns a new markdown Renderer that is configured by default values.
func (*Renderer) AddOptions ¶
AddOptions implements renderer.Renderer.AddOptions
type ThematicBreakLength ¶
type ThematicBreakLength int
ThematicBreakLength configures the character length of thematic breaks
type ThematicBreakStyle ¶
type ThematicBreakStyle int
ThematicBreakStyle is an enum expressing the character used for thematic breaks.