Sync with latest HTML5lib and latest Maruku
This commit is contained in:
parent
8e92e4a3ab
commit
8ccaad85a5
71 changed files with 1974 additions and 1621 deletions
46
vendor/plugins/HTML5lib/lib/html5/html5parser/after_body_phase.rb
vendored
Normal file
46
vendor/plugins/HTML5lib/lib/html5/html5parser/after_body_phase.rb
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class AfterBodyPhase < Phase
|
||||
|
||||
handle_end 'html'
|
||||
|
||||
def processComment(data)
|
||||
# This is needed because data is to be appended to the <html> element
|
||||
# here and not to whatever is currently open.
|
||||
@tree.insertComment(data, @tree.openElements[0])
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.parseError(_('Unexpected non-space characters in the after body phase.'))
|
||||
@parser.phase = @parser.phases[:inBody]
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
|
||||
def processStartTag(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag token (#{name}) in the after body phase."))
|
||||
@parser.phase = @parser.phases[:inBody]
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagHtml(name)
|
||||
if @parser.innerHTML
|
||||
@parser.parseError
|
||||
else
|
||||
# XXX: This may need to be done, not sure
|
||||
# Don't set lastPhase to the current phase but to the inBody phase
|
||||
# instead. No need for extra parse errors if there's something after </html>.
|
||||
# Try "<!doctype html>X</html>X" for instance.
|
||||
@parser.lastPhase = @parser.phase
|
||||
@parser.phase = @parser.phases[:trailingEnd]
|
||||
end
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag token (#{name}) in the after body phase."))
|
||||
@parser.phase = @parser.phases[:inBody]
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
34
vendor/plugins/HTML5lib/lib/html5/html5parser/after_frameset_phase.rb
vendored
Normal file
34
vendor/plugins/HTML5lib/lib/html5/html5parser/after_frameset_phase.rb
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class AfterFramesetPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#after3
|
||||
|
||||
handle_start 'html', 'noframes'
|
||||
|
||||
handle_end 'html'
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.parseError(_('Unexpected non-space characters in the after frameset phase. Ignored.'))
|
||||
end
|
||||
|
||||
def startTagNoframes(name, attributes)
|
||||
@parser.phases[:inBody].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag (#{name}) in the after frameset phase. Ignored."))
|
||||
end
|
||||
|
||||
def endTagHtml(name)
|
||||
@parser.lastPhase = @parser.phase
|
||||
@parser.phase = @parser.phases[:trailingEnd]
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}) in the after frameset phase. Ignored."))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
50
vendor/plugins/HTML5lib/lib/html5/html5parser/after_head_phase.rb
vendored
Normal file
50
vendor/plugins/HTML5lib/lib/html5/html5parser/after_head_phase.rb
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class AfterHeadPhase < Phase
|
||||
|
||||
handle_start 'html', 'body', 'frameset', %w( base link meta script style title ) => 'FromHead'
|
||||
|
||||
def processEOF
|
||||
anythingElse
|
||||
@parser.phase.processEOF
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
anythingElse
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
|
||||
def startTagBody(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inBody]
|
||||
end
|
||||
|
||||
def startTagFrameset(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inFrameset]
|
||||
end
|
||||
|
||||
def startTagFromHead(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag (#{name}) that can be in head. Moved."))
|
||||
@parser.phase = @parser.phases[:inHead]
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
anythingElse
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def processEndTag(name)
|
||||
anythingElse
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
def anythingElse
|
||||
@tree.insertElement('body', {})
|
||||
@parser.phase = @parser.phases[:inBody]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
41
vendor/plugins/HTML5lib/lib/html5/html5parser/before_head_phase.rb
vendored
Normal file
41
vendor/plugins/HTML5lib/lib/html5/html5parser/before_head_phase.rb
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class BeforeHeadPhase < Phase
|
||||
|
||||
handle_start 'html', 'head'
|
||||
|
||||
handle_end %w( html head body br p ) => 'ImplyHead'
|
||||
|
||||
def processEOF
|
||||
startTagHead('head', {})
|
||||
@parser.phase.processEOF
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
startTagHead('head', {})
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
|
||||
def startTagHead(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.headPointer = @tree.openElements[-1]
|
||||
@parser.phase = @parser.phases[:inHead]
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
startTagHead('head', {})
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagImplyHead(name)
|
||||
startTagHead('head', {})
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}) after the (implied) root element."))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
592
vendor/plugins/HTML5lib/lib/html5/html5parser/in_body_phase.rb
vendored
Normal file
592
vendor/plugins/HTML5lib/lib/html5/html5parser/in_body_phase.rb
vendored
Normal file
|
@ -0,0 +1,592 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InBodyPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-body
|
||||
|
||||
handle_start 'html'
|
||||
handle_start %w( base link meta script style ) => 'ProcessInHead'
|
||||
handle_start 'title'
|
||||
|
||||
handle_start 'body', 'form', 'plaintext', 'a', 'button', 'xmp', 'table', 'hr', 'image'
|
||||
|
||||
handle_start 'input', 'textarea', 'select', 'isindex', %w( marquee object )
|
||||
|
||||
handle_start %w( li dd dt ) => 'ListItem'
|
||||
|
||||
handle_start %w( address blockquote center dir div dl fieldset listing menu ol p pre ul ) => 'CloseP'
|
||||
|
||||
handle_start %w( b big em font i s small strike strong tt u ) => 'Formatting'
|
||||
handle_start 'nobr'
|
||||
|
||||
handle_start %w( area basefont bgsound br embed img param spacer wbr ) => 'VoidFormatting'
|
||||
|
||||
handle_start %w( iframe noembed noframes noscript ) => 'Cdata', HEADING_ELEMENTS => 'Heading'
|
||||
|
||||
handle_start %w( caption col colgroup frame frameset head option optgroup tbody td tfoot th thead tr ) => 'Misplaced'
|
||||
|
||||
handle_start %w( event-source section nav article aside header footer datagrid command ) => 'New'
|
||||
|
||||
handle_end 'p', 'body', 'html', 'form', %w( button marquee object ), %w( dd dt li ) => 'ListItem'
|
||||
|
||||
handle_end %w( address blockquote center div dl fieldset listing menu ol pre ul ) => 'Block'
|
||||
|
||||
handle_end HEADING_ELEMENTS => 'Heading'
|
||||
|
||||
handle_end %w( a b big em font i nobr s small strike strong tt u ) => 'Formatting'
|
||||
|
||||
handle_end %w( head frameset select optgroup option table caption colgroup col thead tfoot tbody tr td th ) => 'Misplaced'
|
||||
|
||||
handle_end 'br'
|
||||
|
||||
handle_end %w( area basefont bgsound embed hr image img input isindex param spacer wbr frame ) => 'None'
|
||||
|
||||
handle_end %w( noframes noscript noembed textarea xmp iframe ) => 'CdataTextAreaXmp'
|
||||
|
||||
handle_end %w( event-source section nav article aside header footer datagrid command ) => 'New'
|
||||
|
||||
def initialize(parser, tree)
|
||||
super(parser, tree)
|
||||
|
||||
# for special handling of whitespace in <pre>
|
||||
@processSpaceCharactersDropNewline = false
|
||||
end
|
||||
|
||||
def processSpaceCharactersDropNewline(data)
|
||||
#Sometimes (start of <pre> blocks) we want to drop leading newlines
|
||||
@processSpaceCharactersDropNewline = false
|
||||
if (data.length > 0 and data[0] == ?\n and
|
||||
%w[pre textarea].include?(@tree.openElements[-1].name) and
|
||||
not @tree.openElements[-1].hasContent)
|
||||
data = data[1..-1]
|
||||
end
|
||||
@tree.insertText(data) if data.length > 0
|
||||
end
|
||||
|
||||
def processSpaceCharacters(data)
|
||||
if @processSpaceCharactersDropNewline
|
||||
processSpaceCharactersDropNewline(data)
|
||||
else
|
||||
super(data)
|
||||
end
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
# XXX The specification says to do this for every character at the
|
||||
# moment, but apparently that doesn't match the real world so we don't
|
||||
# do it for space characters.
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertText(data)
|
||||
end
|
||||
|
||||
def startTagProcessInHead(name, attributes)
|
||||
@parser.phases[:inHead].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagTitle(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag (#{name}) that belongs in the head. Moved."))
|
||||
@parser.phases[:inHead].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagBody(name, attributes)
|
||||
@parser.parseError(_('Unexpected start tag (body).'))
|
||||
|
||||
if (@tree.openElements.length == 1 or
|
||||
@tree.openElements[1].name != 'body')
|
||||
assert @parser.innerHTML
|
||||
else
|
||||
attributes.each do |attr, value|
|
||||
unless @tree.openElements[1].attributes.has_key?(attr)
|
||||
@tree.openElements[1].attributes[attr] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def startTagCloseP(name, attributes)
|
||||
endTagP('p') if in_scope?('p')
|
||||
@tree.insertElement(name, attributes)
|
||||
@processSpaceCharactersDropNewline = true if name == 'pre'
|
||||
end
|
||||
|
||||
def startTagForm(name, attributes)
|
||||
if @tree.formPointer
|
||||
@parser.parseError(_('Unexpected start tag (form). Ignored.'))
|
||||
else
|
||||
endTagP('p') if in_scope?('p')
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.formPointer = @tree.openElements[-1]
|
||||
end
|
||||
end
|
||||
|
||||
def startTagListItem(name, attributes)
|
||||
endTagP('p') if in_scope?('p')
|
||||
stopNames = {'li' => ['li'], 'dd' => ['dd', 'dt'], 'dt' => ['dd', 'dt']}
|
||||
stopName = stopNames[name]
|
||||
|
||||
@tree.openElements.reverse.each_with_index do |node, i|
|
||||
if stopName.include?(node.name)
|
||||
poppedNodes = (0..i).collect { @tree.openElements.pop }
|
||||
if i >= 1
|
||||
@parser.parseError(_("Missing end tag%s (%s)" % [
|
||||
(i>1 ? 's' : ''),
|
||||
poppedNodes.reverse.map {|item| item.name}.join(', ')]))
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
# Phrasing elements are all non special, non scoping, non
|
||||
# formatting elements
|
||||
break if ((SPECIAL_ELEMENTS + SCOPING_ELEMENTS).include?(node.name) and
|
||||
not ['address', 'div'].include?(node.name))
|
||||
end
|
||||
|
||||
# Always insert an <li> element.
|
||||
@tree.insertElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagPlaintext(name, attributes)
|
||||
endTagP('p') if in_scope?('p')
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.tokenizer.contentModelFlag = :PLAINTEXT
|
||||
end
|
||||
|
||||
def startTagHeading(name, attributes)
|
||||
endTagP('p') if in_scope?('p')
|
||||
|
||||
# Uncomment the following for IE7 behavior:
|
||||
# HEADING_ELEMENTS.each do |element|
|
||||
# if in_scope?(element)
|
||||
# @parser.parseError(_("Unexpected start tag (#{name})."))
|
||||
#
|
||||
# remove_open_elements_until do |element|
|
||||
# HEADING_ELEMENTS.include?(element.name)
|
||||
# end
|
||||
#
|
||||
# break
|
||||
# end
|
||||
# end
|
||||
@tree.insertElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagA(name, attributes)
|
||||
if afeAElement = @tree.elementInActiveFormattingElements('a')
|
||||
@parser.parseError(_('Unexpected start tag (a) implies end tag (a).'))
|
||||
endTagFormatting('a')
|
||||
@tree.openElements.delete(afeAElement) if @tree.openElements.include?(afeAElement)
|
||||
@tree.activeFormattingElements.delete(afeAElement) if @tree.activeFormattingElements.include?(afeAElement)
|
||||
end
|
||||
@tree.reconstructActiveFormattingElements
|
||||
addFormattingElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagFormatting(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
addFormattingElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagNobr(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
processEndTag('nobr') if in_scope?('nobr')
|
||||
addFormattingElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagButton(name, attributes)
|
||||
if in_scope?('button')
|
||||
@parser.parseError(_('Unexpected start tag (button) implied end tag (button).'))
|
||||
processEndTag('button')
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
else
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.activeFormattingElements.push(Marker)
|
||||
end
|
||||
end
|
||||
|
||||
def startTagMarqueeObject(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.activeFormattingElements.push(Marker)
|
||||
end
|
||||
|
||||
def startTagXmp(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.tokenizer.contentModelFlag = :CDATA
|
||||
end
|
||||
|
||||
def startTagTable(name, attributes)
|
||||
processEndTag('p') if in_scope?('p')
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inTable]
|
||||
end
|
||||
|
||||
def startTagVoidFormatting(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.openElements.pop
|
||||
end
|
||||
|
||||
def startTagHr(name, attributes)
|
||||
endTagP('p') if in_scope?('p')
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.openElements.pop
|
||||
end
|
||||
|
||||
def startTagImage(name, attributes)
|
||||
# No really...
|
||||
@parser.parseError(_('Unexpected start tag (image). Treated as img.'))
|
||||
processStartTag('img', attributes)
|
||||
end
|
||||
|
||||
def startTagInput(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
if @tree.formPointer
|
||||
# XXX Not exactly sure what to do here
|
||||
# @tree.openElements[-1].form = @tree.formPointer
|
||||
end
|
||||
@tree.openElements.pop
|
||||
end
|
||||
|
||||
def startTagIsindex(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag isindex. Don't use it!"))
|
||||
return if @tree.formPointer
|
||||
processStartTag('form', {})
|
||||
processStartTag('hr', {})
|
||||
processStartTag('p', {})
|
||||
processStartTag('label', {})
|
||||
# XXX Localization ...
|
||||
processCharacters('This is a searchable index. Insert your search keywords here:')
|
||||
attributes['name'] = 'isindex'
|
||||
attrs = attributes.to_a
|
||||
processStartTag('input', attributes)
|
||||
processEndTag('label')
|
||||
processEndTag('p')
|
||||
processStartTag('hr', {})
|
||||
processEndTag('form')
|
||||
end
|
||||
|
||||
def startTagTextarea(name, attributes)
|
||||
# XXX Form element pointer checking here as well...
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.tokenizer.contentModelFlag = :RCDATA
|
||||
@processSpaceCharactersDropNewline = true
|
||||
end
|
||||
|
||||
# iframe, noembed noframes, noscript(if scripting enabled)
|
||||
def startTagCdata(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.tokenizer.contentModelFlag = :CDATA
|
||||
end
|
||||
|
||||
def startTagSelect(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inSelect]
|
||||
end
|
||||
|
||||
def startTagMisplaced(name, attributes)
|
||||
# Elements that should be children of other elements that have a
|
||||
# different insertion mode; here they are ignored
|
||||
# "caption", "col", "colgroup", "frame", "frameset", "head",
|
||||
# "option", "optgroup", "tbody", "td", "tfoot", "th", "thead",
|
||||
# "tr", "noscript"
|
||||
@parser.parseError(_("Unexpected start tag (#{name}). Ignored."))
|
||||
end
|
||||
|
||||
def startTagNew(name, attributes)
|
||||
# New HTML5 elements, "event-source", "section", "nav",
|
||||
# "article", "aside", "header", "footer", "datagrid", "command"
|
||||
sys.stderr.write("Warning: Undefined behaviour for start tag #{name}")
|
||||
startTagOther(name, attributes)
|
||||
#raise NotImplementedError
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, attributes)
|
||||
end
|
||||
|
||||
def endTagP(name)
|
||||
@tree.generateImpliedEndTags('p') if in_scope?('p')
|
||||
@parser.parseError(_('Unexpected end tag (p).')) unless @tree.openElements[-1].name == 'p'
|
||||
if in_scope?('p')
|
||||
@tree.openElements.pop while in_scope?('p')
|
||||
else
|
||||
startTagCloseP('p', {})
|
||||
endTagP('p')
|
||||
end
|
||||
end
|
||||
|
||||
def endTagBody(name)
|
||||
# XXX Need to take open <p> tags into account here. We shouldn't imply
|
||||
# </p> but we should not throw a parse error either. Specification is
|
||||
# likely to be updated.
|
||||
unless @tree.openElements[1].name == 'body'
|
||||
# innerHTML case
|
||||
@parser.parseError
|
||||
return
|
||||
end
|
||||
unless @tree.openElements[-1].name == 'body'
|
||||
@parser.parseError(_("Unexpected end tag (body). Missing end tag (#{@tree.openElements[-1].name})."))
|
||||
end
|
||||
@parser.phase = @parser.phases[:afterBody]
|
||||
end
|
||||
|
||||
def endTagHtml(name)
|
||||
endTagBody(name)
|
||||
@parser.phase.processEndTag(name) unless @parser.innerHTML
|
||||
end
|
||||
|
||||
def endTagBlock(name)
|
||||
#Put us back in the right whitespace handling mode
|
||||
@processSpaceCharactersDropNewline = false if name == 'pre'
|
||||
|
||||
@tree.generateImpliedEndTags if in_scope?(name)
|
||||
|
||||
unless @tree.openElements[-1].name == name
|
||||
@parser.parseError(_("End tag (#{name}) seen too early. Expected other end tag."))
|
||||
end
|
||||
|
||||
if in_scope?(name)
|
||||
remove_open_elements_until(name)
|
||||
end
|
||||
end
|
||||
|
||||
def endTagForm(name)
|
||||
if in_scope?(name)
|
||||
@tree.generateImpliedEndTags
|
||||
end
|
||||
if @tree.openElements[-1].name != name
|
||||
@parser.parseError(_("End tag (form) seen too early. Ignored."))
|
||||
else
|
||||
@tree.openElements.pop
|
||||
end
|
||||
@tree.formPointer = nil
|
||||
end
|
||||
|
||||
def endTagListItem(name)
|
||||
# AT Could merge this with the Block case
|
||||
if in_scope?(name)
|
||||
@tree.generateImpliedEndTags(name)
|
||||
|
||||
unless @tree.openElements[-1].name == name
|
||||
@parser.parseError(_("End tag (#{name}) seen too early. Expected other end tag."))
|
||||
end
|
||||
end
|
||||
|
||||
remove_open_elements_until(name) if in_scope?(name)
|
||||
end
|
||||
|
||||
def endTagHeading(name)
|
||||
HEADING_ELEMENTS.each do |element|
|
||||
if in_scope?(element)
|
||||
@tree.generateImpliedEndTags
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
unless @tree.openElements[-1].name == name
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Expected other end tag."))
|
||||
end
|
||||
|
||||
HEADING_ELEMENTS.each do |element|
|
||||
if in_scope?(element)
|
||||
remove_open_elements_until { |element| HEADING_ELEMENTS.include?(element.name) }
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# The much-feared adoption agency algorithm
|
||||
def endTagFormatting(name)
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#adoptionAgency
|
||||
# XXX Better parseError messages appreciated.
|
||||
while true
|
||||
# Step 1 paragraph 1
|
||||
afeElement = @tree.elementInActiveFormattingElements(name)
|
||||
if not afeElement or (@tree.openElements.include?(afeElement) and not in_scope?(afeElement.name))
|
||||
@parser.parseError(_("End tag (#{name}) violates step 1, paragraph 1 of the adoption agency algorithm."))
|
||||
return
|
||||
# Step 1 paragraph 2
|
||||
elsif not @tree.openElements.include?(afeElement)
|
||||
@parser.parseError(_("End tag (#{name}) violates step 1, paragraph 2 of the adoption agency algorithm."))
|
||||
@tree.activeFormattingElements.delete(afeElement)
|
||||
return
|
||||
end
|
||||
|
||||
# Step 1 paragraph 3
|
||||
if afeElement != @tree.openElements[-1]
|
||||
@parser.parseError(_("End tag (#{name}) violates step 1, paragraph 3 of the adoption agency algorithm."))
|
||||
end
|
||||
|
||||
# Step 2
|
||||
# Start of the adoption agency algorithm proper
|
||||
afeIndex = @tree.openElements.index(afeElement)
|
||||
furthestBlock = nil
|
||||
@tree.openElements[afeIndex..-1].each do |element|
|
||||
if (SPECIAL_ELEMENTS + SCOPING_ELEMENTS).include?(element.name)
|
||||
furthestBlock = element
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Step 3
|
||||
if furthestBlock.nil?
|
||||
element = remove_open_elements_until { |element| element == afeElement }
|
||||
@tree.activeFormattingElements.delete(element)
|
||||
return
|
||||
end
|
||||
commonAncestor = @tree.openElements[afeIndex - 1]
|
||||
|
||||
# Step 5
|
||||
furthestBlock.parent.removeChild(furthestBlock) if furthestBlock.parent
|
||||
|
||||
# Step 6
|
||||
# The bookmark is supposed to help us identify where to reinsert
|
||||
# nodes in step 12. We have to ensure that we reinsert nodes after
|
||||
# the node before the active formatting element. Note the bookmark
|
||||
# can move in step 7.4
|
||||
bookmark = @tree.activeFormattingElements.index(afeElement)
|
||||
|
||||
# Step 7
|
||||
lastNode = node = furthestBlock
|
||||
while true
|
||||
# AT replace this with a function and recursion?
|
||||
# Node is element before node in open elements
|
||||
node = @tree.openElements[@tree.openElements.index(node) - 1]
|
||||
until @tree.activeFormattingElements.include?(node)
|
||||
tmpNode = node
|
||||
node = @tree.openElements[@tree.openElements.index(node) - 1]
|
||||
@tree.openElements.delete(tmpNode)
|
||||
end
|
||||
# Step 7.3
|
||||
break if node == afeElement
|
||||
# Step 7.4
|
||||
if lastNode == furthestBlock
|
||||
# XXX should this be index(node) or index(node)+1
|
||||
# Anne: I think +1 is ok. Given x = [2,3,4,5]
|
||||
# x.index(3) gives 1 and then x[1 +1] gives 4...
|
||||
bookmark = @tree.activeFormattingElements.index(node) + 1
|
||||
end
|
||||
# Step 7.5
|
||||
cite = node.parent
|
||||
if node.hasContent
|
||||
clone = node.cloneNode
|
||||
# Replace node with clone
|
||||
@tree.activeFormattingElements[@tree.activeFormattingElements.index(node)] = clone
|
||||
@tree.openElements[@tree.openElements.index(node)] = clone
|
||||
node = clone
|
||||
end
|
||||
# Step 7.6
|
||||
# Remove lastNode from its parents, if any
|
||||
lastNode.parent.removeChild(lastNode) if lastNode.parent
|
||||
node.appendChild(lastNode)
|
||||
# Step 7.7
|
||||
lastNode = node
|
||||
# End of inner loop
|
||||
end
|
||||
|
||||
# Step 8
|
||||
lastNode.parent.removeChild(lastNode) if lastNode.parent
|
||||
commonAncestor.appendChild(lastNode)
|
||||
|
||||
# Step 9
|
||||
clone = afeElement.cloneNode
|
||||
|
||||
# Step 10
|
||||
furthestBlock.reparentChildren(clone)
|
||||
|
||||
# Step 11
|
||||
furthestBlock.appendChild(clone)
|
||||
|
||||
# Step 12
|
||||
@tree.activeFormattingElements.delete(afeElement)
|
||||
@tree.activeFormattingElements.insert([bookmark,@tree.activeFormattingElements.length].min, clone)
|
||||
|
||||
# Step 13
|
||||
@tree.openElements.delete(afeElement)
|
||||
@tree.openElements.insert(@tree.openElements.index(furthestBlock) + 1, clone)
|
||||
end
|
||||
end
|
||||
|
||||
def endTagButtonMarqueeObject(name)
|
||||
@tree.generateImpliedEndTags if in_scope?(name)
|
||||
|
||||
unless @tree.openElements[-1].name == name
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Expected other end tag first."))
|
||||
end
|
||||
|
||||
if in_scope?(name)
|
||||
remove_open_elements_until(name)
|
||||
|
||||
@tree.clearActiveFormattingElements
|
||||
end
|
||||
end
|
||||
|
||||
def endTagMisplaced(name)
|
||||
# This handles elements with end tags in other insertion modes.
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
|
||||
def endTagBr(name)
|
||||
@parser.parseError(_("Unexpected end tag (br). Treated as br element."))
|
||||
@tree.reconstructActiveFormattingElements
|
||||
@tree.insertElement(name, {})
|
||||
@tree.openElements.pop()
|
||||
end
|
||||
|
||||
def endTagNone(name)
|
||||
# This handles elements with no end tag.
|
||||
@parser.parseError(_("This tag (#{name}) has no end tag"))
|
||||
end
|
||||
|
||||
def endTagCdataTextAreaXmp(name)
|
||||
if @tree.openElements[-1].name == name
|
||||
@tree.openElements.pop
|
||||
else
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
end
|
||||
|
||||
def endTagNew(name)
|
||||
# New HTML5 elements, "event-source", "section", "nav",
|
||||
# "article", "aside", "header", "footer", "datagrid", "command"
|
||||
STDERR.puts "Warning: Undefined behaviour for end tag #{name}"
|
||||
endTagOther(name)
|
||||
#raise NotImplementedError
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
# XXX This logic should be moved into the treebuilder
|
||||
@tree.openElements.reverse.each do |node|
|
||||
if node.name == name
|
||||
@tree.generateImpliedEndTags
|
||||
|
||||
unless @tree.openElements[-1].name == name
|
||||
@parser.parseError(_("Unexpected end tag (#{name})."))
|
||||
end
|
||||
|
||||
remove_open_elements_until { |element| element == node }
|
||||
|
||||
break
|
||||
else
|
||||
if (SPECIAL_ELEMENTS + SCOPING_ELEMENTS).include?(node.name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def addFormattingElement(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.activeFormattingElements.push(@tree.openElements[-1])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
68
vendor/plugins/HTML5lib/lib/html5/html5parser/in_caption_phase.rb
vendored
Normal file
68
vendor/plugins/HTML5lib/lib/html5/html5parser/in_caption_phase.rb
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InCaptionPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-caption
|
||||
|
||||
handle_start 'html', %w( caption col colgroup tbody td tfoot th thead tr ) => 'TableElement'
|
||||
|
||||
handle_end 'caption', 'table', %w( body col colgroup html tbody td tfoot th thead tr ) => 'Ignore'
|
||||
|
||||
def ignoreEndTagCaption
|
||||
not in_scope?('caption', true)
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.phases[:inBody].processCharacters(data)
|
||||
end
|
||||
|
||||
def startTagTableElement(name, attributes)
|
||||
@parser.parseError
|
||||
#XXX Have to duplicate logic here to find out if the tag is ignored
|
||||
ignoreEndTag = ignoreEndTagCaption
|
||||
@parser.phase.processEndTag('caption')
|
||||
@parser.phase.processStartTag(name, attributes) unless ignoreEndTag
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.phases[:inBody].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagCaption(name)
|
||||
if ignoreEndTagCaption
|
||||
# innerHTML case
|
||||
assert @parser.innerHTML
|
||||
@parser.parseError
|
||||
else
|
||||
# AT this code is quite similar to endTagTable in "InTable"
|
||||
@tree.generateImpliedEndTags
|
||||
|
||||
unless @tree.openElements[-1].name == 'caption'
|
||||
@parser.parseError(_("Unexpected end tag (caption). Missing end tags."))
|
||||
end
|
||||
|
||||
remove_open_elements_until('caption')
|
||||
|
||||
@tree.clearActiveFormattingElements
|
||||
@parser.phase = @parser.phases[:inTable]
|
||||
end
|
||||
end
|
||||
|
||||
def endTagTable(name)
|
||||
@parser.parseError
|
||||
ignoreEndTag = ignoreEndTagCaption
|
||||
@parser.phase.processEndTag('caption')
|
||||
@parser.phase.processEndTag(name) unless ignoreEndTag
|
||||
end
|
||||
|
||||
def endTagIgnore(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.phases[:inBody].processEndTag(name)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
78
vendor/plugins/HTML5lib/lib/html5/html5parser/in_cell_phase.rb
vendored
Normal file
78
vendor/plugins/HTML5lib/lib/html5/html5parser/in_cell_phase.rb
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InCellPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-cell
|
||||
|
||||
handle_start 'html', %w( caption col colgroup tbody td tfoot th thead tr ) => 'TableOther'
|
||||
|
||||
handle_end %w( td th ) => 'TableCell', %w( body caption col colgroup html ) => 'Ignore'
|
||||
|
||||
handle_end %w( table tbody tfoot thead tr ) => 'Imply'
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.phases[:inBody].processCharacters(data)
|
||||
end
|
||||
|
||||
def startTagTableOther(name, attributes)
|
||||
if in_scope?('td', true) or in_scope?('th', true)
|
||||
closeCell
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
else
|
||||
# innerHTML case
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.phases[:inBody].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagTableCell(name)
|
||||
if in_scope?(name, true)
|
||||
@tree.generateImpliedEndTags(name)
|
||||
if @tree.openElements[-1].name != name
|
||||
@parser.parseError("Got table cell end tag (#{name}) while required end tags are missing.")
|
||||
|
||||
remove_open_elements_until(name)
|
||||
else
|
||||
@tree.openElements.pop
|
||||
end
|
||||
@tree.clearActiveFormattingElements
|
||||
@parser.phase = @parser.phases[:inRow]
|
||||
else
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
end
|
||||
|
||||
def endTagIgnore(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
|
||||
def endTagImply(name)
|
||||
if in_scope?(name, true)
|
||||
closeCell
|
||||
@parser.phase.processEndTag(name)
|
||||
else
|
||||
# sometimes innerHTML case
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.phases[:inBody].processEndTag(name)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def closeCell
|
||||
if in_scope?('td', true)
|
||||
endTagTableCell('td')
|
||||
elsif in_scope?('th', true)
|
||||
endTagTableCell('th')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
55
vendor/plugins/HTML5lib/lib/html5/html5parser/in_column_group_phase.rb
vendored
Normal file
55
vendor/plugins/HTML5lib/lib/html5/html5parser/in_column_group_phase.rb
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InColumnGroupPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-column
|
||||
|
||||
handle_start 'html', 'col'
|
||||
|
||||
handle_end 'colgroup', 'col'
|
||||
|
||||
def ignoreEndTagColgroup
|
||||
@tree.openElements[-1].name == 'html'
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
ignoreEndTag = ignoreEndTagColgroup
|
||||
endTagColgroup("colgroup")
|
||||
@parser.phase.processCharacters(data) unless ignoreEndTag
|
||||
end
|
||||
|
||||
def startTagCol(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.openElements.pop
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
ignoreEndTag = ignoreEndTagColgroup
|
||||
endTagColgroup('colgroup')
|
||||
@parser.phase.processStartTag(name, attributes) unless ignoreEndTag
|
||||
end
|
||||
|
||||
def endTagColgroup(name)
|
||||
if ignoreEndTagColgroup
|
||||
# innerHTML case
|
||||
assert @parser.innerHTML
|
||||
@parser.parseError
|
||||
else
|
||||
@tree.openElements.pop
|
||||
@parser.phase = @parser.phases[:inTable]
|
||||
end
|
||||
end
|
||||
|
||||
def endTagCol(name)
|
||||
@parser.parseError(_('Unexpected end tag (col). col has no end tag.'))
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
ignoreEndTag = ignoreEndTagColgroup
|
||||
endTagColgroup('colgroup')
|
||||
@parser.phase.processEndTag(name) unless ignoreEndTag
|
||||
end
|
||||
|
||||
end
|
||||
end
|
57
vendor/plugins/HTML5lib/lib/html5/html5parser/in_frameset_phase.rb
vendored
Normal file
57
vendor/plugins/HTML5lib/lib/html5/html5parser/in_frameset_phase.rb
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InFramesetPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-frameset
|
||||
|
||||
handle_start 'html', 'frameset', 'frame', 'noframes'
|
||||
|
||||
handle_end 'frameset', 'noframes'
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.parseError(_('Unexpected characters in the frameset phase. Characters ignored.'))
|
||||
end
|
||||
|
||||
def startTagFrameset(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagFrame(name, attributes)
|
||||
@tree.insertElement(name, attributes)
|
||||
@tree.openElements.pop
|
||||
end
|
||||
|
||||
def startTagNoframes(name, attributes)
|
||||
@parser.phases[:inBody].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag token (#{name}) in the frameset phase. Ignored"))
|
||||
end
|
||||
|
||||
def endTagFrameset(name)
|
||||
if @tree.openElements[-1].name == 'html'
|
||||
# innerHTML case
|
||||
@parser.parseError(_("Unexpected end tag token (frameset) in the frameset phase (innerHTML)."))
|
||||
else
|
||||
@tree.openElements.pop
|
||||
end
|
||||
if (not @parser.innerHTML and
|
||||
@tree.openElements[-1].name != 'frameset')
|
||||
# If we're not in innerHTML mode and the the current node is not a
|
||||
# "frameset" element (anymore) then switch.
|
||||
@parser.phase = @parser.phases[:afterFrameset]
|
||||
end
|
||||
end
|
||||
|
||||
def endTagNoframes(name)
|
||||
@parser.phases[:inBody].processEndTag(name)
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag token (#{name}) in the frameset phase. Ignored."))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
126
vendor/plugins/HTML5lib/lib/html5/html5parser/in_head_phase.rb
vendored
Normal file
126
vendor/plugins/HTML5lib/lib/html5/html5parser/in_head_phase.rb
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InHeadPhase < Phase
|
||||
|
||||
handle_start 'html', 'head', 'title', 'style', 'script', %w( base link meta )
|
||||
|
||||
handle_end 'head'
|
||||
handle_end %w( html body br p ) => 'ImplyAfterHead'
|
||||
handle_end %w( title style script )
|
||||
|
||||
def processEOF
|
||||
if ['title', 'style', 'script'].include?(name = @tree.openElements[-1].name)
|
||||
@parser.parseError(_("Unexpected end of file. Expected end tag (#{name})."))
|
||||
@tree.openElements.pop
|
||||
end
|
||||
anythingElse
|
||||
@parser.phase.processEOF
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
if ['title', 'style', 'script'].include?(@tree.openElements[-1].name)
|
||||
@tree.insertText(data)
|
||||
else
|
||||
anythingElse
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
end
|
||||
|
||||
def startTagHead(name, attributes)
|
||||
@parser.parseError(_('Unexpected start tag head in existing head. Ignored'))
|
||||
end
|
||||
|
||||
def startTagTitle(name, attributes)
|
||||
element = @tree.createElement(name, attributes)
|
||||
appendToHead(element)
|
||||
@tree.openElements.push(element)
|
||||
@parser.tokenizer.contentModelFlag = :RCDATA
|
||||
end
|
||||
|
||||
def startTagStyle(name, attributes)
|
||||
element = @tree.createElement(name, attributes)
|
||||
if @tree.headPointer != nil and @parser.phase == @parser.phases[:inHead]
|
||||
appendToHead(element)
|
||||
else
|
||||
@tree.openElements[-1].appendChild(element)
|
||||
end
|
||||
@tree.openElements.push(element)
|
||||
@parser.tokenizer.contentModelFlag = :CDATA
|
||||
end
|
||||
|
||||
def startTagScript(name, attributes)
|
||||
#XXX Inner HTML case may be wrong
|
||||
element = @tree.createElement(name, attributes)
|
||||
element._flags.push("parser-inserted")
|
||||
if (@tree.headPointer != nil and
|
||||
@parser.phase == @parser.phases[:inHead])
|
||||
appendToHead(element)
|
||||
else
|
||||
@tree.openElements[-1].appendChild(element)
|
||||
end
|
||||
@tree.openElements.push(element)
|
||||
@parser.tokenizer.contentModelFlag = :CDATA
|
||||
end
|
||||
|
||||
def startTagBaseLinkMeta(name, attributes)
|
||||
element = @tree.createElement(name, attributes)
|
||||
if @tree.headPointer != nil and @parser.phase == @parser.phases[:inHead]
|
||||
appendToHead(element)
|
||||
else
|
||||
@tree.openElements[-1].appendChild(element)
|
||||
end
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
anythingElse
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagHead(name)
|
||||
if @tree.openElements[-1].name == 'head'
|
||||
@tree.openElements.pop
|
||||
else
|
||||
@parser.parseError(_("Unexpected end tag (head). Ignored."))
|
||||
end
|
||||
@parser.phase = @parser.phases[:afterHead]
|
||||
end
|
||||
|
||||
def endTagImplyAfterHead(name)
|
||||
anythingElse
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
def endTagTitleStyleScript(name)
|
||||
if @tree.openElements[-1].name == name
|
||||
@tree.openElements.pop
|
||||
else
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
|
||||
def anythingElse
|
||||
if @tree.openElements[-1].name == 'head'
|
||||
endTagHead('head')
|
||||
else
|
||||
@parser.phase = @parser.phases[:afterHead]
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def appendToHead(element)
|
||||
if @tree.headPointer.nil?
|
||||
assert @parser.innerHTML
|
||||
@tree.openElements[-1].appendChild(element)
|
||||
else
|
||||
@tree.headPointer.appendChild(element)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
87
vendor/plugins/HTML5lib/lib/html5/html5parser/in_row_phase.rb
vendored
Normal file
87
vendor/plugins/HTML5lib/lib/html5/html5parser/in_row_phase.rb
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InRowPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-row
|
||||
|
||||
handle_start 'html', %w( td th ) => 'TableCell', %w( caption col colgroup tbody tfoot thead tr ) => 'TableOther'
|
||||
|
||||
handle_end 'tr', 'table', %w( tbody tfoot thead ) => 'TableRowGroup', %w( body caption col colgroup html td th ) => 'Ignore'
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.phases[:inTable].processCharacters(data)
|
||||
end
|
||||
|
||||
def startTagTableCell(name, attributes)
|
||||
clearStackToTableRowContext
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inCell]
|
||||
@tree.activeFormattingElements.push(Marker)
|
||||
end
|
||||
|
||||
def startTagTableOther(name, attributes)
|
||||
ignoreEndTag = ignoreEndTagTr
|
||||
endTagTr('tr')
|
||||
# XXX how are we sure it's always ignored in the innerHTML case?
|
||||
@parser.phase.processStartTag(name, attributes) unless ignoreEndTag
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.phases[:inTable].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagTr(name)
|
||||
if ignoreEndTagTr
|
||||
# innerHTML case
|
||||
assert @parser.innerHTML
|
||||
@parser.parseError
|
||||
else
|
||||
clearStackToTableRowContext
|
||||
@tree.openElements.pop
|
||||
@parser.phase = @parser.phases[:inTableBody]
|
||||
end
|
||||
end
|
||||
|
||||
def endTagTable(name)
|
||||
ignoreEndTag = ignoreEndTagTr
|
||||
endTagTr('tr')
|
||||
# Reprocess the current tag if the tr end tag was not ignored
|
||||
# XXX how are we sure it's always ignored in the innerHTML case?
|
||||
@parser.phase.processEndTag(name) unless ignoreEndTag
|
||||
end
|
||||
|
||||
def endTagTableRowGroup(name)
|
||||
if in_scope?(name, true)
|
||||
endTagTr('tr')
|
||||
@parser.phase.processEndTag(name)
|
||||
else
|
||||
# innerHTML case
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def endTagIgnore(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}) in the row phase. Ignored."))
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.phases[:inTable].processEndTag(name)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# XXX unify this with other table helper methods
|
||||
def clearStackToTableRowContext
|
||||
until ['tr', 'html'].include?(name = @tree.openElements[-1].name)
|
||||
@parser.parseError(_("Unexpected implied end tag (#{name}) in the row phase."))
|
||||
@tree.openElements.pop
|
||||
end
|
||||
end
|
||||
|
||||
def ignoreEndTagTr
|
||||
not in_scope?('tr', :tableVariant => true)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
84
vendor/plugins/HTML5lib/lib/html5/html5parser/in_select_phase.rb
vendored
Normal file
84
vendor/plugins/HTML5lib/lib/html5/html5parser/in_select_phase.rb
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InSelectPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-select
|
||||
|
||||
handle_start 'html', 'option', 'optgroup', 'select'
|
||||
|
||||
handle_end 'option', 'optgroup', 'select', %w( caption table tbody tfoot thead tr td th ) => 'TableElements'
|
||||
|
||||
def processCharacters(data)
|
||||
@tree.insertText(data)
|
||||
end
|
||||
|
||||
def startTagOption(name, attributes)
|
||||
# We need to imply </option> if <option> is the current node.
|
||||
@tree.openElements.pop if @tree.openElements[-1].name == 'option'
|
||||
@tree.insertElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagOptgroup(name, attributes)
|
||||
@tree.openElements.pop if @tree.openElements[-1].name == 'option'
|
||||
@tree.openElements.pop if @tree.openElements[-1].name == 'optgroup'
|
||||
@tree.insertElement(name, attributes)
|
||||
end
|
||||
|
||||
def startTagSelect(name, attributes)
|
||||
@parser.parseError(_('Unexpected start tag (select) in the select phase implies select start tag.'))
|
||||
endTagSelect('select')
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.parseError(_('Unexpected start tag token (#{name}) in the select phase. Ignored.'))
|
||||
end
|
||||
|
||||
def endTagOption(name)
|
||||
if @tree.openElements[-1].name == 'option'
|
||||
@tree.openElements.pop
|
||||
else
|
||||
@parser.parseError(_('Unexpected end tag (option) in the select phase. Ignored.'))
|
||||
end
|
||||
end
|
||||
|
||||
def endTagOptgroup(name)
|
||||
# </optgroup> implicitly closes <option>
|
||||
if @tree.openElements[-1].name == 'option' and @tree.openElements[-2].name == 'optgroup'
|
||||
@tree.openElements.pop
|
||||
end
|
||||
# It also closes </optgroup>
|
||||
if @tree.openElements[-1].name == 'optgroup'
|
||||
@tree.openElements.pop
|
||||
# But nothing else
|
||||
else
|
||||
@parser.parseError(_('Unexpected end tag (optgroup) in the select phase. Ignored.'))
|
||||
end
|
||||
end
|
||||
|
||||
def endTagSelect(name)
|
||||
if in_scope?('select', true)
|
||||
remove_open_elements_until('select')
|
||||
|
||||
@parser.resetInsertionMode
|
||||
else
|
||||
# innerHTML case
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def endTagTableElements(name)
|
||||
@parser.parseError(_("Unexpected table end tag (#{name}) in the select phase."))
|
||||
|
||||
if in_scope?(name, true)
|
||||
endTagSelect('select')
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag token (#{name}) in the select phase. Ignored."))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
83
vendor/plugins/HTML5lib/lib/html5/html5parser/in_table_body_phase.rb
vendored
Normal file
83
vendor/plugins/HTML5lib/lib/html5/html5parser/in_table_body_phase.rb
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InTableBodyPhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-table0
|
||||
|
||||
handle_start 'html', 'tr', %w( td th ) => 'TableCell', %w( caption col colgroup tbody tfoot thead ) => 'TableOther'
|
||||
|
||||
handle_end 'table', %w( tbody tfoot thead ) => 'TableRowGroup', %w( body caption col colgroup html td th tr ) => 'Ingore'
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.phases[:inTable].processCharacters(data)
|
||||
end
|
||||
|
||||
def startTagTr(name, attributes)
|
||||
clearStackToTableBodyContext
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inRow]
|
||||
end
|
||||
|
||||
def startTagTableCell(name, attributes)
|
||||
@parser.parseError(_("Unexpected table cell start tag (#{name}) in the table body phase."))
|
||||
startTagTr('tr', {})
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagTableOther(name, attributes)
|
||||
# XXX AT Any ideas on how to share this with endTagTable?
|
||||
if in_scope?('tbody', true) or in_scope?('thead', true) or in_scope?('tfoot', true)
|
||||
clearStackToTableBodyContext
|
||||
endTagTableRowGroup(@tree.openElements[-1].name)
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
else
|
||||
# innerHTML case
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.phases[:inTable].processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def endTagTableRowGroup(name)
|
||||
if in_scope?(name, true)
|
||||
clearStackToTableBodyContext
|
||||
@tree.openElements.pop
|
||||
@parser.phase = @parser.phases[:inTable]
|
||||
else
|
||||
@parser.parseError(_("Unexpected end tag (#{name}) in the table body phase. Ignored."))
|
||||
end
|
||||
end
|
||||
|
||||
def endTagTable(name)
|
||||
if in_scope?('tbody', true) or in_scope?('thead', true) or in_scope?('tfoot', true)
|
||||
clearStackToTableBodyContext
|
||||
endTagTableRowGroup(@tree.openElements[-1].name)
|
||||
@parser.phase.processEndTag(name)
|
||||
else
|
||||
# innerHTML case
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def endTagIgnore(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}) in the table body phase. Ignored."))
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.phases[:inTable].processEndTag(name)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def clearStackToTableBodyContext
|
||||
until ['tbody', 'tfoot', 'thead', 'html'].include?(name = @tree.openElements[-1].name)
|
||||
@parser.parseError(_("Unexpected implied end tag (#{name}) in the table body phase."))
|
||||
@tree.openElements.pop
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
110
vendor/plugins/HTML5lib/lib/html5/html5parser/in_table_phase.rb
vendored
Normal file
110
vendor/plugins/HTML5lib/lib/html5/html5parser/in_table_phase.rb
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InTablePhase < Phase
|
||||
|
||||
# http://www.whatwg.org/specs/web-apps/current-work/#in-table
|
||||
|
||||
handle_start 'html', 'caption', 'colgroup', 'col', 'table'
|
||||
|
||||
handle_start %w( tbody tfoot thead ) => 'RowGroup', %w( td th tr ) => 'ImplyTbody'
|
||||
|
||||
handle_end 'table', %w( body caption col colgroup html tbody td tfoot th thead tr ) => 'Ignore'
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.parseError(_("Unexpected non-space characters in table context caused voodoo mode."))
|
||||
# Make all the special element rearranging voodoo kick in
|
||||
@tree.insertFromTable = true
|
||||
# Process the character in the "in body" mode
|
||||
@parser.phases[:inBody].processCharacters(data)
|
||||
@tree.insertFromTable = false
|
||||
end
|
||||
|
||||
def startTagCaption(name, attributes)
|
||||
clearStackToTableContext
|
||||
@tree.activeFormattingElements.push(Marker)
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inCaption]
|
||||
end
|
||||
|
||||
def startTagColgroup(name, attributes)
|
||||
clearStackToTableContext
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inColumnGroup]
|
||||
end
|
||||
|
||||
def startTagCol(name, attributes)
|
||||
startTagColgroup('colgroup', {})
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagRowGroup(name, attributes)
|
||||
clearStackToTableContext
|
||||
@tree.insertElement(name, attributes)
|
||||
@parser.phase = @parser.phases[:inTableBody]
|
||||
end
|
||||
|
||||
def startTagImplyTbody(name, attributes)
|
||||
startTagRowGroup('tbody', {})
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def startTagTable(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag (table) in table phase. Implies end tag (table)."))
|
||||
@parser.phase.processEndTag('table')
|
||||
@parser.phase.processStartTag(name, attributes) unless @parser.innerHTML
|
||||
end
|
||||
|
||||
def startTagOther(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag (#{name}) in table context caused voodoo mode."))
|
||||
# Make all the special element rearranging voodoo kick in
|
||||
@tree.insertFromTable = true
|
||||
# Process the start tag in the "in body" mode
|
||||
@parser.phases[:inBody].processStartTag(name, attributes)
|
||||
@tree.insertFromTable = false
|
||||
end
|
||||
|
||||
def endTagTable(name)
|
||||
if in_scope?('table', true)
|
||||
@tree.generateImpliedEndTags
|
||||
|
||||
unless @tree.openElements[-1].name == 'table'
|
||||
@parser.parseError(_("Unexpected end tag (table). Expected end tag (#{@tree.openElements[-1].name})."))
|
||||
end
|
||||
|
||||
remove_open_elements_until('table')
|
||||
|
||||
@parser.resetInsertionMode
|
||||
else
|
||||
# innerHTML case
|
||||
assert @parser.innerHTML
|
||||
@parser.parseError
|
||||
end
|
||||
end
|
||||
|
||||
def endTagIgnore(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Ignored."))
|
||||
end
|
||||
|
||||
def endTagOther(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}) in table context caused voodoo mode."))
|
||||
# Make all the special element rearranging voodoo kick in
|
||||
@tree.insertFromTable = true
|
||||
# Process the end tag in the "in body" mode
|
||||
@parser.phases[:inBody].processEndTag(name)
|
||||
@tree.insertFromTable = false
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def clearStackToTableContext
|
||||
# "clear the stack back to a table context"
|
||||
until ['table', 'html'].include?(name = @tree.openElements[-1].name)
|
||||
@parser.parseError(_("Unexpected implied end tag (#{name}) in the table phase."))
|
||||
@tree.openElements.pop
|
||||
end
|
||||
# When the current node is <html> it's an innerHTML case
|
||||
end
|
||||
|
||||
end
|
||||
end
|
135
vendor/plugins/HTML5lib/lib/html5/html5parser/initial_phase.rb
vendored
Normal file
135
vendor/plugins/HTML5lib/lib/html5/html5parser/initial_phase.rb
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class InitialPhase < Phase
|
||||
|
||||
# This phase deals with error handling as well which is currently not
|
||||
# covered in the specification. The error handling is typically known as
|
||||
# "quirks mode". It is expected that a future version of HTML5 will define this.
|
||||
|
||||
def processEOF
|
||||
@parser.parseError(_('Unexpected End of file. Expected DOCTYPE.'))
|
||||
@parser.phase = @parser.phases[:rootElement]
|
||||
@parser.phase.processEOF
|
||||
end
|
||||
|
||||
def processComment(data)
|
||||
@tree.insertComment(data, @tree.document)
|
||||
end
|
||||
|
||||
def processDoctype(name, publicId, systemId, correct)
|
||||
if name.downcase != 'html' or publicId or systemId
|
||||
@parser.parseError(_('Erroneous DOCTYPE.'))
|
||||
end
|
||||
# XXX need to update DOCTYPE tokens
|
||||
@tree.insertDoctype(name)
|
||||
|
||||
publicId = publicId.to_s.upcase
|
||||
|
||||
if name.downcase != 'html'
|
||||
# XXX quirks mode
|
||||
else
|
||||
if ["+//silmaril//dtd html pro v0r11 19970101//en",
|
||||
"-//advasoft ltd//dtd html 3.0 aswedit + extensions//en",
|
||||
"-//as//dtd html 3.0 aswedit + extensions//en",
|
||||
"-//ietf//dtd html 2.0 level 1//en",
|
||||
"-//ietf//dtd html 2.0 level 2//en",
|
||||
"-//ietf//dtd html 2.0 strict level 1//en",
|
||||
"-//ietf//dtd html 2.0 strict level 2//en",
|
||||
"-//ietf//dtd html 2.0 strict//en",
|
||||
"-//ietf//dtd html 2.0//en",
|
||||
"-//ietf//dtd html 2.1e//en",
|
||||
"-//ietf//dtd html 3.0//en",
|
||||
"-//ietf//dtd html 3.0//en//",
|
||||
"-//ietf//dtd html 3.2 final//en",
|
||||
"-//ietf//dtd html 3.2//en",
|
||||
"-//ietf//dtd html 3//en",
|
||||
"-//ietf//dtd html level 0//en",
|
||||
"-//ietf//dtd html level 0//en//2.0",
|
||||
"-//ietf//dtd html level 1//en",
|
||||
"-//ietf//dtd html level 1//en//2.0",
|
||||
"-//ietf//dtd html level 2//en",
|
||||
"-//ietf//dtd html level 2//en//2.0",
|
||||
"-//ietf//dtd html level 3//en",
|
||||
"-//ietf//dtd html level 3//en//3.0",
|
||||
"-//ietf//dtd html strict level 0//en",
|
||||
"-//ietf//dtd html strict level 0//en//2.0",
|
||||
"-//ietf//dtd html strict level 1//en",
|
||||
"-//ietf//dtd html strict level 1//en//2.0",
|
||||
"-//ietf//dtd html strict level 2//en",
|
||||
"-//ietf//dtd html strict level 2//en//2.0",
|
||||
"-//ietf//dtd html strict level 3//en",
|
||||
"-//ietf//dtd html strict level 3//en//3.0",
|
||||
"-//ietf//dtd html strict//en",
|
||||
"-//ietf//dtd html strict//en//2.0",
|
||||
"-//ietf//dtd html strict//en//3.0",
|
||||
"-//ietf//dtd html//en",
|
||||
"-//ietf//dtd html//en//2.0",
|
||||
"-//ietf//dtd html//en//3.0",
|
||||
"-//metrius//dtd metrius presentational//en",
|
||||
"-//microsoft//dtd internet explorer 2.0 html strict//en",
|
||||
"-//microsoft//dtd internet explorer 2.0 html//en",
|
||||
"-//microsoft//dtd internet explorer 2.0 tables//en",
|
||||
"-//microsoft//dtd internet explorer 3.0 html strict//en",
|
||||
"-//microsoft//dtd internet explorer 3.0 html//en",
|
||||
"-//microsoft//dtd internet explorer 3.0 tables//en",
|
||||
"-//netscape comm. corp.//dtd html//en",
|
||||
"-//netscape comm. corp.//dtd strict html//en",
|
||||
"-//o'reilly and associates//dtd html 2.0//en",
|
||||
"-//o'reilly and associates//dtd html extended 1.0//en",
|
||||
"-//spyglass//dtd html 2.0 extended//en",
|
||||
"-//sq//dtd html 2.0 hotmetal + extensions//en",
|
||||
"-//sun microsystems corp.//dtd hotjava html//en",
|
||||
"-//sun microsystems corp.//dtd hotjava strict html//en",
|
||||
"-//w3c//dtd html 3 1995-03-24//en",
|
||||
"-//w3c//dtd html 3.2 draft//en",
|
||||
"-//w3c//dtd html 3.2 final//en",
|
||||
"-//w3c//dtd html 3.2//en",
|
||||
"-//w3c//dtd html 3.2s draft//en",
|
||||
"-//w3c//dtd html 4.0 frameset//en",
|
||||
"-//w3c//dtd html 4.0 transitional//en",
|
||||
"-//w3c//dtd html experimental 19960712//en",
|
||||
"-//w3c//dtd html experimental 970421//en",
|
||||
"-//w3c//dtd w3 html//en",
|
||||
"-//w3o//dtd w3 html 3.0//en",
|
||||
"-//w3o//dtd w3 html 3.0//en//",
|
||||
"-//w3o//dtd w3 html strict 3.0//en//",
|
||||
"-//webtechs//dtd mozilla html 2.0//en",
|
||||
"-//webtechs//dtd mozilla html//en",
|
||||
"-/w3c/dtd html 4.0 transitional/en",
|
||||
"html"].include?(publicId) or
|
||||
(systemId == nil and
|
||||
["-//w3c//dtd html 4.01 frameset//EN",
|
||||
"-//w3c//dtd html 4.01 transitional//EN"].include?(publicId)) or
|
||||
(systemId == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd")
|
||||
#XXX quirks mode
|
||||
end
|
||||
end
|
||||
|
||||
@parser.phase = @parser.phases[:rootElement]
|
||||
end
|
||||
|
||||
def processSpaceCharacters(data)
|
||||
@tree.insertText(data, @tree.document)
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.parseError(_('Unexpected non-space characters. Expected DOCTYPE.'))
|
||||
@parser.phase = @parser.phases[:rootElement]
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
|
||||
def processStartTag(name, attributes)
|
||||
@parser.parseError(_("Unexpected start tag (#{name}). Expected DOCTYPE."))
|
||||
@parser.phase = @parser.phases[:rootElement]
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def processEndTag(name)
|
||||
@parser.parseError(_("Unexpected end tag (#{name}). Expected DOCTYPE."))
|
||||
@parser.phase = @parser.phases[:rootElement]
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
156
vendor/plugins/HTML5lib/lib/html5/html5parser/phase.rb
vendored
Normal file
156
vendor/plugins/HTML5lib/lib/html5/html5parser/phase.rb
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
module HTML5
|
||||
# Base class for helper objects that implement each phase of processing.
|
||||
#
|
||||
# Handler methods should be in the following order (they can be omitted):
|
||||
#
|
||||
# * EOF
|
||||
# * Comment
|
||||
# * Doctype
|
||||
# * SpaceCharacters
|
||||
# * Characters
|
||||
# * StartTag
|
||||
# - startTag* methods
|
||||
# * EndTag
|
||||
# - endTag* methods
|
||||
#
|
||||
class Phase
|
||||
|
||||
# The following example call:
|
||||
#
|
||||
# tag_handlers('startTag', 'html', %( base link meta ), %( li dt dd ) => 'ListItem')
|
||||
#
|
||||
# ...would return a hash equal to this:
|
||||
#
|
||||
# { 'html' => 'startTagHtml',
|
||||
# 'base' => 'startTagBaseLinkMeta',
|
||||
# 'link' => 'startTagBaseLinkMeta',
|
||||
# 'meta' => 'startTagBaseLinkMeta',
|
||||
# 'li' => 'startTagListItem',
|
||||
# 'dt' => 'startTagListItem',
|
||||
# 'dd' => 'startTagListItem' }
|
||||
#
|
||||
def self.tag_handlers(prefix, *tags)
|
||||
mapping = {}
|
||||
if tags.last.is_a?(Hash)
|
||||
tags.pop.each do |names, handler_method_suffix|
|
||||
handler_method = prefix + handler_method_suffix
|
||||
Array(names).each { |name| mapping[name] = handler_method }
|
||||
end
|
||||
end
|
||||
tags.each do |names|
|
||||
names = Array(names)
|
||||
handler_method = prefix + names.map { |name| name.capitalize }.join
|
||||
names.each { |name| mapping[name] = handler_method }
|
||||
end
|
||||
return mapping
|
||||
end
|
||||
|
||||
def self.start_tag_handlers
|
||||
@start_tag_handlers ||= Hash.new('startTagOther')
|
||||
end
|
||||
|
||||
# Declare what start tags this Phase handles. Can be called more than once.
|
||||
#
|
||||
# Example usage:
|
||||
#
|
||||
# handle_start 'html'
|
||||
# # html start tags will be handled by a method named 'startTagHtml'
|
||||
#
|
||||
# handle_start %( base link meta )
|
||||
# # base, link and meta start tags will be handled by a method named 'startTagBaseLinkMeta'
|
||||
#
|
||||
# handle_start %( li dt dd ) => 'ListItem'
|
||||
# # li, dt, and dd start tags will be handled by a method named 'startTagListItem'
|
||||
#
|
||||
def self.handle_start(*tags)
|
||||
start_tag_handlers.update tag_handlers('startTag', *tags)
|
||||
end
|
||||
|
||||
def self.end_tag_handlers
|
||||
@end_tag_handlers ||= Hash.new('endTagOther')
|
||||
end
|
||||
|
||||
# Declare what end tags this Phase handles. Behaves like handle_start.
|
||||
#
|
||||
def self.handle_end(*tags)
|
||||
end_tag_handlers.update tag_handlers('endTag', *tags)
|
||||
end
|
||||
|
||||
def initialize(parser, tree)
|
||||
@parser, @tree = parser, tree
|
||||
end
|
||||
|
||||
def processEOF
|
||||
@tree.generateImpliedEndTags
|
||||
|
||||
if @tree.openElements.length > 2
|
||||
@parser.parseError(_('Unexpected end of file. Missing closing tags.'))
|
||||
elsif @tree.openElements.length == 2 and @tree.openElements[1].name != 'body'
|
||||
# This happens for framesets or something?
|
||||
@parser.parseError(_("Unexpected end of file. Expected end tag (#{@tree.openElements[1].name}) first."))
|
||||
elsif @parser.innerHTML and @tree.openElements.length > 1
|
||||
# XXX This is not what the specification says. Not sure what to do here.
|
||||
@parser.parseError(_('XXX innerHTML EOF'))
|
||||
end
|
||||
# Betting ends.
|
||||
end
|
||||
|
||||
def processComment(data)
|
||||
# For most phases the following is correct. Where it's not it will be
|
||||
# overridden.
|
||||
@tree.insertComment(data, @tree.openElements[-1])
|
||||
end
|
||||
|
||||
def processDoctype(name, publicId, systemId, correct)
|
||||
@parser.parseError(_('Unexpected DOCTYPE. Ignored.'))
|
||||
end
|
||||
|
||||
def processSpaceCharacters(data)
|
||||
@tree.insertText(data)
|
||||
end
|
||||
|
||||
def processStartTag(name, attributes)
|
||||
send self.class.start_tag_handlers[name], name, attributes
|
||||
end
|
||||
|
||||
def startTagHtml(name, attributes)
|
||||
if @parser.firstStartTag == false and name == 'html'
|
||||
@parser.parseError(_('html needs to be the first start tag.'))
|
||||
end
|
||||
# XXX Need a check here to see if the first start tag token emitted is
|
||||
# this token... If it's not, invoke @parser.parseError.
|
||||
attributes.each do |attr, value|
|
||||
unless @tree.openElements[0].attributes.has_key?(attr)
|
||||
@tree.openElements[0].attributes[attr] = value
|
||||
end
|
||||
end
|
||||
@parser.firstStartTag = false
|
||||
end
|
||||
|
||||
def processEndTag(name)
|
||||
send self.class.end_tag_handlers[name], name
|
||||
end
|
||||
|
||||
def _(string)
|
||||
string
|
||||
end
|
||||
|
||||
def assert(value)
|
||||
throw AssertionError.new unless value
|
||||
end
|
||||
|
||||
def in_scope?(*args)
|
||||
@tree.elementInScope(*args)
|
||||
end
|
||||
|
||||
def remove_open_elements_until(name=nil)
|
||||
finished = false
|
||||
until finished
|
||||
element = @tree.openElements.pop
|
||||
finished = name.nil?? yield(element) : element.name == name
|
||||
end
|
||||
return element
|
||||
end
|
||||
|
||||
end
|
||||
end
|
43
vendor/plugins/HTML5lib/lib/html5/html5parser/root_element_phase.rb
vendored
Normal file
43
vendor/plugins/HTML5lib/lib/html5/html5parser/root_element_phase.rb
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class RootElementPhase < Phase
|
||||
|
||||
def processEOF
|
||||
insertHtmlElement
|
||||
@parser.phase.processEOF
|
||||
end
|
||||
|
||||
def processComment(data)
|
||||
@tree.insertComment(data, @tree.document)
|
||||
end
|
||||
|
||||
def processSpaceCharacters(data)
|
||||
@tree.insertText(data, @tree.document)
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
insertHtmlElement
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
|
||||
def processStartTag(name, attributes)
|
||||
@parser.firstStartTag = true if name == 'html'
|
||||
insertHtmlElement
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def processEndTag(name)
|
||||
insertHtmlElement
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
def insertHtmlElement
|
||||
element = @tree.createElement('html', {})
|
||||
@tree.openElements.push(element)
|
||||
@tree.document.appendChild(element)
|
||||
@parser.phase = @parser.phases[:beforeHead]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
36
vendor/plugins/HTML5lib/lib/html5/html5parser/trailing_end_phase.rb
vendored
Normal file
36
vendor/plugins/HTML5lib/lib/html5/html5parser/trailing_end_phase.rb
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
require 'html5/html5parser/phase'
|
||||
|
||||
module HTML5
|
||||
class TrailingEndPhase < Phase
|
||||
|
||||
def processEOF
|
||||
end
|
||||
|
||||
def processComment(data)
|
||||
@tree.insertComment(data, @tree.document)
|
||||
end
|
||||
|
||||
def processSpaceCharacters(data)
|
||||
@parser.lastPhase.processSpaceCharacters(data)
|
||||
end
|
||||
|
||||
def processCharacters(data)
|
||||
@parser.parseError(_('Unexpected non-space characters. Expected end of file.'))
|
||||
@parser.phase = @parser.lastPhase
|
||||
@parser.phase.processCharacters(data)
|
||||
end
|
||||
|
||||
def processStartTag(name, attributes)
|
||||
@parser.parseError(_('Unexpected start tag (#{name}). Expected end of file.'))
|
||||
@parser.phase = @parser.lastPhase
|
||||
@parser.phase.processStartTag(name, attributes)
|
||||
end
|
||||
|
||||
def processEndTag(name)
|
||||
@parser.parseError(_('Unexpected end tag (#{name}). Expected end of file.'))
|
||||
@parser.phase = @parser.lastPhase
|
||||
@parser.phase.processEndTag(name)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue