code_terminator 0.5.8 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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