})
}
-// 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
if n.Namespace != "" {
continue
}
- if n.Data != tag {
+ if n.DataAtom != tagAtom {
continue
}
if len(n.Attr) != len(attr) {
}
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.
})
return true
}
- p.parseImpliedToken(StartTagToken, a.Html, a.Html.String(), nil)
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
return false
}
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
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.
return true
}
- p.parseImpliedToken(StartTagToken, a.Head, a.Head.String(), nil)
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
return false
}
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
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.
return true
}
- p.parseImpliedToken(EndTagToken, a.Head, a.Head.String(), nil)
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
return false
}
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:
return true
}
- p.parseImpliedToken(StartTagToken, a.Body, a.Body.String(), nil)
+ p.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
p.framesetOK = true
return false
}
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:
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-- {
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-- {
}
}
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 {
}
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
}
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
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
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 {
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 {
}
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
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:
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) {
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
}
// 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()
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
}
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
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
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) {
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
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.
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
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()
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.
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.
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:
}
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()
// 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()
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)
}
}