From 904c7c8e9905c7ef7dfe817f8acb50a5f9fdd04b Mon Sep 17 00:00:00 2001 From: Andrew Balholm Date: Sat, 21 Apr 2012 09:20:38 +1000 Subject: [PATCH] exp/html: more work on inBodyIM Reorder some cases. Handle
, , , , , , , ,
, , , and  tags.

Pass 6 additional tests.

R=golang-dev, nigeltao
CC=golang-dev
https://golang.org/cl/6089043
---
 src/pkg/exp/html/parse.go                 | 150 ++++++++++++++--------
 src/pkg/exp/html/testlogs/tests19.dat.log |  12 +-
 2 files changed, 104 insertions(+), 58 deletions(-)

diff --git a/src/pkg/exp/html/parse.go b/src/pkg/exp/html/parse.go
index 780b47a27a..1cb65b7dcb 100644
--- a/src/pkg/exp/html/parse.go
+++ b/src/pkg/exp/html/parse.go
@@ -166,6 +166,31 @@ func (p *parser) clearStackToContext(s scope) {
 	}
 }
 
+// generateImpliedEndTags pops nodes off the stack of open elements as long as
+// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt.
+// If exceptions are specified, nodes with that name will not be popped off.
+func (p *parser) generateImpliedEndTags(exceptions ...string) {
+	var i int
+loop:
+	for i = len(p.oe) - 1; i >= 0; i-- {
+		n := p.oe[i]
+		if n.Type == ElementNode {
+			switch n.Data {
+			case "dd", "dt", "li", "option", "optgroup", "p", "rp", "rt":
+				for _, except := range exceptions {
+					if n.Data == except {
+						break loop
+					}
+				}
+				continue
+			}
+		}
+		break
+	}
+
+	p.oe = p.oe[:i+1]
+}
+
 // addChild adds a child node n to the top element, and pushes n onto the stack
 // of open elements if it is an element node.
 func (p *parser) addChild(n *Node) {
@@ -673,6 +698,61 @@ func inBodyIM(p *parser) bool {
 				p.oe.pop()
 			}
 			p.addElement(p.tok.Data, p.tok.Attr)
+		case "pre", "listing":
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+			// The newline, if any, will be dealt with by the TextToken case.
+			p.framesetOK = false
+		case "form":
+			if p.form == nil {
+				p.popUntil(buttonScope, "p")
+				p.addElement(p.tok.Data, p.tok.Attr)
+				p.form = p.top()
+			}
+		case "li":
+			p.framesetOK = false
+			for i := len(p.oe) - 1; i >= 0; i-- {
+				node := p.oe[i]
+				switch node.Data {
+				case "li":
+					p.oe = p.oe[:i]
+				case "address", "div", "p":
+					continue
+				default:
+					if !isSpecialElement(node) {
+						continue
+					}
+				}
+				break
+			}
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "dd", "dt":
+			p.framesetOK = false
+			for i := len(p.oe) - 1; i >= 0; i-- {
+				node := p.oe[i]
+				switch node.Data {
+				case "dd", "dt":
+					p.oe = p.oe[:i]
+				case "address", "div", "p":
+					continue
+				default:
+					if !isSpecialElement(node) {
+						continue
+					}
+				}
+				break
+			}
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "plaintext":
+			p.popUntil(buttonScope, "p")
+			p.addElement(p.tok.Data, p.tok.Attr)
+		case "button":
+			p.popUntil(defaultScope, "button")
+			p.reconstructActiveFormattingElements()
+			p.addElement(p.tok.Data, p.tok.Attr)
+			p.framesetOK = false
 		case "a":
 			for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
 				if n := p.afe[i]; n.Type == ElementNode && n.Data == "a" {
@@ -725,56 +805,6 @@ func inBodyIM(p *parser) bool {
 			p.framesetOK = false
 			p.im = inSelectIM
 			return true
-		case "form":
-			if p.form == nil {
-				p.popUntil(buttonScope, "p")
-				p.addElement(p.tok.Data, p.tok.Attr)
-				p.form = p.top()
-			}
-		case "li":
-			p.framesetOK = false
-			for i := len(p.oe) - 1; i >= 0; i-- {
-				node := p.oe[i]
-				switch node.Data {
-				case "li":
-					p.popUntil(listItemScope, "li")
-				case "address", "div", "p":
-					continue
-				default:
-					if !isSpecialElement(node) {
-						continue
-					}
-				}
-				break
-			}
-			p.popUntil(buttonScope, "p")
-			p.addElement(p.tok.Data, p.tok.Attr)
-		case "dd", "dt":
-			p.framesetOK = false
-			for i := len(p.oe) - 1; i >= 0; i-- {
-				node := p.oe[i]
-				switch node.Data {
-				case "dd", "dt":
-					p.oe = p.oe[:i]
-				case "address", "div", "p":
-					continue
-				default:
-					if !isSpecialElement(node) {
-						continue
-					}
-				}
-				break
-			}
-			p.popUntil(buttonScope, "p")
-			p.addElement(p.tok.Data, p.tok.Attr)
-		case "plaintext":
-			p.popUntil(buttonScope, "p")
-			p.addElement(p.tok.Data, p.tok.Attr)
-		case "button":
-			p.popUntil(defaultScope, "button")
-			p.reconstructActiveFormattingElements()
-			p.addElement(p.tok.Data, p.tok.Attr)
-			p.framesetOK = false
 		case "optgroup", "option":
 			if p.top().Data == "option" {
 				p.oe.pop()
@@ -856,15 +886,31 @@ func inBodyIM(p *parser) bool {
 				return false
 			}
 			return true
+		case "address", "article", "aside", "blockquote", "button", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "listing", "menu", "nav", "ol", "pre", "section", "summary", "ul":
+			p.popUntil(defaultScope, p.tok.Data)
+		case "form":
+			node := p.form
+			p.form = nil
+			i := p.indexOfElementInScope(defaultScope, "form")
+			if node == nil || i == -1 || p.oe[i] != node {
+				// Ignore the token.
+				return true
+			}
+			p.generateImpliedEndTags()
+			p.oe.remove(node)
 		case "p":
 			if !p.elementInScope(buttonScope, "p") {
 				p.addElement("p", nil)
 			}
 			p.popUntil(buttonScope, "p")
+		case "li":
+			p.popUntil(listItemScope, "li")
+		case "dd", "dt":
+			p.popUntil(defaultScope, p.tok.Data)
+		case "h1", "h2", "h3", "h4", "h5", "h6":
+			p.popUntil(defaultScope, "h1", "h2", "h3", "h4", "h5", "h6")
 		case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
 			p.inBodyEndTagFormatting(p.tok.Data)
-		case "address", "article", "aside", "blockquote", "button", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "listing", "menu", "nav", "ol", "pre", "section", "summary", "ul":
-			p.popUntil(defaultScope, p.tok.Data)
 		case "applet", "marquee", "object":
 			if p.popUntil(defaultScope, p.tok.Data) {
 				p.clearActiveFormattingElements()
diff --git a/src/pkg/exp/html/testlogs/tests19.dat.log b/src/pkg/exp/html/testlogs/tests19.dat.log
index 189e0fe4a8..27ab4f05ef 100644
--- a/src/pkg/exp/html/testlogs/tests19.dat.log
+++ b/src/pkg/exp/html/testlogs/tests19.dat.log
@@ -1,8 +1,8 @@
 FAIL ""
 PASS "

" PASS "

" -FAIL "

"
-FAIL "

" +PASS "

"
+PASS "

" PASS "

" PASS "<!doctype html><p><h1>" PASS "<!doctype html><form><isindex>" @@ -19,9 +19,9 @@ FAIL "<!doctype html><ruby><div><p><rt>" PASS "<!doctype html><math/><foo>" PASS "<!doctype html><svg/><foo>" PASS "<!doctype html><div></body><!--foo-->" -FAIL "<!doctype html><h1><div><h3><span></h1>foo" +PASS "<!doctype html><h1><div><h3><span></h1>foo" PASS "<!doctype html><p></h3>foo" -FAIL "<!doctype html><h3><li>abc</h2>foo" +PASS "<!doctype html><h3><li>abc</h2>foo" PASS "<!doctype html><table>abc<!--foo-->" FAIL "<!doctype html><table> <!--foo-->" PASS "<!doctype html><table> b <!--foo-->" @@ -46,8 +46,8 @@ PASS "<!doctype html><body><frameset>" PASS "<!doctype html><p><frameset><frame>" PASS "<!doctype html><p>a<frameset>" FAIL "<!doctype html><p> <frameset><frame>" -FAIL "<!doctype html><pre><frameset>" -FAIL "<!doctype html><listing><frameset>" +PASS "<!doctype html><pre><frameset>" +PASS "<!doctype html><listing><frameset>" PASS "<!doctype html><li><frameset>" PASS "<!doctype html><dd><frameset>" PASS "<!doctype html><dt><frameset>"