Class: Gammo::Parser::InBody

Inherits:
InsertionMode show all
Defined in:
lib/gammo/parser/insertion_mode/in_body.rb

Overview

Section 12.2.6.4.6.

Instance Attribute Summary

Attributes inherited from InsertionMode

#parser

Instance Method Summary collapse

Methods inherited from InsertionMode

#initialize, #process

Constructor Details

This class inherits a constructor from Gammo::Parser::InsertionMode

Instance Method Details

#character_token(token) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/gammo/parser/insertion_mode/in_body.rb', line 5

def character_token(token)
  data = token.data
  node = parser.open_elements.last
  case node.tag
  when Tags::Pre, Tags::Listing
    unless node.first_child
      # ignore a newline at the start of the <pre> block.
      data = data.slice(1..-1) if !data.empty? && data[0] == ?\r
      data = data.slice(1..-1) if !data.empty? && data[0] == ?\n
    end
  end
  data = data.gsub("\x00", '')
  halt true if data.empty?
  parser.reconstruct_active_formatting_elements
  parser.frameset_ok = false if parser.frameset_ok && !data.lstrip.empty?
  parser.add_text(data)
end

#comment_token(token) ⇒ Object



287
288
289
# File 'lib/gammo/parser/insertion_mode/in_body.rb', line 287

def comment_token(token)
  parser.add_child Node::Comment.new(data: token.data)
end

#default(_) ⇒ Object



309
310
311
# File 'lib/gammo/parser/insertion_mode/in_body.rb', line 309

def default(_)
  halt true
end

#end_tag_token(token) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/gammo/parser/insertion_mode/in_body.rb', line 228

def end_tag_token(token)
  case token.tag
  when Tags::Body
    parser.insertion_mode = AfterBody if parser.element_in_scope?(DEFAULT_SCOPE, Tags::Body)
  when Tags::Html
    halt true unless parser.element_in_scope?(DEFAULT_SCOPE, Tags::Body)
    parser.parse_implied_token(Tokenizer::EndTagToken, Tags::Body, Tags::Body.to_s)
    halt false
  when Tags::Address, Tags::Article, Tags::Aside, Tags::Blockquote,
    Tags::Button, Tags::Center, Tags::Dialog, Tags::Details, Tags::Dir,
    Tags::Div, Tags::Dl, Tags::Fieldset, Tags::Figcaption, Tags::Figure,
    Tags::Footer, Tags::Header, Tags::Hgroup, Tags::Listing, Tags::Main,
    Tags::Menu, Tags::Nav, Tags::Ol, Tags::Pre, Tags::Section,
    Tags::Summary, Tags::Ul
    parser.pop_until(DEFAULT_SCOPE, token.tag)
  when Tags::Form
    if parser.open_elements.any? { |oe| oe.tag == Tags::Template }
      index = parser.index_of_element_in_scope(DEFAULT_SCOPE, Tags::Form)
      # ignore the token.
      halt true if index == -1
      parser.generate_implied_end_tags
      # ignore the token.
      halt true if parser.open_elements[index].tag != Tags::Form
      parser.pop_until(DEFAULT_SCOPE, Tags::Form)
    else
      node = parser.form
      parser.form = nil
      index = parser.index_of_element_in_scope(DEFAULT_SCOPE, Tags::Form)
      # ignore the token.
      halt true if node == nil || index == -1 || parser.open_elements[index] != node
      parser.generate_implied_end_tags
      parser.open_elements.delete(node)
    end
  when Tags::P
    parser.parse_implied_token(Tokenizer::StartTagToken, Tags::P, Tags::P.to_s) unless parser.element_in_scope?(BUTTON_SCOPE, Tags::P)
    parser.pop_until(BUTTON_SCOPE, Tags::P)
  when Tags::Li
    parser.pop_until(LIST_ITEM_SCOPE, Tags::Li)
  when Tags::Dd, Tags::Dt
    parser.pop_until(DEFAULT_SCOPE, token.tag)
  when Tags::H1, Tags::H2, Tags::H3, Tags::H4, Tags::H5, Tags::H6
    parser.pop_until(DEFAULT_SCOPE, Tags::H1, Tags::H2, Tags::H3, Tags::H4, Tags::H5, Tags::H6)
  when Tags::A, Tags::B, Tags::Big, Tags::Code, Tags::Em, Tags::Font,
    Tags::I, Tags::Nobr, Tags::S, Tags::Small, Tags::Strike,
    Tags::Strong, Tags::Tt, Tags::U
    adoption_agency_for_end_tag_formatting(token.tag, token.data)
  when Tags::Applet, Tags::Marquee, Tags::Object
    parser.clear_active_formatting_elements if parser.pop_until(DEFAULT_SCOPE, token.tag)
  when Tags::Br
    # FIXME
    parser.token = Tokenizer::StartTagToken.new(token.data, tag: token.tag)
    halt false
  when Tags::Template
    halt InHead.new(parser).process
  else
    adoption_agency_for_end_tag_formatting(token.tag, token.data)
  end
end

#error_token(token) ⇒ Object



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/gammo/parser/insertion_mode/in_body.rb', line 291

def error_token(token)
  if parser.template_stack.length > 0
    parser.insertion_mode = InTemplate
    halt false
  else
    parser.open_elements.any? do |oe|
      case oe.tag
      when Tags::Dd, Tags::Dt, Tags::Li, Tags::Optgroup, Tags::Option, Tags::P,
        Tags::Rb, Tags::Rp, Tags::Rt, Tags::Rtc, Tags::Tbody, Tags::Td, Tags::Tfoot,
        Tags::Th, Tags::Thead, Tags::Tr, Tags::Body, Tags::Html
      else
        halt true
      end
    end
    halt true
  end
end

#start_tag_token(token) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/gammo/parser/insertion_mode/in_body.rb', line 23

def start_tag_token(token)
  case token.tag
  when Tags::Html
    halt true if parser.open_elements.any? { |oe| oe.tag == Tags::Template }
    copy_attributes(parser.open_elements[0], token)
  when Tags::Base, Tags::Basefont, Tags::Bgsound, Tags::Link, Tags::Meta,
    Tags::Noframes, Tags::Script, Tags::Style, Tags::Template, Tags::Title
    halt InHead.new(parser).process
  when Tags::Body
    halt true if parser.open_elements.any? { |oe| oe.tag == Tags::Template }
    if parser.open_elements.length >= 2
      body = parser.open_elements[1]
      if body.instance_of?(Node::Element) && body.tag == Tags::Body
        parser.frameset_ok = false
        copy_attributes(body, parser.token)
      end
    end
  when Tags::Frameset
    if !parser.frameset_ok || parser.open_elements.length < 2 || parser.open_elements[1].tag != Tags::Body
      # ignore the token
      halt true
    end
    body = parser.open_elements[1]
    body.parent.remove_child(body) if body.parent
    parser.open_elements = parser.open_elements.slice(0, 1)
    parser.add_element
    parser.insertion_mode = InFrameset
    halt true
  when Tags::Address, Tags::Article, Tags::Aside, Tags::Blockquote,
    Tags::Center, Tags::Dialog, Tags::Details, Tags::Dir, Tags::Div,
    Tags::Dl, Tags::Fieldset, Tags::Figcaption, Tags::Figure,
    Tags::Footer, Tags::Header, Tags::Hgroup, Tags::Main, Tags::Menu,
    Tags::Nav, Tags::Ol, Tags::P, Tags::Section, Tags::Summary, Tags::Ul
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    parser.add_element
  when Tags::H1, Tags::H2, Tags::H3, Tags::H4, Tags::H5, Tags::H6
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    node = parser.top
    case node.tag
    when Tags::H1, Tags::H2, Tags::H3, Tags::H4, Tags::H5, Tags::H6
      parser.open_elements.pop
    end
    parser.add_element
  when Tags::Pre, Tags::Listing
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    parser.add_element
    parser.frameset_ok = false
  when Tags::Form
    # ignore the token.
    halt true if parser.form && !parser.open_elements.any? { |oe| oe.tag == Tags::Template }
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    parser.add_element
    parser.form = parser.top unless parser.open_elements.any? { |oe| oe.tag == Tags::Template }
  when Tags::Li
    parser.frameset_ok = false
    parser.open_elements.reverse_each_with_index do |open_element, index|
      case open_element.tag
      when Tags::Li then parser.open_elements = parser.open_elements.slice(0, index)
      when Tags::Address, Tags::Div, Tags::P then next
      else
        next unless parser.special_element?(open_element)
      end
      break
    end
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    parser.add_element
  when Tags::Dd, Tags::Dt
    parser.frameset_ok = false
    parser.open_elements.reverse_each_with_index do |open_element, index|
      case open_element.tag
      when Tags::Dd, Tags::Dt then parser.open_elements = parser.open_elements.slice(0, index)
      when Tags::Address, Tags::Div, Tags::P then next
      else
        next unless parser.special_element?(open_element)
      end
      break
    end
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    parser.add_element
  when Tags::Plaintext
    parser.pop_until BUTTON_SCOPE, Tags::P
    parser.add_element
  when Tags::Button
    parser.pop_until DEFAULT_SCOPE, Tags::Button
    parser.reconstruct_active_formatting_elements
    parser.add_element
    parser.frameset_ok = false
  when Tags::A
    parser.active_formatting_elements.reverse_each do |afe|
      break if afe.is_a?(Node::ScopeMarker)
      next unless afe.instance_of?(Node::Element) && afe.tag == Tags::A
      adoption_agency_for_end_tag_formatting(Tags::A, "a")
      parser.open_elements.delete(afe)
      parser.active_formatting_elements.delete(afe)
      break
    end
    parser.reconstruct_active_formatting_elements
    parser.add_formatting_element
  when Tags::B, Tags::Big, Tags::Code, Tags::Em, Tags::Font, Tags::I,
    Tags::S, Tags::Small, Tags::Strike, Tags::Strong, Tags::Tt, Tags::U
    parser.reconstruct_active_formatting_elements
    parser.add_formatting_element
  when Tags::Nobr
    parser.reconstruct_active_formatting_elements
    if parser.element_in_scope?(DEFAULT_SCOPE, Tags::Nobr)
      adoption_agency_for_end_tag_formatting(Tags::Nobr, "nobr")
      parser.reconstruct_active_formatting_elements
    end
    parser.add_formatting_element
  when Tags::Applet, Tags::Marquee, Tags::Object
    parser.reconstruct_active_formatting_elements
    parser.add_element
    parser.active_formatting_elements << Node::DEFAULT_SCOPE_MARKER
    parser.frameset_ok = false
  when Tags::Table
    parser.pop_until(BUTTON_SCOPE, Tags::P) unless parser.quirks
    parser.add_element
    parser.frameset_ok = false
    parser.insertion_mode = InTable
    halt true
  when Tags::Area, Tags::Br, Tags::Embed, Tags::Img, Tags::Input, Tags::Keygen, Tags::Wbr
    parser.reconstruct_active_formatting_elements
    parser.add_element
    parser.open_elements.pop
    parser.acknowledge_self_closing_tag
    token.attributes.each do |attr|
      # skip setting frameset_ok = false
      halt true if attr.key == 'type' && attr.value.downcase == 'hidden'
    end if token.tag == Tags::Input
    parser.frameset_ok = false
  when Tags::Param, Tags::Source, Tags::Track
    parser.add_element
    parser.open_elements.pop
    parser.acknowledge_self_closing_tag
  when Tags::Hr
    parser.pop_until BUTTON_SCOPE, Tags::P
    parser.add_element
    parser.open_elements.pop
    parser.acknowledge_self_closing_tag
    parser.frameset_ok = false
  when Tags::Image
    token.tag = Tags::Img
    # todo: fixme <img>
    token.data = Tags::Img.to_s
    halt false
  when Tags::Textarea
    parser.add_element
    parser.set_original_insertion_mode
    parser.frameset_ok = false
    parser.insertion_mode = Text
  when Tags::Xmp
    parser.pop_until(BUTTON_SCOPE, Tags::P)
    parser.reconstruct_active_formatting_elements
    parser.frameset_ok = false
    parser.add_element
    parser.set_original_insertion_mode
    parser.insertion_mode = Text
  when Tags::Iframe
    parser.frameset_ok = false
    parser.parse_generic_raw_text_element
  when Tags::Noembed
    parser.parse_generic_raw_text_element
  when Tags::Noscript
    if parser.scripting?
      parser.parse_generic_raw_text_element
      halt true
    end
    parser.reconstruct_active_formatting_elements
    parser.add_element
    parser.tokenizer.next_is_not_raw_text!
  when Tags::Select
    parser.reconstruct_active_formatting_elements
    parser.add_element
    parser.frameset_ok = false
    parser.insertion_mode = InSelect
    halt true
  when Tags::Optgroup, Tags::Option
    parser.open_elements.pop if parser.top.tag == Tags::Option
    parser.reconstruct_active_formatting_elements
    parser.add_element
  when Tags::Rb, Tags::Rtc
    parser.generate_implied_end_tags if parser.element_in_scope?(DEFAULT_SCOPE, Tags::Ruby)
    parser.add_element
  when Tags::Rp, Tags::Rt
    parser.generate_implied_end_tags('rtc') if parser.element_in_scope?(DEFAULT_SCOPE, Tags::Ruby)
    parser.add_element
  when Tags::Math, Tags::Svg
    parser.reconstruct_active_formatting_elements
    parser.adjust_attribute_names(token.attributes, token.tag == Tags::Math ? Parser::MATH_ML_ATTRIBUTE_ADJUSTMENTS : Parser::SVG_ATTRIBUTE_ADJUSTMENTS)
    parser.adjust_foreign_attributes(token.attributes)
    parser.add_element
    parser.top.namespace = token.data
    if parser.has_self_closing_token
      parser.open_elements.pop
      parser.acknowledge_self_closing_tag
    end
    halt true
  when Tags::Caption, Tags::Col, Tags::Colgroup, Tags::Frame, Tags::Head, Tags::Tbody, Tags::Td, Tags::Tfoot, Tags::Th, Tags::Thead, Tags::Tr
    # ignore the token.
  else
    parser.reconstruct_active_formatting_elements
    parser.add_element
  end
end