func NewContext(options ...ContextOption) Context {
	cfg := &ContextConfig{
		IDs: newIDs(),
	}
	for _, option := range options {
		option(cfg)
	}
	return &parseContext{
		store:         make([]interface{}, ContextKeyMax+1),
		refs:          map[string]Reference{},
		ids:           cfg.IDs,
		blockOffset:   -1,
		blockIndent:   -1,
		delimiters:    nil,
		lastDelimiter: nil,
		openedBlocks:  []Block{},
	}
}
NewContext returns a new Context.
package parser
import (
	"fmt"
	"strings"
	"sync"
	"github.com/yuin/goldmark/ast"
	"github.com/yuin/goldmark/text"
	"github.com/yuin/goldmark/util"
)
type Reference interface {
	String() string
	Label() []byte
	Destination() []byte
	Title() []byte
}
type reference struct {
	label       []byte
	destination []byte
	title       []byte
}
func NewReference(label, destination, title []byte) Reference {
	return &reference{label, destination, title}
}
func (r *reference) Label() []byte {
	return r.label
}
func (r *reference) Destination() []byte {
	return r.destination
}
func (r *reference) Title() []byte {
	return r.title
}
func (r *reference) String() string {
	return fmt.Sprintf("Reference{Label:%s, Destination:%s, Title:%s}", r.label, r.destination, r.title)
}
type IDs interface {
	Generate(value []byte, kind ast.NodeKind) []byte
	Put(value []byte)
}
type ids struct {
	values map[string]bool
}
func newIDs() IDs {
	return &ids{
		values: map[string]bool{},
	}
}
func (s *ids) Generate(value []byte, kind ast.NodeKind) []byte {
	value = util.TrimLeftSpace(value)
	value = util.TrimRightSpace(value)
	result := []byte{}
	for i := 0; i < len(value); {
		v := value[i]
		l := util.UTF8Len(v)
		i += int(l)
		if l != 1 {
			continue
		}
		if util.IsAlphaNumeric(v) {
			if 'A' <= v && v <= 'Z' {
				v += 'a' - 'A'
			}
			result = append(result, v)
		} else if util.IsSpace(v) || v == '-' || v == '_' {
			result = append(result, '-')
		}
	}
	if len(result) == 0 {
		if kind == ast.KindHeading {
			result = []byte("heading")
		} else {
			result = []byte("id")
		}
	}
	if _, ok := s.values[util.BytesToReadOnlyString(result)]; !ok {
		s.values[util.BytesToReadOnlyString(result)] = true
		return result
	}
	for i := 1; ; i++ {
		newResult := fmt.Sprintf("%s-%d", result, i)
		if _, ok := s.values[newResult]; !ok {
			s.values[newResult] = true
			return []byte(newResult)
		}
	}
}
func (s *ids) Put(value []byte) {
	s.values[util.BytesToReadOnlyString(value)] = true
}
type ContextKey int
var ContextKeyMax ContextKey
func NewContextKey() ContextKey {
	ContextKeyMax++
	return ContextKeyMax
}
type Context interface {
	String() string
	Get(ContextKey) interface{}
	ComputeIfAbsent(ContextKey, func() interface{}) interface{}
	Set(ContextKey, interface{})
	AddReference(Reference)
	Reference(label string) (Reference, bool)
	References() []Reference
	IDs() IDs
	BlockOffset() int
	SetBlockOffset(int)
	BlockIndent() int
	SetBlockIndent(int)
	FirstDelimiter() *Delimiter
	LastDelimiter() *Delimiter
	PushDelimiter(delimiter *Delimiter)
	RemoveDelimiter(d *Delimiter)
	ClearDelimiters(bottom ast.Node)
	OpenedBlocks() []Block
	SetOpenedBlocks([]Block)
	LastOpenedBlock() Block
	IsInLinkLabel() bool
}
type ContextConfig struct {
	IDs IDs
}
type ContextOption func(*ContextConfig)
func WithIDs(ids IDs) ContextOption {
	return func(c *ContextConfig) {
		c.IDs = ids
	}
}
type parseContext struct {
	store         []interface{}
	ids           IDs
	refs          map[string]Reference
	blockOffset   int
	blockIndent   int
	delimiters    *Delimiter
	lastDelimiter *Delimiter
	openedBlocks  []Block
}