99 lines
2.9 KiB
Go
99 lines
2.9 KiB
Go
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package html
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
)
|
||
|
|
||
|
// context describes the state an HTML parser must be in when it reaches the
|
||
|
// portion of HTML produced by evaluating a particular template node.
|
||
|
//
|
||
|
// The zero value of type context is the start context for a template that
|
||
|
// produces an HTML fragment as defined at
|
||
|
// http://www.w3.org/TR/html5/the-end.html#parsing-html-fragments
|
||
|
// where the context element is null.
|
||
|
type context struct {
|
||
|
state state
|
||
|
delim delim
|
||
|
}
|
||
|
|
||
|
func (c context) String() string {
|
||
|
return fmt.Sprintf("context{state: %s, delim: %s", c.state, c.delim)
|
||
|
}
|
||
|
|
||
|
// eq is true if the two contexts are identical field-wise.
|
||
|
func (c context) eq(d context) bool {
|
||
|
return c.state == d.state && c.delim == d.delim
|
||
|
}
|
||
|
|
||
|
// state describes a high-level HTML parser state.
|
||
|
//
|
||
|
// It bounds the top of the element stack, and by extension the HTML
|
||
|
// insertion mode, but also contains state that does not correspond to
|
||
|
// anything in the HTML5 parsing algorithm because a single token
|
||
|
// production in the HTML grammar may contain embedded actions in a template.
|
||
|
// For instance, the quoted HTML attribute produced by
|
||
|
// <div title="Hello {{.World}}">
|
||
|
// is a single token in HTML's grammar but in a template spans several nodes.
|
||
|
type state uint8
|
||
|
|
||
|
const (
|
||
|
// statePCDATA is parsed character data. An HTML parser is in
|
||
|
// this state when its parse position is outside an HTML tag,
|
||
|
// directive, comment, and special element body.
|
||
|
statePCDATA state = iota
|
||
|
// stateTag occurs before an HTML attribute or the end of a tag.
|
||
|
stateTag
|
||
|
// stateURI occurs inside an HTML attribute whose content is a URI.
|
||
|
stateURI
|
||
|
// stateError is an infectious error state outside any valid
|
||
|
// HTML/CSS/JS construct.
|
||
|
stateError
|
||
|
)
|
||
|
|
||
|
var stateNames = [...]string{
|
||
|
statePCDATA: "statePCDATA",
|
||
|
stateTag: "stateTag",
|
||
|
stateURI: "stateURI",
|
||
|
stateError: "stateError",
|
||
|
}
|
||
|
|
||
|
func (s state) String() string {
|
||
|
if uint(s) < uint(len(stateNames)) {
|
||
|
return stateNames[s]
|
||
|
}
|
||
|
return fmt.Sprintf("illegal state %d", uint(s))
|
||
|
}
|
||
|
|
||
|
// delim is the delimiter that will end the current HTML attribute.
|
||
|
type delim uint8
|
||
|
|
||
|
const (
|
||
|
// delimNone occurs outside any attribute.
|
||
|
delimNone delim = iota
|
||
|
// delimDoubleQuote occurs when a double quote (") closes the attribute.
|
||
|
delimDoubleQuote
|
||
|
// delimSingleQuote occurs when a single quote (') closes the attribute.
|
||
|
delimSingleQuote
|
||
|
// delimSpaceOrTagEnd occurs when a space or right angle bracket (>)
|
||
|
// closes the attribute.
|
||
|
delimSpaceOrTagEnd
|
||
|
)
|
||
|
|
||
|
var delimNames = [...]string{
|
||
|
delimNone: "delimNone",
|
||
|
delimDoubleQuote: "delimDoubleQuote",
|
||
|
delimSingleQuote: "delimSingleQuote",
|
||
|
delimSpaceOrTagEnd: "delimSpaceOrTagEnd",
|
||
|
}
|
||
|
|
||
|
func (d delim) String() string {
|
||
|
if uint(d) < uint(len(delimNames)) {
|
||
|
return delimNames[d]
|
||
|
}
|
||
|
return fmt.Sprintf("illegal delim %d", uint(d))
|
||
|
}
|