Parse function

Parse converts Markdown source to HTML.

Parameters:

  • src string

Returns:

  • string
Show/Hide Function Body
{
	flags := blackfriday.CommonHTMLFlags &^ blackfriday.Smartypants &^ blackfriday.SmartypantsFractions &^ blackfriday.SmartypantsDashes &^ blackfriday.SmartypantsLatexDashes
	renderer := blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{Flags: flags})
	out := blackfriday.Run(
		[]byte(src),
		blackfriday.WithExtensions(blackfriday.CommonExtensions),
		blackfriday.WithRenderer(renderer),
	)
	return string(out)
}

Heading struct

Heading represents a parsed heading.

Fields:

  • Text (string)
  • Depth (int)
  • ID (string)

slugger struct

Fields:

  • seen (map[string]int)

Methods:

slug


Parameters:
  • text string

Returns:
  • string

Show/Hide Method Body
{
	slug := strings.ToLower(text)
	slug = slugRe.ReplaceAllString(slug, "")
	slug = strings.TrimSpace(slug)
	slug = strings.ReplaceAll(slug, " ", "-")
	if n, ok := s.seen[slug]; ok {
		s.seen[slug] = n + 1
		return fmt.Sprintf("%s-%d", slug, n)
	}
	s.seen[slug] = 1
	return slug
}

newSlugger function

Returns:

  • *slugger
Show/Hide Function Body
{ return &slugger{seen: make(map[string]int)} }

Headings function

Headings extracts headings from Markdown and generates ids.

Parameters:

  • src string

Returns:

  • []Heading
Show/Hide Function Body
{
	parser := blackfriday.New(blackfriday.WithExtensions(blackfriday.CommonExtensions))
	root := parser.Parse([]byte(src))

	headings := []Heading{}
	slug := newSlugger()

	var buf bytes.Buffer
	var collectText func(n *blackfriday.Node)
	collectText = func(n *blackfriday.Node) {
		switch n.Type {
		case blackfriday.Text, blackfriday.Code:
			buf.Write(n.Literal)
		}
		for c := n.FirstChild; c != nil; c = c.Next {
			collectText(c)
		}
	}

	root.Walk(func(n *blackfriday.Node, entering bool) blackfriday.WalkStatus {
		if !entering {
			return blackfriday.GoToNext
		}
		if n.Type == blackfriday.Heading {
			buf.Reset()
			for c := n.FirstChild; c != nil; c = c.Next {
				collectText(c)
				if c.Next != nil {
					buf.WriteByte(' ')
				}
			}
			text := strings.TrimSpace(buf.String())
			level := n.HeadingData.Level
			headings = append(headings, Heading{
				Text:  text,
				Depth: int(level),
				ID:    slug.slug(text),
			})
		}
		return blackfriday.GoToNext
	})

	return headings
}

TestParse function

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	md := "# Title"
	html := Parse(md)
	if html == "" || html[:4] != "<h1>" {
		t.Fatalf("unexpected html: %q", html)
	}
}

TestHeadings function

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	md := "# Title\n## Sub"
	hs := Headings(md)
	if len(hs) != 2 {
		t.Fatalf("expected 2 headings, got %d", len(hs))
	}
	if hs[0].Text != "Title" || hs[0].Depth != 1 {
		t.Fatalf("unexpected first heading: %+v", hs[0])
	}
}

TestParsePreservesQuotes function

TestParsePreservesQuotes ensures markdown.Parse keeps plain quotes so

component include directives remain parseable.

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	src := `@include:Comp:{code:"/path/file.go", uri:"/demo"}`
	html := Parse(src)
	if !strings.Contains(html, `code:&quot;/path/file.go&quot;`) {
		t.Fatalf("expected quoted code path, got %q", html)
	}
	if strings.Contains(html, "&ldquo;") || strings.Contains(html, "&rdquo;") {
		t.Fatalf("unexpected smart quotes in %q", html)
	}
}

bytes import

Import example:

import "bytes"

fmt import

Import example:

import "fmt"

regexp import

Import example:

import "regexp"

strings import

Import example:

import "strings"

github.com/russross/blackfriday/v2 import

Import example:

import "github.com/russross/blackfriday/v2"

Imported as:

blackfriday

strings import

Import example:

import "strings"

testing import

Import example:

import "testing"