code_terminator 0.5.8 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exercises/html/check_divs_different_attribute_exist.html +13 -0
- data/exercises/html/check_divs_different_attributes_exist_error.html +13 -0
- data/exercises/issue0.html +1 -0
- data/exercises/issue24.html +14 -0
- data/exercises/issue25.html +13 -0
- data/exercises/web_development/lesson1_1.html +1 -0
- data/exercises/web_development/lesson1_2.html +8 -0
- data/exercises/web_development/lesson1_3.html +12 -0
- data/exercises/web_development/lesson1_4.html +9 -0
- data/exercises/web_development/lesson1_5.html +12 -0
- data/exercises/web_development/lesson1_6.html +11 -0
- data/exercises/web_development/lesson1_7.html +13 -0
- data/exercises/web_development/lesson1_challenge.html +26 -0
- data/lib/code_terminator/css.rb +3 -23
- data/lib/code_terminator/html.rb +158 -402
- data/lib/code_terminator/html_deprecated.rb +742 -0
- data/lib/code_terminator/version.rb +1 -1
- metadata +16 -7
- data/exercises/css/lesson0.css +0 -5
- data/exercises/css/lesson0_w.css +0 -5
- data/exercises/css/lesson1_1.css +0 -1
- data/exercises/css/lesson1_2.css +0 -5
- data/exercises/css/lesson1_5.css +0 -16
@@ -0,0 +1,742 @@
|
|
1
|
+
require 'active_support/core_ext/string/filters'
|
2
|
+
|
3
|
+
class CodeTerminator::Html
|
4
|
+
|
5
|
+
def initialize(args = {})
|
6
|
+
@code = args[:code]
|
7
|
+
@source = args[:source]
|
8
|
+
@tags = Array.new
|
9
|
+
@elements = Array.new
|
10
|
+
|
11
|
+
args[:source_type] ||= "file"
|
12
|
+
@source_type = args[:source_type]
|
13
|
+
end
|
14
|
+
|
15
|
+
# Create a Html file with the code of the editor. Return a boolean that indicate if the file was created or not.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
# >> CodeTerminator::Html.new_file("hola_mundo.html", "<h1>Hola Mundo!</h1>")
|
19
|
+
# => true
|
20
|
+
#
|
21
|
+
# Arguments:
|
22
|
+
# source: (String)
|
23
|
+
# code: (String)
|
24
|
+
|
25
|
+
def new_file(source,code)
|
26
|
+
fileHtml = File.new(source, "w+")
|
27
|
+
result = true
|
28
|
+
begin
|
29
|
+
fileHtml.puts code
|
30
|
+
rescue
|
31
|
+
result = false
|
32
|
+
ensure
|
33
|
+
fileHtml.close unless fileHtml.nil?
|
34
|
+
end
|
35
|
+
#return true if file was succesfully created
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# Get html elements of a html file. Return a list of Nokogiri XML objects.
|
41
|
+
#
|
42
|
+
# Example:
|
43
|
+
# >> CodeTerminator::Html.get_elements("hola_mundo.html")
|
44
|
+
# => [#<Nokogiri::XML::Element:0x3fe3391547d8 name="h1" children=[#<Nokogiri::XML::Text:0x3fe33915474c "Hola Mundo!">]>, #<Nokogiri::XML::Text:0x3fe33915474c "Hola Mundo!">]
|
45
|
+
#
|
46
|
+
# Arguments:
|
47
|
+
# source: (String)
|
48
|
+
|
49
|
+
def get_elements(source)
|
50
|
+
@elements = Array.new
|
51
|
+
#How to read if is an url
|
52
|
+
if @source_type == "url"
|
53
|
+
reader = Nokogiri::HTML(open(source).read)
|
54
|
+
else
|
55
|
+
reader = Nokogiri::HTML(File.open(source))
|
56
|
+
end
|
57
|
+
#remove empty spaces from reader
|
58
|
+
reader = remove_empty_text(reader)
|
59
|
+
node = Hash.new
|
60
|
+
node[:parent] = ""
|
61
|
+
node[:tag] = "html"
|
62
|
+
@elements << node
|
63
|
+
|
64
|
+
#search elements from body section
|
65
|
+
if reader.at('body')
|
66
|
+
node = Hash.new
|
67
|
+
node[:parent] = "html"
|
68
|
+
node[:tag] = "body"
|
69
|
+
@elements << node
|
70
|
+
|
71
|
+
reader.at('body').attribute_nodes.each do |element_attribute|
|
72
|
+
node = Hash.new
|
73
|
+
node[:parent] = "html"
|
74
|
+
node[:tag] = "body"
|
75
|
+
node[:attribute] = element_attribute.name if element_attribute.name
|
76
|
+
node[:value] = element_attribute.value if element_attribute.value
|
77
|
+
node[:pointer] = element_attribute.pointer_id
|
78
|
+
@elements << node
|
79
|
+
end
|
80
|
+
end
|
81
|
+
#end search
|
82
|
+
|
83
|
+
#search elements from head section
|
84
|
+
if reader.at('head')
|
85
|
+
node = Hash.new
|
86
|
+
node[:parent] = "html"
|
87
|
+
node[:tag] = "head"
|
88
|
+
@elements << node
|
89
|
+
reader.at('head').children.each do |child|
|
90
|
+
if child.attribute_nodes.empty?
|
91
|
+
node = Hash.new
|
92
|
+
node[:parent] = "head"
|
93
|
+
node[:tag] = child.name
|
94
|
+
node[:content] = child.text if child.text or child.comment?
|
95
|
+
node[:pointer] = child.pointer_id
|
96
|
+
node[:parent_pointer] = child.parent.pointer_id
|
97
|
+
|
98
|
+
@elements << node
|
99
|
+
else
|
100
|
+
child.attribute_nodes.each do |element_attribute|
|
101
|
+
node = Hash.new
|
102
|
+
node[:parent] = "head"
|
103
|
+
if child.name == "#cdata-section"
|
104
|
+
node[:tag] = "text"
|
105
|
+
else
|
106
|
+
node[:tag] = child.name
|
107
|
+
end
|
108
|
+
# node[:tag] = ( ? "text", child.name)
|
109
|
+
node[:content] = child.text if !child.text.nil?
|
110
|
+
node[:attribute] = element_attribute.name if element_attribute.name
|
111
|
+
node[:value] = element_attribute.value if element_attribute.value
|
112
|
+
node[:pointer] = element_attribute.pointer_id
|
113
|
+
node[:parent_pointer] = child.pointer_id
|
114
|
+
@elements << node
|
115
|
+
end
|
116
|
+
end
|
117
|
+
add_children(child) if child.children.any?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
#end search elements
|
121
|
+
|
122
|
+
#search elements inside body (children)
|
123
|
+
if reader.at('body')
|
124
|
+
reader.at('body').children.each do |child|
|
125
|
+
if child.attribute_nodes.empty?
|
126
|
+
node = Hash.new
|
127
|
+
node[:parent] = "body"
|
128
|
+
node[:tag] = child.name
|
129
|
+
node[:content] = child.text if child.text? or child.comment?
|
130
|
+
node[:pointer] = child.pointer_id
|
131
|
+
node[:parent_pointer] = child.parent.pointer_id
|
132
|
+
@elements << node
|
133
|
+
else
|
134
|
+
node = Hash.new
|
135
|
+
node[:parent] = "body"
|
136
|
+
node[:tag] = child.name
|
137
|
+
node[:content] = child.text if child.text? or child.comment?
|
138
|
+
node[:pointer] = child.pointer_id
|
139
|
+
node[:parent_pointer] = child.parent.pointer_id
|
140
|
+
@elements << node
|
141
|
+
child.attribute_nodes.each do |element_attribute|
|
142
|
+
node = Hash.new
|
143
|
+
node[:parent] = "body"
|
144
|
+
node[:tag] = child.name
|
145
|
+
node[:attribute] = element_attribute.name if element_attribute.name
|
146
|
+
node[:value] = element_attribute.value if element_attribute.value
|
147
|
+
node[:pointer] = element_attribute.pointer_id
|
148
|
+
node[:parent_pointer] = child.pointer_id
|
149
|
+
@elements << node
|
150
|
+
end
|
151
|
+
end
|
152
|
+
add_children(child) if child.children.any?
|
153
|
+
end
|
154
|
+
end
|
155
|
+
#end search elements
|
156
|
+
|
157
|
+
@elements
|
158
|
+
end
|
159
|
+
|
160
|
+
# Validate if the syntax is correct. Return an array with Nokogiri errors.
|
161
|
+
#
|
162
|
+
# Example:
|
163
|
+
# >> CodeTerminator::Html.validate_syntax("<h1>Hola Mundo!</h1")
|
164
|
+
# => [#<Nokogiri::XML::SyntaxError: expected '>'>]
|
165
|
+
#
|
166
|
+
# Arguments:
|
167
|
+
# code: (String)
|
168
|
+
|
169
|
+
def validate_syntax(code)
|
170
|
+
errors = Array.new
|
171
|
+
|
172
|
+
begin
|
173
|
+
Nokogiri::XML(code) { |config| config.strict }
|
174
|
+
|
175
|
+
#validate if html follow w3, uncomment when check all the page
|
176
|
+
#"<!DOCTYPE html>
|
177
|
+
# <html>
|
178
|
+
# <head>
|
179
|
+
# <h1>asdasd</h1>
|
180
|
+
# <title>asdasd</title>
|
181
|
+
# </head>
|
182
|
+
# <body>
|
183
|
+
# <h1>hola</h1>
|
184
|
+
# </body>
|
185
|
+
# </html>"
|
186
|
+
# @validator = Html5Validator::Validator.new
|
187
|
+
# @validator.validate_text(@html)
|
188
|
+
|
189
|
+
rescue Nokogiri::XML::SyntaxError => e
|
190
|
+
#errors[0] = "Check if you close your tags"
|
191
|
+
errors[0] = e
|
192
|
+
end
|
193
|
+
|
194
|
+
errors
|
195
|
+
end
|
196
|
+
|
197
|
+
# Read a html file. Return the text of the file.
|
198
|
+
#
|
199
|
+
# Example:
|
200
|
+
# >> CodeTerminator::Html.read_file("hola_mundo.html")
|
201
|
+
# => "<h1>Hola Mundo!</h1>\n"
|
202
|
+
#
|
203
|
+
# Arguments:
|
204
|
+
# source: (String)
|
205
|
+
|
206
|
+
def read_file(source)
|
207
|
+
if @source_type == "url"
|
208
|
+
fileHtml = open(source).read
|
209
|
+
else
|
210
|
+
fileHtml = File.open(source, "r")
|
211
|
+
end
|
212
|
+
|
213
|
+
text = ""
|
214
|
+
begin
|
215
|
+
fileHtml.each_line do |line|
|
216
|
+
text << line
|
217
|
+
end
|
218
|
+
fileHtml.close
|
219
|
+
rescue
|
220
|
+
text = false
|
221
|
+
ensure
|
222
|
+
#fileHtml.close unless fileHtml.nil?
|
223
|
+
end
|
224
|
+
|
225
|
+
text
|
226
|
+
end
|
227
|
+
|
228
|
+
# Get the elements of the code in html format. Return a string with elements in html.
|
229
|
+
#
|
230
|
+
# Example:
|
231
|
+
# >> CodeTerminator::Html.print_elements("exercises/hola_mundo.html" )
|
232
|
+
# => "name = h1<br><hr>name = text<br>content = hola mundo<br><hr>"
|
233
|
+
#
|
234
|
+
# Arguments:
|
235
|
+
# elements: (Array)
|
236
|
+
|
237
|
+
def print_elements(elements)
|
238
|
+
text = ""
|
239
|
+
elements.each do |child|
|
240
|
+
text << "parent = " + child[:parent] + "<br>" if child[:parent]
|
241
|
+
text << "tag = " + child[:tag] + "<br>" if child[:tag]
|
242
|
+
text << "attribute = " + child[:attribute] + "<br>" if child[:attribute]
|
243
|
+
text << "value = " + child[:value] + "<br>" if child[:value]
|
244
|
+
text << "content = " + child[:content] + "<br>" if child[:content]
|
245
|
+
text << "<hr>"
|
246
|
+
end
|
247
|
+
text
|
248
|
+
end
|
249
|
+
|
250
|
+
# Get the instructions to recreate the html code. Return an array with strings .
|
251
|
+
#
|
252
|
+
# Example:
|
253
|
+
# >> CodeTerminator::Html.get_instructions(file.get_elements("exercises/test.html"))
|
254
|
+
# => ["Add the tag h2 in body", "Add the tag text in h2 with content 'hola test' ", "Add the tag p in body"]
|
255
|
+
#
|
256
|
+
# Arguments:
|
257
|
+
# instructions: (Array)
|
258
|
+
|
259
|
+
def get_instructions(source)
|
260
|
+
elements = get_elements(source)
|
261
|
+
text = ""
|
262
|
+
instructions = Array.new
|
263
|
+
elements.each do |child|
|
264
|
+
if child[:tag]!="text"
|
265
|
+
text << "Add the tag " + child[:tag]
|
266
|
+
text << " in " + child[:parent] if !child[:parent].nil?
|
267
|
+
text << " with an attribute '" + child[:attribute] + "' " if !child[:attribute].nil?
|
268
|
+
text << " with value '" + child[:value] + "' " if !child[:value].nil?
|
269
|
+
elsif child[:tag] == "comment"
|
270
|
+
text << " In " + child[:tag]+ " add the text '" + child[:content] + "' " if !child[:content].nil?
|
271
|
+
else
|
272
|
+
text << " In " + child[:parent]+ " add the text '" + child[:content] + "' " if !child[:content].nil?
|
273
|
+
end
|
274
|
+
instructions.push(text)
|
275
|
+
text = ""
|
276
|
+
end
|
277
|
+
instructions
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
|
282
|
+
# Match if the code have the same elements than the exercise. Return an array with the mismatches.
|
283
|
+
#
|
284
|
+
# Example:
|
285
|
+
#
|
286
|
+
# hola_mundo.html
|
287
|
+
# => <h1>Hola Mundo!</h1>
|
288
|
+
#
|
289
|
+
# >> CodeTerminator::Html.match("hola_mundo.html","<h2>Hola Mundo!</h2>")
|
290
|
+
# => ["h1 not exist"]
|
291
|
+
#
|
292
|
+
# Arguments:
|
293
|
+
# source: (String)
|
294
|
+
# code: (String)
|
295
|
+
|
296
|
+
def match(source, code)
|
297
|
+
@html_errors = Array.new
|
298
|
+
html_errors = @html_errors
|
299
|
+
|
300
|
+
code = Nokogiri::HTML(code)
|
301
|
+
|
302
|
+
elements = get_elements(source)
|
303
|
+
|
304
|
+
|
305
|
+
exist_in_body = Array.new
|
306
|
+
exist_value = Array.new
|
307
|
+
|
308
|
+
error_elements = Array.new
|
309
|
+
|
310
|
+
elements_count = Array.new
|
311
|
+
|
312
|
+
error333 = nil
|
313
|
+
|
314
|
+
#lista de relaciones entre tags y elementos
|
315
|
+
css_code_checked = Array.new
|
316
|
+
|
317
|
+
|
318
|
+
elements.each do |e|
|
319
|
+
p "element " + e.to_s
|
320
|
+
p "select ---"
|
321
|
+
# p elements_count
|
322
|
+
|
323
|
+
if e[:attribute].nil?
|
324
|
+
#tag con el mismo parent pointer no se repite ni se cuenta
|
325
|
+
# p "element count"
|
326
|
+
# elements_count.select {|element| element[:parent_pointer].to_s == e[:parent_pointer].to_s && element[:tag].to_s == e[:tag]}
|
327
|
+
|
328
|
+
|
329
|
+
# if elements_count.select {|element| element[:parent_pointer].to_s == e[:parent_pointer].to_s && element[:tag].to_s == e[:tag]}.count < 1
|
330
|
+
the_element = Hash.new
|
331
|
+
the_element[:tag] = e[:tag]
|
332
|
+
the_element[:pointer] = e[:pointer]
|
333
|
+
the_element[:parent_pointer] = e[:parent_pointer]
|
334
|
+
the_element[:count] = 0
|
335
|
+
elements_count << the_element
|
336
|
+
# end
|
337
|
+
end
|
338
|
+
|
339
|
+
item = e[:tag]
|
340
|
+
|
341
|
+
if item == "text" or item == "comment"
|
342
|
+
# Check the text
|
343
|
+
if e[:content]
|
344
|
+
if code.css(e[:parent]).count < 2
|
345
|
+
if code.css(e[:parent]).class == Nokogiri::XML::NodeSet
|
346
|
+
#look for children elements with texts or comments
|
347
|
+
look_comment_or_text(code,e)
|
348
|
+
end
|
349
|
+
else
|
350
|
+
#check if parent tag of the user code has text apart from the children tags
|
351
|
+
look_parent_text(code,e)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
#end if content is null
|
355
|
+
else
|
356
|
+
#item class is different to text or comment
|
357
|
+
|
358
|
+
p "code_checked"
|
359
|
+
p css_code_checked
|
360
|
+
p "elements count"
|
361
|
+
p elements_count
|
362
|
+
p "elements"
|
363
|
+
p elements
|
364
|
+
p "code css"
|
365
|
+
p code.css(e[:tag])
|
366
|
+
|
367
|
+
code.css(e[:tag]).each do |tag|
|
368
|
+
p "tag " + tag.to_s
|
369
|
+
tag_element = nil
|
370
|
+
# e_check = css_code_checked.select {|element| element[:original_pointer].to_s == e[:pointer].to_s }
|
371
|
+
# p "echeck " + e_check.to_s
|
372
|
+
e_check2 = css_code_checked.select {|element| element[:pointer].to_s == tag.pointer_id.to_s }
|
373
|
+
|
374
|
+
#original_pointer es el pointer del elemento e[]
|
375
|
+
#busca si el original_pointer esta en la lista de relaciones
|
376
|
+
#busca si el pointer del tag esta en la lista de relaciones
|
377
|
+
#cuando un original pointer o un pointer esta en la lista de relaciones, ya no puede volver a ser ingresado en la lista
|
378
|
+
#si el original pointer ya esta en la lista de relaciones, ya no es necesario volver a checarlo
|
379
|
+
check_original_pointer = css_code_checked.select {|element| element[:original_pointer].to_s == e[:pointer].to_s }
|
380
|
+
|
381
|
+
check_add_pointer = css_code_checked.select {|element| element[:pointer].to_s == tag.pointer_id.to_s }
|
382
|
+
# p "check_add " + check_add_pointer.to_s
|
383
|
+
#look for same tags in code
|
384
|
+
# p "elements_count"
|
385
|
+
# p elements_count
|
386
|
+
|
387
|
+
if check_original_pointer.count == 0
|
388
|
+
# p "pasa"
|
389
|
+
# # if tag.attributes.nil?
|
390
|
+
# # p "CON ATRIBUTOS"
|
391
|
+
# # else
|
392
|
+
# # p elements_count.to_s
|
393
|
+
# p "element " +e[:tag].to_s
|
394
|
+
# p "e pointer "+e[:pointer].to_s
|
395
|
+
# p "e parent pointer "+e[:parent_pointer].to_s
|
396
|
+
|
397
|
+
# end
|
398
|
+
# if check_add_pointer.count < 1
|
399
|
+
element_checked = Hash.new
|
400
|
+
element_checked[:pointer] = tag.pointer_id
|
401
|
+
element_checked[:tag] = e[:tag]
|
402
|
+
element_checked[:original_pointer] = e[:pointer]
|
403
|
+
element_checked[:original_parent_pointer] = e[:parent_pointer]
|
404
|
+
css_code_checked << element_checked
|
405
|
+
end
|
406
|
+
# the_element = elements_count.select {|element| element[:tag].to_s == e[:tag].to_s && element[:parent_pointer].to_s == e[:parent_pointer].to_s}.first
|
407
|
+
# the_element = elements_count.select {|element| element[:tag].to_s == e[:tag].to_s && element[:pointer].to_s == e[:parent_pointer].to_s}.first
|
408
|
+
p "the element"
|
409
|
+
if e[:tag]!="head" && e[:tag]!="html" && e[:tag]!="body"
|
410
|
+
the_element = elements_count.select {|element| element[:tag].to_s == e[:tag].to_s && element[:pointer].to_s == e[:pointer].to_s}.first
|
411
|
+
the_element[:count] += 1 if the_element
|
412
|
+
else
|
413
|
+
the_element = elements_count.select {|element| element[:tag].to_s == e[:tag].to_s}.first
|
414
|
+
the_element[:count] += 1 if the_element
|
415
|
+
end
|
416
|
+
# p "the element " + the_element.to_s
|
417
|
+
|
418
|
+
# end
|
419
|
+
# end
|
420
|
+
# end
|
421
|
+
# p "checked = " + elements_count.to_s
|
422
|
+
|
423
|
+
if code.css(e[:tag]).length > 0
|
424
|
+
|
425
|
+
#tag es el elemento reccorrido en el codigo
|
426
|
+
#e es el elemento original
|
427
|
+
#elementscount son los elementos que existen en codigo y original
|
428
|
+
|
429
|
+
# if tag_element
|
430
|
+
if e[:attribute]
|
431
|
+
|
432
|
+
# p "e --- " + e[:tag].to_s
|
433
|
+
# p "e pt--- " + e[:pointer].to_s
|
434
|
+
# p "e parent pt--- " + e[:parent_pointer].to_s
|
435
|
+
# p "e attribute --- " + e[:attribute].to_s
|
436
|
+
|
437
|
+
|
438
|
+
# if tag.attribute(e[:attribute])
|
439
|
+
# p "elements count = " + css_code_checked.to_s
|
440
|
+
tag_element = css_code_checked.select {|element| element[:pointer].to_s == tag.pointer_id.to_s && element[:original_pointer] == e[:pointer] }.first
|
441
|
+
# p "tag --" + tag.name.to_s
|
442
|
+
# p "tag --" + tag.to_s
|
443
|
+
# p "tag parent -- " + tag.parent.name.to_s
|
444
|
+
# p "tag pointer -- " + tag.pointer_id.to_s
|
445
|
+
# p "tag parent pointer -- " + tag.parent.pointer_id.to_s
|
446
|
+
# p "tag attribute -- " + tag.attribute(e[:attribute]).to_s
|
447
|
+
# p "parent_element --- " + tag_element.to_s
|
448
|
+
# else
|
449
|
+
# end
|
450
|
+
|
451
|
+
# Check the tag's attributes
|
452
|
+
if tag.attribute(e[:attribute]).nil?
|
453
|
+
if tag_element
|
454
|
+
# p "attribute element " + e[:attribute].to_s
|
455
|
+
# p "attribute tag " + tag.attribute(e[:attribute]).name.to_s
|
456
|
+
# if e[:attribute] != tag.attribute(e[:attribute]).name
|
457
|
+
html_errors << new_error(element: e, type: 334, description: "`<#{e[:tag]}>` should have an attribute named #{e[:attribute]}")
|
458
|
+
# end
|
459
|
+
end
|
460
|
+
else
|
461
|
+
if tag.attribute(e[:attribute]).value != e[:value]
|
462
|
+
exist_in_body << false
|
463
|
+
# p "value " + e[:value]
|
464
|
+
tag_attribute = tag.attribute(e[:attribute]).name
|
465
|
+
tag_attribute_value = tag.attribute(e[:attribute]).value
|
466
|
+
# p "type " + e[:tag] + " with attribute " + e[:attribute] + " value " + e[:value]
|
467
|
+
# Check if the img have attribute src and value is null, the user can write whatever image he wants
|
468
|
+
# p exist_value
|
469
|
+
if !(e[:tag] == "img" && (e[:attribute] == tag_attribute) && e[:value] == "")
|
470
|
+
if (!exist_value.include? tag_attribute_value and !exist_value.include? e[:value])
|
471
|
+
exist_in_body << false
|
472
|
+
error333 = new_error(element: e, type: 333, description: "Make sure that the attribute #{e[:attribute]} in `<#{e[:tag]}>` has the value #{e[:value]}")
|
473
|
+
end
|
474
|
+
# html_errors << error333 if error333
|
475
|
+
else
|
476
|
+
|
477
|
+
end
|
478
|
+
else
|
479
|
+
# p "add code_checked"
|
480
|
+
exist_value << e[:value]
|
481
|
+
# css_code_checked << element_checked
|
482
|
+
exist_in_body << true
|
483
|
+
end
|
484
|
+
end
|
485
|
+
# end
|
486
|
+
|
487
|
+
|
488
|
+
# p "respond" + tag.parent.to_s
|
489
|
+
# Check that tags exist within parent tags
|
490
|
+
if tag.first.respond_to? :parent
|
491
|
+
|
492
|
+
# p "check if exists in parent tags"
|
493
|
+
|
494
|
+
# e_check4 = css_code_checked.select {|element| element[:pointer].to_s == e[:pointer].to_s }
|
495
|
+
# e_check5 = css_code_checked.select {|element| element[:target_parent_pointer].to_s == e[:parent_pointer].to_s }
|
496
|
+
|
497
|
+
if (tag.count < 2 && tag.first)
|
498
|
+
if tag.first.parent.name != e[:parent]
|
499
|
+
html_errors << new_error(element: e, type: 440, description: "Remember to add the `<#{e[:tag]}>` tag inside `<#{e[:parent]}>`")
|
500
|
+
end
|
501
|
+
else
|
502
|
+
exist_in_parent = false
|
503
|
+
tag.each do |code_css|
|
504
|
+
exist_in_parent = true if code_css.parent.name == e[:parent]
|
505
|
+
end
|
506
|
+
html_errors << new_error(element: e, type: 440, description: "Remember to add the `<#{e[:tag]}>` tag inside `<#{e[:parent]}>`") if !exist_in_parent
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
end
|
511
|
+
|
512
|
+
end
|
513
|
+
|
514
|
+
end
|
515
|
+
|
516
|
+
# end #end tag
|
517
|
+
|
518
|
+
if exist_in_body && !exist_in_body.include?(true) && error333
|
519
|
+
html_errors << error333
|
520
|
+
end
|
521
|
+
|
522
|
+
# if exist_in_body && !exist_in_body.include?(true) && error333
|
523
|
+
# html_errors << error333
|
524
|
+
# end
|
525
|
+
|
526
|
+
exist_in_body = []
|
527
|
+
error333 = nil
|
528
|
+
# exist_value = []
|
529
|
+
|
530
|
+
end
|
531
|
+
|
532
|
+
end
|
533
|
+
|
534
|
+
# p "elements_count = " + elements_count.group_by{|h| h[:parent_pointer]}.to_s
|
535
|
+
|
536
|
+
# p "elements_count2 = "
|
537
|
+
grouped_elements = elements_count.select {|element| element[:count] > 0}.group_by { |s| [s[:parent_pointer], s[:tag]] }
|
538
|
+
|
539
|
+
grouped_elements.each do |x|
|
540
|
+
#filtrar por parent
|
541
|
+
#tag_count = code.css(x[:tag]).length
|
542
|
+
tag_count = elements.select {|element| element[:parent_pointer].to_s == x[0][0].to_s && element[:tag].to_s == x[0][1]}
|
543
|
+
# p "group="+tag_count.group_by{|h| h[:parent_pointer]}.values.to_s
|
544
|
+
# p result=Hash[tag_count.group_by{|x|x}.map{|k,v| [k,v.size]}]
|
545
|
+
p "tag" + x.to_s
|
546
|
+
p "tag count " + tag_count.count.to_s
|
547
|
+
p "grouped" + x.to_s
|
548
|
+
p "grouped count " + x[1].first[:count].to_s
|
549
|
+
(p "div count " + x[1][0].count.to_s) if x[0][1]=="div"
|
550
|
+
|
551
|
+
# p tag_count = elements.select {|element| element[:pointer].to_s == x[:pointer].to_s && element[:tag].to_s == x[:tag]}.count
|
552
|
+
# p x[:tag]!="body"
|
553
|
+
if tag_count.count >= 1 && !(x[0][1]=="text" || x[0][1]=="comment")
|
554
|
+
# if tag_count >= 1 && !(x[:tag]!="div")
|
555
|
+
if x[0][1]=="div"
|
556
|
+
if x[1][0].count.to_i < tag_count.count
|
557
|
+
html_errors << new_error(element: x[0][1], type: 404, description: "Remember to add the `<#{x[0][1]}>` tag")
|
558
|
+
end
|
559
|
+
else
|
560
|
+
if x[1].first[:count] < tag_count.count
|
561
|
+
html_errors << new_error(element: x[0][1], type: 404, description: "Remember to add the `<#{x[0][1]}>` tag")
|
562
|
+
end
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
# grouped_elements_null = elements_count.select {|element| element[:count] == 0}.group_by { |s| [s[:parent_pointer], s[:tag]] }
|
568
|
+
#
|
569
|
+
# grouped_elements_null.each do |nulls|
|
570
|
+
# if !(nulls[0][1]=="body" || nulls[0][1]=="head" || nulls[0][1]=="text" || nulls[0][1]=="comment")
|
571
|
+
# # if tag_count >= 1 && !(x[:tag]!="div")
|
572
|
+
# # if x[1].count < tag_count.count
|
573
|
+
# html_errors << new_error(element: nulls[0][1], type: 404, description: "Remember to add the `<#{nulls[0][1]}>` tag")
|
574
|
+
# # end
|
575
|
+
# end
|
576
|
+
# end
|
577
|
+
p elements_count
|
578
|
+
html_errors
|
579
|
+
|
580
|
+
end
|
581
|
+
|
582
|
+
private
|
583
|
+
|
584
|
+
def add_children(parent)
|
585
|
+
parent.children.each do |child|
|
586
|
+
if child.attribute_nodes.empty?
|
587
|
+
node = Hash.new
|
588
|
+
node[:parent] = parent.name
|
589
|
+
# node[:tag] = child.name
|
590
|
+
if child.name == "#cdata-section"
|
591
|
+
node[:tag] = "text"
|
592
|
+
else
|
593
|
+
node[:tag] = child.name
|
594
|
+
end
|
595
|
+
node[:content] = child.text if !child.text.nil? and child.class!=Nokogiri::XML::Element
|
596
|
+
node[:pointer] = child.pointer_id
|
597
|
+
node[:parent_pointer] = child.parent.pointer_id
|
598
|
+
@elements << node
|
599
|
+
else
|
600
|
+
child.attribute_nodes.each do |element_attribute|
|
601
|
+
node = Hash.new
|
602
|
+
node[:parent] = parent.name
|
603
|
+
# node[:tag] = child.namecode
|
604
|
+
if element_attribute.name == "#cdata-section"
|
605
|
+
node[:tag] = "text"
|
606
|
+
elsif element_attribute.name == "href"
|
607
|
+
node[:tag] = child.name
|
608
|
+
else
|
609
|
+
node[:tag] = element_attribute.name
|
610
|
+
end
|
611
|
+
node[:attribute] = element_attribute.name if !element_attribute.name.nil?
|
612
|
+
node[:value] = element_attribute.value if !element_attribute.value.nil?
|
613
|
+
node[:pointer] = element_attribute.pointer_id
|
614
|
+
node[:parent_pointer] = child.pointer_id
|
615
|
+
@elements << node
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
add_children(child) if child.children.any?
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
def remove_empty_text (reader)
|
624
|
+
if reader.at('head')
|
625
|
+
reader.at('head').children.each do |child|
|
626
|
+
if child.text
|
627
|
+
child.remove if child.content.to_s.squish.empty? && child.class == Nokogiri::XML::Text
|
628
|
+
end
|
629
|
+
check_children(child) if child.children.any?
|
630
|
+
end
|
631
|
+
end
|
632
|
+
if reader.at('body')
|
633
|
+
reader.at('body').children.each do |child|
|
634
|
+
if child.text
|
635
|
+
child.remove if child.content.to_s.squish.empty? && child.class == Nokogiri::XML::Text
|
636
|
+
end
|
637
|
+
check_children(child) if child.children.any?
|
638
|
+
end
|
639
|
+
end
|
640
|
+
reader
|
641
|
+
end
|
642
|
+
|
643
|
+
def check_children(parent)
|
644
|
+
parent.children.each do |child|
|
645
|
+
if child.text
|
646
|
+
child.remove if child.content.to_s.squish.empty? && child.class == Nokogiri::XML::Text
|
647
|
+
end
|
648
|
+
check_children(child) if child.children.any?
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
652
|
+
def new_error(args = {})
|
653
|
+
element = args[:element]
|
654
|
+
type = args[:type]
|
655
|
+
description = args[:description]
|
656
|
+
node = Hash.new
|
657
|
+
node[:element] = element
|
658
|
+
node[:type] = type
|
659
|
+
node[:description] = description
|
660
|
+
node
|
661
|
+
end
|
662
|
+
|
663
|
+
|
664
|
+
#methods of match
|
665
|
+
def look_comment_or_text(code,e)
|
666
|
+
error330 = nil
|
667
|
+
text_found = false
|
668
|
+
@comment_found = false if e[:tag] == "comment"
|
669
|
+
|
670
|
+
#look for comments or text in code
|
671
|
+
#code, e
|
672
|
+
if code.css(e[:parent]).children.any?
|
673
|
+
#look for comments and text in children of body
|
674
|
+
# code, e
|
675
|
+
#save
|
676
|
+
#return
|
677
|
+
code.css(e[:parent]).children.each do |node_child|
|
678
|
+
#if class of the node is a comment, look in the code
|
679
|
+
# @e, node_child
|
680
|
+
#save error330
|
681
|
+
#return true (flag)
|
682
|
+
if node_child.class == Nokogiri::XML::Comment
|
683
|
+
error330 = new_error(element: e, type: 330, description: "The text inside the comment should be #{e[:content]}") if e[:content].strip != "" && node_child.text.strip! != e[:content].strip!
|
684
|
+
@comment_found = true
|
685
|
+
end
|
686
|
+
|
687
|
+
#if class of node is text and element is not a comment
|
688
|
+
#@e, node_child
|
689
|
+
#save a error330, text_found
|
690
|
+
#return true (flag)
|
691
|
+
if node_child.class == Nokogiri::XML::Text && e[:tag] != "comment"
|
692
|
+
node_child.text.strip != e[:content].strip ? error330 = new_error(element: e, type: 330, description: "The text inside `<#{e[:parent]}>` should be #{e[:content]}") : text_found = true
|
693
|
+
end
|
694
|
+
end #each
|
695
|
+
|
696
|
+
else
|
697
|
+
#validate if comment exist and has the expected content in body
|
698
|
+
#code, @e
|
699
|
+
#save @comment_found, text_found
|
700
|
+
if code.css(e[:parent]).text.strip != e[:content].strip
|
701
|
+
if e[:tag] == "comment"
|
702
|
+
error330 = new_error(element: e, type: 330, description: "The text inside the comment should be #{e[:content]}")
|
703
|
+
@comment_found = true
|
704
|
+
else
|
705
|
+
error330 = new_error(element: e, type: 330, description: "The text inside `<#{e[:parent]}>` should be #{e[:content]}")
|
706
|
+
end
|
707
|
+
else
|
708
|
+
text_found = true
|
709
|
+
end
|
710
|
+
end #end if parent has children
|
711
|
+
|
712
|
+
#throw errors of comment or text
|
713
|
+
#if comment not found, throw error
|
714
|
+
if (defined? @comment_found) && !@comment_found
|
715
|
+
@html_errors << new_error(element: e, type: 404, description: "Remember to add the comment tag")
|
716
|
+
remove_instance_variable(:@comment_found) if !@comment_found
|
717
|
+
end
|
718
|
+
|
719
|
+
if !text_found && error330
|
720
|
+
@html_errors << error330
|
721
|
+
error330 = nil
|
722
|
+
end
|
723
|
+
#end throw errors
|
724
|
+
end #end look_comment_or_text
|
725
|
+
|
726
|
+
def look_parent_text(code,e)
|
727
|
+
exist = false
|
728
|
+
#look for text in parent, if found check flag true
|
729
|
+
code.css(e[:parent]).each do |code_css|
|
730
|
+
if code_css.text == e[:content]
|
731
|
+
exist = true
|
732
|
+
end
|
733
|
+
end
|
734
|
+
if !exist
|
735
|
+
@html_errors << new_error(element: e, type: 330, description: "The text inside `<#{e[:parent]}>` should be #{e[:content]}")
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
739
|
+
|
740
|
+
#end
|
741
|
+
|
742
|
+
end
|