func NewConverter(domain string, enableCommonmark bool, options *Options) *Converter {
	conv := &Converter{
		domain: domain,
		rules:  make(map[string][]ruleFunc),
		keep:   make(map[string]struct{}),
		remove: make(map[string]struct{}),
	}
	conv.before = append(conv.before, func(selec *goquery.Selection) {
		selec.Find("a[href]").Each(func(i int, s *goquery.Selection) {
			s.SetAttr("data-index", strconv.Itoa(i+1))
		})
	})
	conv.before = append(conv.before, func(selec *goquery.Selection) {
		selec.Find("li").Each(func(i int, s *goquery.Selection) {
			prefix := getListPrefix(options, s)
			s.SetAttr(attrListPrefix, prefix)
		})
	})
	conv.after = append(conv.after, func(markdown string) string {
		markdown = strings.TrimSpace(markdown)
		markdown = multipleNewLinesRegex.ReplaceAllString(markdown, "\n\n")
		markdown = TrimTrailingSpaces(markdown)
		return markdown
	})
	if enableCommonmark {
		conv.AddRules(commonmark...)
		conv.remove["script"] = struct{}{}
		conv.remove["style"] = struct{}{}
		conv.remove["textarea"] = struct{}{}
	}
	if options == nil {
		options = &Options{}
	}
	if options.HeadingStyle == "" {
		options.HeadingStyle = "atx"
	}
	if options.HorizontalRule == "" {
		options.HorizontalRule = "* * *"
	}
	if options.BulletListMarker == "" {
		options.BulletListMarker = "-"
	}
	if options.CodeBlockStyle == "" {
		options.CodeBlockStyle = "indented"
	}
	if options.Fence == "" {
		options.Fence = "```"
	}
	if options.EmDelimiter == "" {
		options.EmDelimiter = "_"
	}
	if options.StrongDelimiter == "" {
		options.StrongDelimiter = "**"
	}
	if options.LinkStyle == "" {
		options.LinkStyle = "inlined"
	}
	if options.LinkReferenceStyle == "" {
		options.LinkReferenceStyle = "full"
	}
	options.domain = domain
	if options.GetAbsoluteURL == nil {
		options.GetAbsoluteURL = DefaultGetAbsoluteURL
	}
	conv.options = *options
	err := validateOptions(conv.options)
	if err != nil {
		log.Println("markdown options is not valid:", err)
	}
	return conv
}
NewConverter initializes a new converter and holds all the rules.
- `domain` is used for links and images to convert relative urls ("/image.png") to absolute urls.
- CommonMark is the default set of rules. Set enableCommonmark to false if you want
to customize everything using AddRules and DONT want to fallback to default rules.
package md
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/PuerkitoBio/goquery"
)
type simpleRuleFunc func(content string, selec *goquery.Selection, options *Options) *string
type ruleFunc func(content string, selec *goquery.Selection, options *Options) (res AdvancedResult, skip bool)
type BeforeHook func(selec *goquery.Selection)
type Afterhook func(markdown string) string
type Converter struct {
	mutex  sync.RWMutex
	rules  map[string][]ruleFunc
	keep   map[string]struct{}
	remove map[string]struct{}
	before []BeforeHook
	after  []Afterhook
	domain  string
	options Options
}
func validate(val string, possible ...string) error {
	for _, e := range possible {
		if e == val {
			return nil
		}
	}
	return fmt.Errorf("field must be one of %v but got %s", possible, val)
}
func validateOptions(opt Options) error {
	if err := validate(opt.HeadingStyle, "setext", "atx"); err != nil {
		return err
	}
	if strings.Count(opt.HorizontalRule, "*") < 3 &&
		strings.Count(opt.HorizontalRule, "_") < 3 &&
		strings.Count(opt.HorizontalRule, "-") < 3 {
		return errors.New("HorizontalRule must be at least 3 characters of '*', '_' or '-' but got " + opt.HorizontalRule)
	}
	if err := validate(opt.BulletListMarker, "-", "+", "*"); err != nil {
		return err
	}
	if err := validate(opt.CodeBlockStyle, "indented", "fenced"); err != nil {
		return err
	}
	if err := validate(opt.Fence, "```", "~~~"); err != nil {
		return err
	}
	if err := validate(opt.EmDelimiter, "_", "*"); err != nil {
		return err
	}
	if err := validate(opt.StrongDelimiter, "**", "__"); err != nil {
		return err
	}
	if err := validate(opt.LinkStyle, "inlined", "referenced"); err != nil {
		return err
	}
	if err := validate(opt.LinkReferenceStyle, "full", "collapsed", "shortcut"); err != nil {
		return err
	}
	return nil
}
var (
	attrListPrefix = "data-converter-list-prefix"
)