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.
@@ -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