func (s *htmlState) checkEscaping(text string) {
	if s.ignore&issueEscaping != 0 {
		return
	}
	if n := len(s.openTags); n > 0 &&
		(s.openTags[n-1] == "script" || s.openTags[n-1] == "noscript" || s.openTags[n-1] == "iframe") {
		return
	}
	if i := strings.Index(text, "<"); i != -1 {
		a, e := i-15, i+15
		if a < 0 {
			a = 0
		}
		if e > len(text) {
			e = len(text)
		}
		s.err(fmt.Errorf("Unescaped '<' in %q", strings.TrimSpace(text[a:e])))
	}
	if i := strings.Index(text, ">"); i != -1 {
		a, e := i-15, i+15
		if a < 0 {
			a = 0
		}
		if e > len(text) {
			e = len(text)
		}
		s.err(fmt.Errorf("Unescaped '>' in %q", strings.TrimSpace(text[a:e])))
	}
	s.checkAmbiguousAmpersand(text)
}
checkEscaping of text
package ht
import (
	"encoding/base64"
	"fmt"
	"io"
	"mime"
	"net/url"
	"strings"
	"github.com/vdobler/ht/errorlist"
	"golang.org/x/net/html"
	"golang.org/x/text/language"
)
func init() {
	RegisterCheck(ValidHTML{})
}
type ValidHTML struct {
	Ignore string `json:",omitempty"`
}
func (v ValidHTML) Execute(t *Test) error {
	if t.Response.BodyErr != nil {
		return ErrBadBody
	}
	mask, _ := ignoreMask(v.Ignore)
	state := newHTMLState(t.Response.BodyStr, mask)
	z := html.NewTokenizer(state)
	depth := 0
done:
	for {
		tt := z.Next()
		switch tt {
		case html.ErrorToken:
			if z.Err() == io.EOF {
				break done
			}
			return z.Err()
		case html.TextToken:
			if depth > 0 {
				state.checkEscaping(string(z.Raw()))
			}
		case html.StartTagToken, html.SelfClosingTagToken:
			raw := string(z.Raw())
			if len(raw) > 3 {
				state.checkAmbiguousAmpersand(raw[1 : len(raw)-1])
			}
			tn, hasAttr := z.TagName()
			if tt != html.SelfClosingTagToken && !emptyHTMLElement[string(tn)] {
				state.push(string(tn))
				depth++
			}
			tag := string(tn)
			state.count(tag)
			attrs := map[string]string{}
			var bkey, bval []byte
			for hasAttr {
				bkey, bval, hasAttr = z.TagAttr()
				key, val := string(bkey), string(bval)
				if _, ok := attrs[key]; ok {
					if state.ignore&issueAttr == 0 {
						state.err(fmt.Errorf("Duplicate attribute '%s'", key))
					}
				}
				attrs[key] = val
				switch {
				case key == "id":
					state.checkID(val)
				case tag == "label" && key == "for":
					state.recordLabel(val)
				case key == "lang":
					state.checkLang(val)
				case isURLAttr(tag, key):
					state.checkURL(val)
				}
			}
		case html.EndTagToken:
			tn, _ := z.TagName()
			state.pop(string(tn))
			depth--
		case html.CommentToken:
		case html.DoctypeToken:
			state.count("DOCTYPE")
		}
	}
	state.line = -1  
	if state.ignore&issueDoctype == 0 {
		if d := state.elementCount["DOCTYPE"]; d != 1 {
			if d > 1 {
				state.err(fmt.Errorf("Found %d DOCTYPE declarations", d))
			} else {
				state.err(fmt.Errorf("Missing DOCTYPE declaration"))
			}
		}
	}
	if state.ignore&issueLabelRef == 0 {
		for _, id := range state.labelFor {
			if _, ok := state.seenIDs[id]; !ok {
				state.err(fmt.Errorf("Label references unknown id '%s'", id))
			}
		}
	}
	if len(state.errors) == 0 {
		return nil
	}
	return state.errors
}
func isURLAttr(tag, attr string) bool {
	if a, ok := linkURLattr[tag]; ok {
		return attr == a.attr
	}
	return false
}
func (v ValidHTML) Prepare(*Test) error {
	_, err := ignoreMask(v.Ignore)
	return err
}
var _ Preparable = ValidHTML{}
var emptyHTMLElement = map[string]bool{
	"br":    true,
	"hr":    true,
	"meta":  true,
	"base":  true,
	"link":  true,
	"img":   true,
	"embed": true,
	"param": true,
	"area":  true,
	"col":   true,
	"input": true,
}
type htmlIssue uint32
const (
	issueIgnoreNone htmlIssue = 0
	issueDoctype    htmlIssue = 1 << (iota - 1)
	issueStructure
	issueUniqIDs
	issueLangTag
	issueAttr
	issueEscaping
	issueLabelRef
	issueURL
)
func ignoreMask(s string) (htmlIssue, error) {
	const issueNames = "doctype  structureuniqueidslang     attr     escaping label    url"
	mask := issueIgnoreNone
	s = strings.ToLower(s)
	for _, p := range strings.Split(s, " ") {
		if p == "" {
			continue
		}
		i := strings.Index(issueNames, p)
		if i == -1 {
			return mask, fmt.Errorf("no such html issue '%s'", p)
		}
		mask |= 1 << uint(i/9)
	}
	return mask, nil
}
type htmlState struct {
	body string
	i    int
	line int
	col  int
	elementCount map[string]int
	seenIDs      map[string]bool
	openTags     []string
	labelFor     []string
	errors       errorlist.List
	ignore     htmlIssue
	badNesting bool
}
func newHTMLState(body string, ignore htmlIssue) *htmlState {
	return &htmlState{
		body:         body,
		i:            0,
		line:         0,
		col:          0,
		elementCount: make(map[string]int, 50),
		seenIDs:      make(map[string]bool),
		openTags:     make([]string, 0, 50),
		labelFor:     make([]string, 0, 10),
		errors:       make(errorlist.List, 0),
		badNesting:   false,
		ignore:       ignore,
	}
}
func (s *htmlState) Read(buf []byte) (int, error) {
	if s.i == len(s.body) {
		return 0, io.EOF
	}
	c := s.body[s.i]
	buf[0] = c
	if c == '\n' {
		s.line++
		s.col = 0
	}
	s.i++
	s.col++
	return 1, nil
}
func (s *htmlState) err(e error) {
	pe := PosError{Err: e}
	if s.line >= 0 {
		pe.Line = s.line + 1
	}
	if s.col > 160 {
		pe.Col = s.col
	}
	s.errors = append(s.errors, pe)
}
func (s *htmlState) count(tag string) {
	s.elementCount[tag] = s.elementCount[tag] + 1
}
func (s *htmlState) checkID(id string) {
	if s.ignore&issueUniqIDs == 0 {
		if _, seen := s.seenIDs[id]; seen {
			s.err(fmt.Errorf("Duplicate id '%s'", id))
		}
	}
	s.seenIDs[id] = true
}
func (s *htmlState) recordLabel(id string) {
	s.labelFor = append(s.labelFor, id)
}