diff options
Diffstat (limited to 'src/pkg/exp/template/html/context.go')
-rw-r--r-- | src/pkg/exp/template/html/context.go | 125 |
1 files changed, 100 insertions, 25 deletions
diff --git a/src/pkg/exp/template/html/context.go b/src/pkg/exp/template/html/context.go index 411006883..428b3d0b3 100644 --- a/src/pkg/exp/template/html/context.go +++ b/src/pkg/exp/template/html/context.go @@ -16,56 +16,77 @@ import ( // 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 + state state + delim delim + urlPart urlPart + jsCtx jsCtx + errLine int + errStr string } -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. +// eq returns whether two contexts are equal. func (c context) eq(d context) bool { - return c.state == d.state && c.delim == d.delim + return c.state == d.state && c.delim == d.delim && c.urlPart == d.urlPart && c.jsCtx == d.jsCtx && c.errLine == d.errLine && c.errStr == d.errStr } // 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 +// 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 + // stateText 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 + stateText 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 + // stateAttr occurs inside an HTML attribute whose content is text. + stateAttr + // stateURL occurs inside an HTML attribute whose content is a URL. + stateURL + // stateJS occurs inside an event handler or script element. + stateJS + // stateJSDqStr occurs inside a JavaScript double quoted string. + stateJSDqStr + // stateJSSqStr occurs inside a JavaScript single quoted string. + stateJSSqStr + // stateJSRegexp occurs inside a JavaScript regexp literal. + stateJSRegexp + // stateJSBlockCmt occurs inside a JavaScript /* block comment */. + stateJSBlockCmt + // stateJSLineCmt occurs inside a JavaScript // line comment. + stateJSLineCmt // 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", + stateText: "stateText", + stateTag: "stateTag", + stateAttr: "stateAttr", + stateURL: "stateURL", + stateJS: "stateJS", + stateJSDqStr: "stateJSDqStr", + stateJSSqStr: "stateJSSqStr", + stateJSRegexp: "stateJSRegexp", + stateJSBlockCmt: "stateJSBlockCmt", + stateJSLineCmt: "stateJSLineCmt", + stateError: "stateError", } func (s state) String() string { - if uint(s) < uint(len(stateNames)) { + if int(s) < len(stateNames) { return stateNames[s] } - return fmt.Sprintf("illegal state %d", uint(s)) + return fmt.Sprintf("illegal state %d", s) } // delim is the delimiter that will end the current HTML attribute. @@ -91,8 +112,62 @@ var delimNames = [...]string{ } func (d delim) String() string { - if uint(d) < uint(len(delimNames)) { + if int(d) < len(delimNames) { return delimNames[d] } - return fmt.Sprintf("illegal delim %d", uint(d)) + return fmt.Sprintf("illegal delim %d", d) +} + +// urlPart identifies a part in an RFC 3986 hierarchical URL to allow different +// encoding strategies. +type urlPart uint8 + +const ( + // urlPartNone occurs when not in a URL, or possibly at the start: + // ^ in "^http://auth/path?k=v#frag". + urlPartNone urlPart = iota + // urlPartPreQuery occurs in the scheme, authority, or path; between the + // ^s in "h^ttp://auth/path^?k=v#frag". + urlPartPreQuery + // urlPartQueryOrFrag occurs in the query portion between the ^s in + // "http://auth/path?^k=v#frag^". + urlPartQueryOrFrag + // urlPartUnknown occurs due to joining of contexts both before and after + // the query separator. + urlPartUnknown +) + +var urlPartNames = [...]string{ + urlPartNone: "urlPartNone", + urlPartPreQuery: "urlPartPreQuery", + urlPartQueryOrFrag: "urlPartQueryOrFrag", + urlPartUnknown: "urlPartUnknown", +} + +func (u urlPart) String() string { + if int(u) < len(urlPartNames) { + return urlPartNames[u] + } + return fmt.Sprintf("illegal urlPart %d", u) +} + +// jsCtx determines whether a '/' starts a regular expression literal or a +// division operator. +type jsCtx uint8 + +const ( + // jsCtxRegexp occurs where a '/' would start a regexp literal. + jsCtxRegexp jsCtx = iota + // jsCtxDivOp occurs where a '/' would start a division operator. + jsCtxDivOp +) + +func (c jsCtx) String() string { + switch c { + case jsCtxRegexp: + return "jsCtxRegexp" + case jsCtxDivOp: + return "jsCtxDivOp" + } + return fmt.Sprintf("illegal jsCtx %d", c) } |