Source File
parse.go
Belonging Package
golang.org/x/net/html
package html
import (
a
)
var (
defaultScopeStopTags = map[string][]a.Atom{
"": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
"math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},
"svg": {a.Desc, a.ForeignObject, a.Title},
}
)
type scope int
const (
defaultScope scope = iota
listItemScope
buttonScope
tableScope
tableRowScope
tableBodyScope
selectScope
)
case listItemScope:
if == a.Ol || == a.Ul {
return -1
}
case buttonScope:
if == a.Button {
return -1
}
case tableScope:
if == a.Html || == a.Table || == a.Template {
return -1
}
case selectScope:
if != a.Optgroup && != a.Option {
return -1
}
default:
panic("unreachable")
}
}
switch {
case defaultScope, listItemScope, buttonScope:
for , := range defaultScopeStopTags[.oe[].Namespace] {
if == {
return -1
}
}
}
}
return -1
}
func ( *parser) ( scope) {
for := len(.oe) - 1; >= 0; -- {
:= .oe[].DataAtom
switch {
case tableScope:
if == a.Html || == a.Table || == a.Template {
.oe = .oe[:+1]
return
}
case tableRowScope:
if == a.Html || == a.Tr || == a.Template {
.oe = .oe[:+1]
return
}
case tableBodyScope:
if == a.Html || == a.Tbody || == a.Tfoot || == a.Thead || == a.Template {
.oe = .oe[:+1]
return
}
default:
panic("unreachable")
}
}
}
func ( *parser) () {
.addElement()
.originalIM = .im
.im = textIM
}
func ( *parser) ( *Node) {
if .shouldFosterParent() {
.fosterParent()
} else {
.top().AppendChild()
}
if .Type == ElementNode {
.oe = append(.oe, )
}
}
continue
}
func ( *parser) () {
:= .afe.top()
if == nil {
return
}
if .Type == scopeMarkerNode || .oe.index() != -1 {
return
}
:= len(.afe) - 1
for .Type != scopeMarkerNode && .oe.index() == -1 {
if == 0 {
= -1
break
}
--
= .afe[]
}
for {
++
:= .afe[].clone()
.addChild()
.afe[] =
if == len(.afe)-1 {
break
}
}
}
func ( *parser) () {
.hasSelfClosingToken = false
}
type insertionMode func(*parser) bool
func ( *parser) () {
if .originalIM != nil {
panic("html: bad parser state: originalIM was set twice")
}
.originalIM = .im
}
func ( *parser) () {
for := len(.oe) - 1; >= 0; -- {
:= .oe[]
:= == 0
if && .context != nil {
= .context
}
switch .DataAtom {
case a.Select:
if ! {
for , := , .oe[0]; != ; {
= .oe[.oe.index()-1]
switch .DataAtom {
case a.Template:
.im = inSelectIM
return
case a.Table:
.im = inSelectInTableIM
return
}
}
}
.im = inSelectIM
if .Namespace != "" {
continue
}
.im = .templateStack.top()
return true
}
case CommentToken:
.doc.AppendChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
case DoctypeToken:
, := parseDoctype(.tok.Data)
.doc.AppendChild()
.quirks =
.im = beforeHTMLIM
return true
}
.quirks = true
.im = beforeHTMLIM
return false
}
return true
}
case StartTagToken:
if .tok.DataAtom == a.Html {
.addElement()
.im = beforeHeadIM
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Head, a.Body, a.Html, a.Br:
.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
return false
return true
}
case CommentToken:
.doc.AppendChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
}
.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
return false
}
return true
}
case StartTagToken:
switch .tok.DataAtom {
case a.Head:
.addElement()
.head = .top()
.im = inHeadIM
return true
case a.Html:
return inBodyIM()
}
case EndTagToken:
switch .tok.DataAtom {
case a.Head, a.Body, a.Html, a.Br:
.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
return false
return true
}
case CommentToken:
.addChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
return true
}
.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
return false
}
.addText(.tok.Data[:len(.tok.Data)-len()])
if == "" {
return true
}
.tok.Data =
}
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta:
.addElement()
.oe.pop()
.acknowledgeSelfClosingTag()
return true
case a.Noscript:
if .scripting {
.parseGenericRawTextElement()
return true
}
.addElement()
.tokenizer.NextIsNotRawText()
return true
case a.Script, a.Title:
.addElement()
.setOriginalIM()
.im = textIM
return true
case a.Noframes, a.Style:
.parseGenericRawTextElement()
return true
return true
case a.Template:
.addElement()
.afe = append(.afe, &scopeMarker)
.framesetOK = false
.im = inTemplateIM
.templateStack = append(.templateStack, inTemplateIM)
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Head:
.oe.pop()
.im = afterHeadIM
return true
case a.Body, a.Html, a.Br:
.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
return false
case a.Template:
if !.oe.contains(a.Template) {
return true
.generateImpliedEndTags()
for := len(.oe) - 1; >= 0; -- {
if := .oe[]; .Namespace == "" && .DataAtom == a.Template {
.oe = .oe[:]
break
}
}
.clearActiveFormattingElements()
.templateStack.pop()
.resetInsertionMode()
return true
return true
}
case CommentToken:
.addChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
return true
}
.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
return false
}
return true
.addText(.tok.Data[:len(.tok.Data)-len()])
if == "" {
return true
}
.tok.Data =
}
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Body:
.addElement()
.framesetOK = false
.im = inBodyIM
return true
case a.Frameset:
.addElement()
.im = inFramesetIM
return true
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
.oe = append(.oe, .head)
defer .oe.remove(.head)
return inHeadIM()
return true
}
case EndTagToken:
switch .tok.DataAtom {
return true
}
case CommentToken:
.addChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
return true
}
.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
.framesetOK = true
return false
}
if != "" && [0] == '\r' {
= [1:]
}
if != "" && [0] == '\n' {
= [1:]
}
}
}
= strings.Replace(, "\x00", "", -1)
if == "" {
return true
}
.reconstructActiveFormattingElements()
.addText()
.framesetOK = false
}
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
if .oe.contains(a.Template) {
return true
}
copyAttributes(.oe[0], .tok)
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
return inHeadIM()
case a.Body:
if .oe.contains(a.Template) {
return true
}
if len(.oe) >= 2 {
:= .oe[1]
if .Type == ElementNode && .DataAtom == a.Body {
.framesetOK = false
copyAttributes(, .tok)
}
}
case a.Frameset:
return true
}
:= .oe[1]
if .Parent != nil {
.Parent.RemoveChild()
}
.oe = .oe[:1]
.addElement()
.im = inFramesetIM
return true
case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Main, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
.popUntil(buttonScope, a.P)
.addElement()
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
.popUntil(buttonScope, a.P)
switch := .top(); .DataAtom {
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
.oe.pop()
}
.addElement()
case a.Pre, a.Listing:
.popUntil(buttonScope, a.P)
.framesetOK = false
case a.Form:
return true
}
.popUntil(buttonScope, a.P)
.addElement()
if !.oe.contains(a.Template) {
.form = .top()
}
case a.Li:
.framesetOK = false
for := len(.oe) - 1; >= 0; -- {
:= .oe[]
switch .DataAtom {
case a.Li:
.oe = .oe[:]
case a.Address, a.Div, a.P:
continue
default:
if !isSpecialElement() {
continue
}
}
break
}
.popUntil(buttonScope, a.P)
.addElement()
case a.Dd, a.Dt:
.framesetOK = false
for := len(.oe) - 1; >= 0; -- {
:= .oe[]
switch .DataAtom {
case a.Dd, a.Dt:
.oe = .oe[:]
case a.Address, a.Div, a.P:
continue
default:
if !isSpecialElement() {
continue
}
}
break
}
.popUntil(buttonScope, a.P)
.addElement()
case a.Plaintext:
.popUntil(buttonScope, a.P)
.addElement()
case a.Button:
.popUntil(defaultScope, a.Button)
.reconstructActiveFormattingElements()
.addElement()
.framesetOK = false
case a.A:
for := len(.afe) - 1; >= 0 && .afe[].Type != scopeMarkerNode; -- {
if := .afe[]; .Type == ElementNode && .DataAtom == a.A {
.inBodyEndTagFormatting(a.A, "a")
.oe.remove()
.afe.remove()
break
}
}
.reconstructActiveFormattingElements()
.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:
.reconstructActiveFormattingElements()
.addFormattingElement()
case a.Nobr:
.reconstructActiveFormattingElements()
if .elementInScope(defaultScope, a.Nobr) {
.inBodyEndTagFormatting(a.Nobr, "nobr")
.reconstructActiveFormattingElements()
}
.addFormattingElement()
case a.Applet, a.Marquee, a.Object:
.reconstructActiveFormattingElements()
.addElement()
.afe = append(.afe, &scopeMarker)
.framesetOK = false
case a.Table:
if !.quirks {
.popUntil(buttonScope, a.P)
}
.addElement()
.framesetOK = false
.im = inTableIM
return true
case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
.reconstructActiveFormattingElements()
.addElement()
.oe.pop()
.acknowledgeSelfClosingTag()
if .tok.DataAtom == a.Input {
for , := range .tok.Attr {
if .Key == "type" {
return true
}
}
}
}
.framesetOK = false
case a.Param, a.Source, a.Track:
.addElement()
.oe.pop()
.acknowledgeSelfClosingTag()
case a.Hr:
.popUntil(buttonScope, a.P)
.addElement()
.oe.pop()
.acknowledgeSelfClosingTag()
.framesetOK = false
case a.Image:
.tok.DataAtom = a.Img
.tok.Data = a.Img.String()
return false
case a.Textarea:
.addElement()
.setOriginalIM()
.framesetOK = false
.im = textIM
case a.Xmp:
.popUntil(buttonScope, a.P)
.reconstructActiveFormattingElements()
.framesetOK = false
.parseGenericRawTextElement()
case a.Iframe:
.framesetOK = false
.parseGenericRawTextElement()
case a.Noembed:
.parseGenericRawTextElement()
case a.Noscript:
if .scripting {
.parseGenericRawTextElement()
return true
}
.reconstructActiveFormattingElements()
.tokenizer.NextIsNotRawText()
case a.Select:
.reconstructActiveFormattingElements()
.addElement()
.framesetOK = false
.im = inSelectIM
return true
case a.Optgroup, a.Option:
if .top().DataAtom == a.Option {
.oe.pop()
}
.reconstructActiveFormattingElements()
.addElement()
case a.Rb, a.Rtc:
if .elementInScope(defaultScope, a.Ruby) {
.generateImpliedEndTags()
}
.addElement()
case a.Rp, a.Rt:
if .elementInScope(defaultScope, a.Ruby) {
.generateImpliedEndTags("rtc")
}
.addElement()
case a.Math, a.Svg:
.reconstructActiveFormattingElements()
if .tok.DataAtom == a.Math {
adjustAttributeNames(.tok.Attr, mathMLAttributeAdjustments)
} else {
adjustAttributeNames(.tok.Attr, svgAttributeAdjustments)
}
adjustForeignAttributes(.tok.Attr)
.addElement()
.top().Namespace = .tok.Data
if .hasSelfClosingToken {
.oe.pop()
.acknowledgeSelfClosingTag()
}
return true
default:
.reconstructActiveFormattingElements()
.addElement()
}
case EndTagToken:
switch .tok.DataAtom {
case a.Body:
if .elementInScope(defaultScope, a.Body) {
.im = afterBodyIM
}
case a.Html:
if .elementInScope(defaultScope, a.Body) {
.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
return false
}
return true
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Main, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
.popUntil(defaultScope, .tok.DataAtom)
case a.Form:
if .oe.contains(a.Template) {
:= .indexOfElementInScope(defaultScope, a.Form)
return true
}
.generateImpliedEndTags()
return true
}
.popUntil(defaultScope, a.Form)
} else {
:= .form
.form = nil
:= .indexOfElementInScope(defaultScope, a.Form)
return true
}
.generateImpliedEndTags()
.oe.remove()
}
case a.P:
if !.elementInScope(buttonScope, a.P) {
.parseImpliedToken(StartTagToken, a.P, a.P.String())
}
.popUntil(buttonScope, a.P)
case a.Li:
.popUntil(listItemScope, a.Li)
case a.Dd, a.Dt:
.popUntil(defaultScope, .tok.DataAtom)
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
.inBodyEndTagFormatting(.tok.DataAtom, .tok.Data)
case a.Applet, a.Marquee, a.Object:
if .popUntil(defaultScope, .tok.DataAtom) {
.clearActiveFormattingElements()
}
case a.Br:
.tok.Type = StartTagToken
return false
case a.Template:
return inHeadIM()
default:
.inBodyEndTagOther(.tok.DataAtom, .tok.Data)
}
case CommentToken:
.addChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return
}
:=
:=
:= 0
--
if == {
break
if <= {
--
}
continue
if .Parent != nil {
.Parent.RemoveChild()
}
=
}
:= .clone()
reparentChildren(, )
.AppendChild()
if != "" && [0] == '\r' {
= [1:]
}
if != "" && [0] == '\n' {
= [1:]
}
}
if == "" {
return true
}
.addText()
return true
case EndTagToken:
.oe.pop()
}
.im = .originalIM
.originalIM = nil
return .tok.Type == EndTagToken
}
func ( *parser) bool {
switch .tok.Type {
case TextToken:
.tok.Data = strings.Replace(.tok.Data, "\x00", "", -1)
switch .oe.top().DataAtom {
case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
if strings.Trim(.tok.Data, whitespace) == "" {
.addText(.tok.Data)
return true
}
}
case StartTagToken:
switch .tok.DataAtom {
case a.Caption:
.clearStackToContext(tableScope)
.afe = append(.afe, &scopeMarker)
.addElement()
.im = inCaptionIM
return true
case a.Colgroup:
.clearStackToContext(tableScope)
.addElement()
.im = inColumnGroupIM
return true
case a.Col:
.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())
return false
case a.Tbody, a.Tfoot, a.Thead:
.clearStackToContext(tableScope)
.addElement()
.im = inTableBodyIM
return true
case a.Td, a.Th, a.Tr:
.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())
return false
case a.Table:
if .popUntil(tableScope, a.Table) {
.resetInsertionMode()
return false
return true
}
.addElement()
.form = .oe.pop()
case a.Select:
.reconstructActiveFormattingElements()
switch .top().DataAtom {
case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
.fosterParenting = true
}
.addElement()
.fosterParenting = false
.framesetOK = false
.im = inSelectInTableIM
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Table:
if .popUntil(tableScope, a.Table) {
.resetInsertionMode()
return true
return true
return true
case ErrorToken:
return inBodyIM()
}
.fosterParenting = true
defer func() { .fosterParenting = false }()
return inBodyIM()
}
return true
}
.clearActiveFormattingElements()
.im = inTableIM
return false
case a.Select:
.reconstructActiveFormattingElements()
.addElement()
.framesetOK = false
.im = inSelectInTableIM
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Caption:
if .popUntil(tableScope, a.Caption) {
.clearActiveFormattingElements()
.im = inTableIM
}
return true
case a.Table:
return true
}
.clearActiveFormattingElements()
.im = inTableIM
return false
return true
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Col:
.addElement()
.oe.pop()
.acknowledgeSelfClosingTag()
return true
case a.Template:
return inHeadIM()
}
case EndTagToken:
switch .tok.DataAtom {
case a.Colgroup:
if .oe.top().DataAtom == a.Colgroup {
.oe.pop()
.im = inTableIM
}
return true
func ( *parser) bool {
switch .tok.Type {
case StartTagToken:
switch .tok.DataAtom {
case a.Tr:
.clearStackToContext(tableBodyScope)
.addElement()
.im = inRowIM
return true
case a.Td, a.Th:
.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())
return false
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
if .popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
.im = inTableIM
return false
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Tbody, a.Tfoot, a.Thead:
if .elementInScope(tableScope, .tok.DataAtom) {
.clearStackToContext(tableBodyScope)
.oe.pop()
.im = inTableIM
}
return true
case a.Table:
if .popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
.im = inTableIM
return false
return true
func ( *parser) bool {
switch .tok.Type {
case StartTagToken:
switch .tok.DataAtom {
case a.Td, a.Th:
.clearStackToContext(tableRowScope)
.addElement()
.afe = append(.afe, &scopeMarker)
.im = inCellIM
return true
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
if .popUntil(tableScope, a.Tr) {
.im = inTableBodyIM
return false
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Tr:
if .popUntil(tableScope, a.Tr) {
.im = inTableBodyIM
return true
return true
case a.Table:
if .popUntil(tableScope, a.Tr) {
.im = inTableBodyIM
return false
return true
case a.Tbody, a.Tfoot, a.Thead:
if .elementInScope(tableScope, .tok.DataAtom) {
.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
return false
return true
.clearActiveFormattingElements()
.im = inRowIM
return false
return true
case a.Select:
.reconstructActiveFormattingElements()
.addElement()
.framesetOK = false
.im = inSelectInTableIM
return true
}
case EndTagToken:
switch .tok.DataAtom {
case a.Td, a.Th:
return true
}
.clearActiveFormattingElements()
.im = inRowIM
return true
return true
func ( *parser) bool {
switch .tok.Type {
case TextToken:
.addText(strings.Replace(.tok.Data, "\x00", "", -1))
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Option:
if .top().DataAtom == a.Option {
.oe.pop()
}
.addElement()
case a.Optgroup:
if .top().DataAtom == a.Option {
.oe.pop()
}
if .top().DataAtom == a.Optgroup {
.oe.pop()
}
.addElement()
case a.Select:
return true
}
.resetInsertionMode()
case a.Input, a.Keygen, a.Textarea:
if .elementInScope(selectScope, a.Select) {
.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
return false
return true
}
.resetInsertionMode()
case a.Template:
return inHeadIM()
}
case CommentToken:
.addChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
case ErrorToken:
return inBodyIM()
}
return true
}
return true
func ( *parser) bool {
switch .tok.Type {
case TextToken, CommentToken, DoctypeToken:
return inBodyIM()
case StartTagToken:
switch .tok.DataAtom {
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
return inHeadIM()
case a.Caption, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
.templateStack.pop()
.templateStack = append(.templateStack, inTableIM)
.im = inTableIM
return false
case a.Col:
.templateStack.pop()
.templateStack = append(.templateStack, inColumnGroupIM)
.im = inColumnGroupIM
return false
case a.Tr:
.templateStack.pop()
.templateStack = append(.templateStack, inTableBodyIM)
.im = inTableBodyIM
return false
case a.Td, a.Th:
.templateStack.pop()
.templateStack = append(.templateStack, inRowIM)
.im = inRowIM
return false
default:
.templateStack.pop()
.templateStack = append(.templateStack, inBodyIM)
.im = inBodyIM
return false
}
case EndTagToken:
switch .tok.DataAtom {
case a.Template:
return inHeadIM()
return true
}
case ErrorToken:
return true
.generateImpliedEndTags()
for := len(.oe) - 1; >= 0; -- {
if := .oe[]; .Namespace == "" && .DataAtom == a.Template {
.oe = .oe[:]
break
}
}
.clearActiveFormattingElements()
.templateStack.pop()
.resetInsertionMode()
return false
}
return false
}
:= strings.Map(func( rune) rune {
switch {
case ' ', '\t', '\n', '\f', '\r':
return
}
return -1
}, .tok.Data)
if != "" {
.addText()
}
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Frameset:
.addElement()
case a.Frame:
.addElement()
.oe.pop()
.acknowledgeSelfClosingTag()
case a.Noframes:
return inHeadIM()
}
case EndTagToken:
switch .tok.DataAtom {
case a.Frameset:
if .oe.top().DataAtom != a.Html {
.oe.pop()
if .oe.top().DataAtom != a.Frameset {
.im = afterFramesetIM
return true
}
}
}
}
return true
}
:= strings.Map(func( rune) rune {
switch {
case ' ', '\t', '\n', '\f', '\r':
return
}
return -1
}, .tok.Data)
if != "" {
.addText()
}
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Noframes:
return inHeadIM()
}
case EndTagToken:
switch .tok.DataAtom {
case a.Html:
.im = afterAfterFramesetIM
return true
}
}
return true
}
return inBodyIM()
}
case StartTagToken:
if .tok.DataAtom == a.Html {
return inBodyIM()
}
case CommentToken:
.doc.AppendChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
return true
case DoctypeToken:
return inBodyIM()
}
.im = inBodyIM
return false
}
func ( *parser) bool {
switch .tok.Type {
case CommentToken:
.doc.AppendChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
:= strings.Map(func( rune) rune {
switch {
case ' ', '\t', '\n', '\f', '\r':
return
}
return -1
}, .tok.Data)
if != "" {
.tok.Data =
return inBodyIM()
}
case StartTagToken:
switch .tok.DataAtom {
case a.Html:
return inBodyIM()
case a.Noframes:
return inHeadIM()
}
case DoctypeToken:
return inBodyIM()
}
return true
}
const whitespaceOrNUL = whitespace + "\x00"
func ( *parser) bool {
switch .tok.Type {
case TextToken:
if .framesetOK {
.framesetOK = strings.TrimLeft(.tok.Data, whitespaceOrNUL) == ""
}
.tok.Data = strings.Replace(.tok.Data, "\x00", "\ufffd", -1)
.addText(.tok.Data)
case CommentToken:
.addChild(&Node{
Type: CommentNode,
Data: .tok.Data,
})
case StartTagToken:
if !.fragment {
:= breakout[.tok.Data]
if .tok.DataAtom == a.Font {
:
for , := range .tok.Attr {
switch .Key {
case "color", "face", "size":
= true
break
}
}
}
if {
for := len(.oe) - 1; >= 0; -- {
:= .oe[]
if .Namespace == "" || htmlIntegrationPoint() || mathMLTextIntegrationPoint() {
.oe = .oe[:+1]
break
}
}
return false
}
}
:= .adjustedCurrentNode()
switch .Namespace {
case "math":
adjustAttributeNames(.tok.Attr, mathMLAttributeAdjustments)
if := svgTagNameAdjustments[.tok.Data]; != "" {
.tok.DataAtom = a.Lookup([]byte())
.tok.Data =
}
adjustAttributeNames(.tok.Attr, svgAttributeAdjustments)
default:
panic("html: bad parser state: unexpected namespace")
}
adjustForeignAttributes(.tok.Attr)
:= .Namespace
.addElement()
.top().Namespace =
}
return true
}
func ( *parser) () bool {
if len(.oe) == 0 {
return false
}
:= .adjustedCurrentNode()
if .Namespace == "" {
return false
}
if mathMLTextIntegrationPoint() {
if .tok.Type == StartTagToken && .tok.DataAtom != a.Mglyph && .tok.DataAtom != a.Malignmark {
return false
}
if .tok.Type == TextToken {
return false
}
}
if .Namespace == "math" && .DataAtom == a.AnnotationXml && .tok.Type == StartTagToken && .tok.DataAtom == a.Svg {
return false
}
if htmlIntegrationPoint() && (.tok.Type == StartTagToken || .tok.Type == TextToken) {
return false
}
if .tok.Type == ErrorToken {
return false
}
return true
}
func ( *parser) ( TokenType, a.Atom, string) {
, := .tok, .hasSelfClosingToken
.tok = Token{
Type: ,
DataAtom: ,
Data: ,
}
.hasSelfClosingToken = false
.parseCurrentToken()
.tok, .hasSelfClosingToken = ,
}
func ( *parser) () {
if .tok.Type == SelfClosingTagToken {
.hasSelfClosingToken = true
.tok.Type = StartTagToken
}
:= false
for ! {
if .inForeignContent() {
= parseForeignContent()
} else {
= .im()
}
}
.hasSelfClosingToken = false
}
}
var error
func ( io.Reader) (*Node, error) {
return ParseWithOptions()
}
type ParseOption func(p *parser)
func ( bool) ParseOption {
return func( *parser) {
.scripting =
}
}
if .DataAtom != a.Lookup([]byte(.Data)) {
return nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", .DataAtom, .Data)
}
= .DataAtom.String()
}
:= &parser{
doc: &Node{
Type: DocumentNode,
},
scripting: true,
fragment: true,
context: ,
}
if != nil && .Namespace != "" {
.tokenizer = NewTokenizer()
} else {
.tokenizer = NewTokenizerFragment(, )
}
for , := range {
()
}
:= &Node{
Type: ElementNode,
DataAtom: a.Html,
Data: a.Html.String(),
}
.doc.AppendChild()
.oe = nodeStack{}
if != nil && .DataAtom == a.Template {
.templateStack = append(.templateStack, inTemplateIM)
}
.resetInsertionMode()
for := ; != nil; = .Parent {
if .Type == ElementNode && .DataAtom == a.Form {
.form =
break
}
}
if := .parse(); != nil {
return nil,
}
:= .doc
if != nil {
=
}
var []*Node
for := .FirstChild; != nil; {
:= .NextSibling
.RemoveChild()
= append(, )
=
}
return , nil
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |