Commit 3a013f11 authored by Mike Samuel's avatar Mike Samuel

exp/template/html: change transition functions to return indices

Formulaic changes to transition functions in preparation for CL 5074041.
This should be completely semantics preserving.

R=nigeltao
CC=golang-dev
https://golang.org/cl/5091041
parent 3c3a86cc
......@@ -547,22 +547,22 @@ var delimEnds = [...]string{
// escapeText escapes a text template node.
func (e *escaper) escapeText(c context, n *parse.TextNode) context {
s, written := n.Text, 0
var b bytes.Buffer
for len(s) > 0 {
c1, s1 := contextAfterText(c, s)
s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)
for i != len(s) {
c1, nread := contextAfterText(c, s[i:])
i1 := i + nread
if c.state == c1.state && (c.state == stateText || c.state == stateRCDATA) {
i0, i1 := len(n.Text)-len(s), len(n.Text)-len(s1)
for i := i0; i < i1; i++ {
if n.Text[i] == '<' {
b.Write(n.Text[written:i])
for j := i; j < i1; j++ {
if s[j] == '<' {
b.Write(s[written:j])
b.WriteString("&lt;")
written = i + 1
written = j + 1
}
}
}
c, s = c1, s1
c, i = c1, i1
}
if written != 0 && c.state != stateError {
b.Write(n.Text[written:])
e.editTextNode(n, b.Bytes())
......@@ -572,7 +572,7 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
// contextAfterText starts in context c, consumes some tokens from the front of
// s, then returns the context after those tokens and the unprocessed suffix.
func contextAfterText(c context, s []byte) (context, []byte) {
func contextAfterText(c context, s []byte) (context, int) {
if c.delim == delimNone {
return transitionFunc[c.state](c, s)
}
......@@ -584,9 +584,10 @@ func contextAfterText(c context, s []byte) (context, []byte) {
// <button onclick="alert(&quot;Hi!&quot;)">
// without having to entity decode token boundaries.
for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {
c, u = transitionFunc[c.state](c, u)
c1, i1 := transitionFunc[c.state](c, u)
c, u = c1, u[i1:]
}
return c, nil
return c, len(s)
}
if c.delim != delimSpaceOrTagEnd {
// Consume any quote.
......@@ -594,7 +595,7 @@ func contextAfterText(c context, s []byte) (context, []byte) {
}
// On exiting an attribute, we discard all state information
// except the state and element.
return context{state: stateTag, element: c.element}, s[i:]
return context{state: stateTag, element: c.element}, i
}
// editActionNode records a change to an action pipeline for later commit.
......
......@@ -165,43 +165,44 @@ func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
// For example, `<b>&iexcl;Hi!</b> <script>...</script>` -> `&iexcl;Hi! `.
func stripTags(html string) string {
var b bytes.Buffer
s, c := []byte(html), context{}
s, c, i := []byte(html), context{}, 0
// Using the transition funcs helps us avoid mangling
// `<div title="1>2">` or `I <3 Ponies!`.
for len(s) > 0 {
for i != len(s) {
if c.delim == delimNone {
d, t := transitionFunc[c.state](c, s)
d, nread := transitionFunc[c.state](c, s[i:])
i1 := i + nread
if c.state == stateText || c.state == stateRCDATA {
i := len(s) - len(t)
// Emit text up to the start of the tag or comment.
j := i1
if d.state != c.state {
for j := i - 1; j >= 0; j-- {
if s[j] == '<' {
i = j
for j1 := j - 1; j1 >= i; j1-- {
if s[j1] == '<' {
j = j1
break
}
}
}
b.Write(s[:i])
b.Write(s[i:j])
}
c, s = d, t
c, i = d, i1
continue
}
i := bytes.IndexAny(s, delimEnds[c.delim])
if i == -1 {
i1 := i + bytes.IndexAny(s[i:], delimEnds[c.delim])
if i1 < i {
break
}
if c.delim != delimSpaceOrTagEnd {
// Consume any quote.
i++
i1++
}
c, s = context{state: stateTag, element: c.element}, s[i:]
c, i = context{state: stateTag, element: c.element}, i1
}
if c.state == stateText {
if b.Len() == 0 {
return html
}
b.Write(s)
b.Write(s[i:])
}
return b.String()
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment