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 WithNestedListLength(style NestedListLength) interface{ ... }
- func WithThematicBreakLength(style ThematicBreakLength) interface{ ... }
- func WithThematicBreakStyle(style ThematicBreakStyle) interface{ ... }
- type Config
- type HeadingStyle
- type IndentStyle
- type NestedListLength
- 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 ( // NestedListLengthMinimum is the minimum length of a nested list indentation. This is the default. // Any lengths less than this minimum are converted to the minimum. // Ex: --- NestedListLengthMinimum = 1 )
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 WithNestedListLength ¶ added in v0.4.0
func WithNestedListLength(style NestedListLength) interface { renderer.Option Option }
WithNestedListLength is a functional option that sets the length of nested list indentation.
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 HeadingStyle ThematicBreakStyle ThematicBreakLength NestedListLength }
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 ¶ added in v0.1.2
func (i IndentStyle) Bytes() []byte
String returns the string representation of the indent style
type NestedListLength ¶ added in v0.4.0
type NestedListLength int
NestedListLength configures the character length of nested list indentation
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 ¶ added in v0.1.2
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.