diff --git a/src/pkg/exp/html/parse.go b/src/pkg/exp/html/parse.go index 6f09745a104..70c26c75f5d 100644 --- a/src/pkg/exp/html/parse.go +++ b/src/pkg/exp/html/parse.go @@ -279,21 +279,30 @@ func (p *parser) addText(text string) { }) } -// addElement calls addChild with an element node. -// TODO: tagAtom, tag and attr are almost always p.tok.DataAtom, p.tok.Data, p.tok.Attr. -// The common case should be a no-arg addElement method. -func (p *parser) addElement(tagAtom a.Atom, tag string, attr []Attribute) { +// addElement adds a child element based on the current token. +func (p *parser) addElement() { + p.addChild(&Node{ + Type: ElementNode, + DataAtom: p.tok.DataAtom, + Data: p.tok.Data, + Attr: p.tok.Attr, + }) +} + +// addSyntheticElement adds a child element with the given tag and attributes. +func (p *parser) addSyntheticElement(tagAtom a.Atom, attr []Attribute) { p.addChild(&Node{ Type: ElementNode, DataAtom: tagAtom, - Data: tag, + Data: tagAtom.String(), Attr: attr, }) } // Section 12.2.3.3. -func (p *parser) addFormattingElement(tagAtom a.Atom, tag string, attr []Attribute) { - p.addElement(tagAtom, tag, attr) +func (p *parser) addFormattingElement() { + tagAtom, attr := p.tok.DataAtom, p.tok.Attr + p.addElement() // Implement the Noah's Ark clause, but with three per family instead of two. identicalElements := 0 @@ -309,7 +318,7 @@ findIdenticalElements: if n.Namespace != "" { continue } - if n.Data != tag { + if n.DataAtom != tagAtom { continue } if len(n.Attr) != len(attr) { @@ -489,14 +498,14 @@ func beforeHTMLIM(p *parser) bool { } case StartTagToken: if p.tok.DataAtom == a.Html { - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = beforeHeadIM return true } case EndTagToken: switch p.tok.DataAtom { case a.Head, a.Body, a.Html, a.Br: - p.parseImpliedToken(StartTagToken, a.Html, a.Html.String(), nil) + p.parseImpliedToken(StartTagToken, a.Html, a.Html.String()) return false default: // Ignore the token. @@ -509,7 +518,7 @@ func beforeHTMLIM(p *parser) bool { }) return true } - p.parseImpliedToken(StartTagToken, a.Html, a.Html.String(), nil) + p.parseImpliedToken(StartTagToken, a.Html, a.Html.String()) return false } @@ -525,7 +534,7 @@ func beforeHeadIM(p *parser) bool { case StartTagToken: switch p.tok.DataAtom { case a.Head: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.head = p.top() p.im = inHeadIM return true @@ -535,7 +544,7 @@ func beforeHeadIM(p *parser) bool { case EndTagToken: switch p.tok.DataAtom { case a.Head, a.Body, a.Html, a.Br: - p.parseImpliedToken(StartTagToken, a.Head, a.Head.String(), nil) + p.parseImpliedToken(StartTagToken, a.Head, a.Head.String()) return false default: // Ignore the token. @@ -552,7 +561,7 @@ func beforeHeadIM(p *parser) bool { return true } - p.parseImpliedToken(StartTagToken, a.Head, a.Head.String(), nil) + p.parseImpliedToken(StartTagToken, a.Head, a.Head.String()) return false } @@ -574,12 +583,12 @@ func inHeadIM(p *parser) bool { case a.Html: return inBodyIM(p) case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() p.acknowledgeSelfClosingTag() return true case a.Script, a.Title, a.Noscript, a.Noframes, a.Style: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.setOriginalIM() p.im = textIM return true @@ -597,7 +606,7 @@ func inHeadIM(p *parser) bool { p.im = afterHeadIM return true case a.Body, a.Html, a.Br: - p.parseImpliedToken(EndTagToken, a.Head, a.Head.String(), nil) + p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) return false default: // Ignore the token. @@ -614,7 +623,7 @@ func inHeadIM(p *parser) bool { return true } - p.parseImpliedToken(EndTagToken, a.Head, a.Head.String(), nil) + p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) return false } @@ -636,12 +645,12 @@ func afterHeadIM(p *parser) bool { case a.Html: return inBodyIM(p) case a.Body: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.framesetOK = false p.im = inBodyIM return true case a.Frameset: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = inFramesetIM return true case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: @@ -671,7 +680,7 @@ func afterHeadIM(p *parser) bool { return true } - p.parseImpliedToken(StartTagToken, a.Body, a.Body.String(), nil) + p.parseImpliedToken(StartTagToken, a.Body, a.Body.String()) p.framesetOK = true return false } @@ -741,28 +750,28 @@ func inBodyIM(p *parser) bool { body.Parent.Remove(body) } p.oe = p.oe[:1] - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = inFramesetIM return true case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul: p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6: p.popUntil(buttonScope, a.P) switch n := p.top(); n.DataAtom { case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6: p.oe.pop() } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Pre, a.Listing: p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() // The newline, if any, will be dealt with by the TextToken case. p.framesetOK = false case a.Form: if p.form == nil { p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.form = p.top() } case a.Li: @@ -782,7 +791,7 @@ func inBodyIM(p *parser) bool { break } p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Dd, a.Dt: p.framesetOK = false for i := len(p.oe) - 1; i >= 0; i-- { @@ -800,14 +809,14 @@ func inBodyIM(p *parser) bool { break } p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Plaintext: p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Button: p.popUntil(defaultScope, a.Button) p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.framesetOK = false case a.A: for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- { @@ -819,33 +828,33 @@ func inBodyIM(p *parser) bool { } } p.reconstructActiveFormattingElements() - p.addFormattingElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addFormattingElement() case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U: p.reconstructActiveFormattingElements() - p.addFormattingElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addFormattingElement() case a.Nobr: p.reconstructActiveFormattingElements() if p.elementInScope(defaultScope, a.Nobr) { p.inBodyEndTagFormatting(a.Nobr) p.reconstructActiveFormattingElements() } - p.addFormattingElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addFormattingElement() case a.Applet, a.Marquee, a.Object: p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.afe = append(p.afe, &scopeMarker) p.framesetOK = false case a.Table: if !p.quirks { p.popUntil(buttonScope, a.P) } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.framesetOK = false p.im = inTableIM return true case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr: p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() p.acknowledgeSelfClosingTag() if p.tok.DataAtom == a.Input { @@ -860,12 +869,12 @@ func inBodyIM(p *parser) bool { } p.framesetOK = false case a.Param, a.Source, a.Track: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() p.acknowledgeSelfClosingTag() case a.Hr: p.popUntil(buttonScope, a.P) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() p.acknowledgeSelfClosingTag() p.framesetOK = false @@ -895,24 +904,24 @@ func inBodyIM(p *parser) bool { } p.acknowledgeSelfClosingTag() p.popUntil(buttonScope, a.P) - p.addElement(a.Form, a.Form.String(), nil) + p.addSyntheticElement(a.Form, nil) p.form = p.top() if action != "" { p.form.Attr = []Attribute{{Key: "action", Val: action}} } - p.addElement(a.Hr, a.Hr.String(), nil) + p.addSyntheticElement(a.Hr, nil) p.oe.pop() - p.addElement(a.Label, a.Label.String(), nil) + p.addSyntheticElement(a.Label, nil) p.addText(prompt) - p.addElement(a.Input, a.Input.String(), attr) + p.addSyntheticElement(a.Input, attr) p.oe.pop() p.oe.pop() - p.addElement(a.Hr, a.Hr.String(), nil) + p.addSyntheticElement(a.Hr, nil) p.oe.pop() p.oe.pop() p.form = nil case a.Textarea: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.setOriginalIM() p.framesetOK = false p.im = textIM @@ -920,21 +929,21 @@ func inBodyIM(p *parser) bool { p.popUntil(buttonScope, a.P) p.reconstructActiveFormattingElements() p.framesetOK = false - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.setOriginalIM() p.im = textIM case a.Iframe: p.framesetOK = false - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.setOriginalIM() p.im = textIM case a.Noembed, a.Noscript: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.setOriginalIM() p.im = textIM case a.Select: p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.framesetOK = false p.im = inSelectIM return true @@ -943,12 +952,12 @@ func inBodyIM(p *parser) bool { p.oe.pop() } p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Rp, a.Rt: if p.elementInScope(defaultScope, a.Ruby) { p.generateImpliedEndTags() } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Math, a.Svg: p.reconstructActiveFormattingElements() if p.tok.DataAtom == a.Math { @@ -957,14 +966,14 @@ func inBodyIM(p *parser) bool { adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments) } adjustForeignAttributes(p.tok.Attr) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.top().Namespace = p.tok.Data return true case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: // Ignore the token. default: p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() } case EndTagToken: switch p.tok.DataAtom { @@ -974,7 +983,7 @@ func inBodyIM(p *parser) bool { } case a.Html: if p.elementInScope(defaultScope, a.Body) { - p.parseImpliedToken(EndTagToken, a.Body, a.Body.String(), nil) + p.parseImpliedToken(EndTagToken, a.Body, a.Body.String()) return false } return true @@ -992,7 +1001,7 @@ func inBodyIM(p *parser) bool { p.oe.remove(node) case a.P: if !p.elementInScope(buttonScope, a.P) { - p.addElement(a.P, a.P.String(), nil) + p.addSyntheticElement(a.P, nil) } p.popUntil(buttonScope, a.P) case a.Li: @@ -1209,24 +1218,24 @@ func inTableIM(p *parser) bool { case a.Caption: p.clearStackToContext(tableScope) p.afe = append(p.afe, &scopeMarker) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = inCaptionIM return true case a.Colgroup: p.clearStackToContext(tableScope) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = inColumnGroupIM return true case a.Col: - p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String(), nil) + p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String()) return false case a.Tbody, a.Tfoot, a.Thead: p.clearStackToContext(tableScope) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = inTableBodyIM return true case a.Td, a.Th, a.Tr: - p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String(), nil) + p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String()) return false case a.Table: if p.popUntil(tableScope, a.Table) { @@ -1240,7 +1249,7 @@ func inTableIM(p *parser) bool { case a.Input: for _, t := range p.tok.Attr { if t.Key == "type" && strings.ToLower(t.Val) == "hidden" { - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() return true } @@ -1251,7 +1260,7 @@ func inTableIM(p *parser) bool { // Ignore the token. return true } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.form = p.oe.pop() case a.Select: p.reconstructActiveFormattingElements() @@ -1259,7 +1268,7 @@ func inTableIM(p *parser) bool { case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr: p.fosterParenting = true } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.fosterParenting = false p.framesetOK = false p.im = inSelectInTableIM @@ -1314,7 +1323,7 @@ func inCaptionIM(p *parser) bool { } case a.Select: p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.framesetOK = false p.im = inSelectInTableIM return true @@ -1371,7 +1380,7 @@ func inColumnGroupIM(p *parser) bool { case a.Html: return inBodyIM(p) case a.Col: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() p.acknowledgeSelfClosingTag() return true @@ -1404,11 +1413,11 @@ func inTableBodyIM(p *parser) bool { switch p.tok.DataAtom { case a.Tr: p.clearStackToContext(tableBodyScope) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.im = inRowIM return true case a.Td, a.Th: - p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String(), nil) + p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String()) return false case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead: if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) { @@ -1456,7 +1465,7 @@ func inRowIM(p *parser) bool { switch p.tok.DataAtom { case a.Td, a.Th: p.clearStackToContext(tableRowScope) - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.afe = append(p.afe, &scopeMarker) p.im = inCellIM return true @@ -1486,7 +1495,7 @@ func inRowIM(p *parser) bool { return true case a.Tbody, a.Tfoot, a.Thead: if p.elementInScope(tableScope, p.tok.DataAtom) { - p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String(), nil) + p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String()) return false } // Ignore the token. @@ -1516,7 +1525,7 @@ func inCellIM(p *parser) bool { return true case a.Select: p.reconstructActiveFormattingElements() - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.framesetOK = false p.im = inSelectInTableIM return true @@ -1565,7 +1574,7 @@ func inSelectIM(p *parser) bool { if p.top().DataAtom == a.Option { p.oe.pop() } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Optgroup: if p.top().DataAtom == a.Option { p.oe.pop() @@ -1573,13 +1582,13 @@ func inSelectIM(p *parser) bool { if p.top().DataAtom == a.Optgroup { p.oe.pop() } - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Select: p.tok.Type = EndTagToken return false case a.Input, a.Keygen, a.Textarea: if p.elementInScope(selectScope, a.Select) { - p.parseImpliedToken(EndTagToken, a.Select, a.Select.String(), nil) + p.parseImpliedToken(EndTagToken, a.Select, a.Select.String()) return false } // Ignore the token. @@ -1626,7 +1635,7 @@ func inSelectInTableIM(p *parser) bool { switch p.tok.DataAtom { case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th: if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) { - p.parseImpliedToken(EndTagToken, a.Select, a.Select.String(), nil) + p.parseImpliedToken(EndTagToken, a.Select, a.Select.String()) return false } else { // Ignore the token. @@ -1698,9 +1707,9 @@ func inFramesetIM(p *parser) bool { case a.Html: return inBodyIM(p) case a.Frameset: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() case a.Frame: - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.oe.pop() p.acknowledgeSelfClosingTag() case a.Noframes: @@ -1879,7 +1888,7 @@ func parseForeignContent(p *parser) bool { } adjustForeignAttributes(p.tok.Attr) namespace := p.top().Namespace - p.addElement(p.tok.DataAtom, p.tok.Data, p.tok.Attr) + p.addElement() p.top().Namespace = namespace if p.hasSelfClosingToken { p.oe.pop() @@ -1933,13 +1942,12 @@ func (p *parser) inForeignContent() bool { // parseImpliedToken parses a token as though it had appeared in the parser's // input. -func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string, attr []Attribute) { +func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) { realToken, selfClosing := p.tok, p.hasSelfClosingToken p.tok = Token{ Type: t, DataAtom: dataAtom, Data: data, - Attr: attr, } p.hasSelfClosingToken = false p.parseCurrentToken() @@ -1965,7 +1973,7 @@ func (p *parser) parseCurrentToken() { if p.hasSelfClosingToken { p.hasSelfClosingToken = false - p.parseImpliedToken(EndTagToken, p.tok.DataAtom, p.tok.Data, nil) + p.parseImpliedToken(EndTagToken, p.tok.DataAtom, p.tok.Data) } }