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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2e23d5114a50f4fcb74e546366e5bdf65655a305
4
- data.tar.gz: 8714cc7e061a6801689914d2ba9267460abbefce
3
+ metadata.gz: 542fe230e1beb215c850d8ba716a683a370484d1
4
+ data.tar.gz: b8d7b6ed665073ffb799ed0671a9e250c44ec447
5
5
  SHA512:
6
- metadata.gz: 400084dbc2cb543c3b6c1633fd145db9a370bc6c872ed6dfb08785ffffef4dbcf80ef360ac76eca50ed7154055a1948c41bdcd824044238a29dad74aa6ba3695
7
- data.tar.gz: 9f08fb9e06ddab835cea3c21ea71f3db4941eea24a64773773fe47855214ee47e9c73acde299b9d22bf4b220b18153f42c08dc18727bf24eaf2b498e61a0c89a
6
+ metadata.gz: 25d291f5d0676fdaeb941f5fca83841dca82abe79e7e44a256a4cff69c98367d03088fc50d093d97f7fe62b77188f0b717fb268022a8578f360258ee8562f253
7
+ data.tar.gz: 5621cedfe8f2a56eba87a5c68b42daa820cb6598db7b7cbf0b2812f36e4862318ed3caf1a2df2c73954cf758ac9b9d3a9d519000de137d6661b78e3d734fb534
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>My Favorite Book</title>
4
+ </head>
5
+ <body>
6
+ <div id='title'>
7
+ <h1></h1>
8
+ </div>
9
+ <div class='about'>
10
+ <p></p>
11
+ </div>
12
+ </body>
13
+ </html>
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>My Favorite Book</title>
4
+ </head>
5
+ <body>
6
+ <div id='t'>
7
+ <h1></h1>
8
+ </div>
9
+ <div class='a'>
10
+ <p></p>
11
+ </div>
12
+ </body>
13
+ </html>
@@ -0,0 +1 @@
1
+ <p></p>
@@ -0,0 +1,14 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+ <div id="logo">
6
+ <p>hola</p>
7
+ <img alt="">
8
+ </div>
9
+ <div id="catalog">
10
+ <img src="banana" alt="">
11
+ <img src="pear" alt="">
12
+ </div>
13
+ </body>
14
+ </html>
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+ <img src="">
6
+ <div class="col-md-12">
7
+ <img>
8
+ <img>
9
+ <h1>hola</h1>
10
+ </div>
11
+ <img>
12
+ </body>
13
+ </html>
@@ -0,0 +1 @@
1
+ <p></p>
@@ -0,0 +1,8 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ </head>
5
+ <body>
6
+ <p></p>
7
+ </body>
8
+ </html>
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+
5
+ </head>
6
+ <body>
7
+ <!--This paragraph is Han speaking-->
8
+ <p>I love to fly my spaceship. My best friend is big and furry. Sometimes I get myself into sticky situations.</p>
9
+ <!--This paragraph is Chewbacca speaking-->
10
+ <p>Han is my best friend and he is the only one that understands me when I talk.</p>
11
+ </body>
12
+ </html>
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html><html>
2
+ <head>
3
+ <title></title>
4
+ </head>
5
+ <body>
6
+ <h1></h1>
7
+ <p></p>
8
+ </body>
9
+ </html>
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>
5
+ </title>
6
+ </head>
7
+ <body>
8
+ <img src="">
9
+ <img src="">
10
+ <img src="">
11
+ </body>
12
+ </html>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title></title>
5
+ </head>
6
+ <body>
7
+ <ul>
8
+ <li></li>
9
+ </ul>
10
+ </body>
11
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title></title>
5
+ </head>
6
+ <body>
7
+ <a href=""></a>
8
+ <a href=""></a>
9
+ <a href=""></a>
10
+ <a href=""></a>
11
+ <a href=""></a>
12
+ </body>
13
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title></title>
5
+ </head>
6
+ <body>
7
+ <h1></h1>
8
+ <p></p>
9
+ <img src="">
10
+
11
+ <h1></h1>
12
+ <p></p>
13
+ <img src="">
14
+
15
+ <h1></h1>
16
+ <p></p>
17
+ <img src="">
18
+
19
+ <a href=""></a>
20
+ <a href=""></a>
21
+ <a href=""></a>
22
+ <a href=""></a>
23
+ <a href=""></a>
24
+
25
+ </body>
26
+ </html>
@@ -208,36 +208,16 @@ class CodeTerminator::Css
208
208
  parser.load_string!(code)
209
209
  elements.each do |e|
210
210
  item = e[:selector]
211
- if e[:property]
211
+ if !e[:property].nil?
212
212
  property = e[:property]
213
213
  parser_array = parser.find_by_selector(item)
214
214
  if parser_array.any?
215
- # p "array " + parser_array.to_s
216
215
  parser_property = parser_array[0].split(";")
217
- # p "array split" + parser_property.to_s
216
+ parser_property.each {|a| a.strip! if a.respond_to? :strip! }
218
217
 
219
- search_results = parser_property.select { |key| key.include?(property) }
220
- if search_results.empty?
221
- css_errors << new_error(element: e, type: 111, description: "Make sure the property _#{property}_ is in the selector **#{item}**")
222
- end
223
-
224
-
225
- # parser_property.each do |pp|
226
- # p "include " + pp.include?(property).to_s
227
- # if !pp.include?(property)
228
- # css_errors << new_error(element: e, type: 111, description: "Make sure the property _#{property}_ is in the selector **#{item}**")
229
- # end
230
- # end
231
-
232
-
233
- parser_property.each {|a| a.strip! if a.respond_to? :strip! }
234
-
235
-
236
- # p "value:" + e[:value]
237
218
  if e[:value]==""
238
219
  property = e[:property] + ": "
239
- # p "parser property: " + parser_property.to_s
240
- if parser_property.empty?
220
+ if parser_property.empty? { |s| s.include?(property) }
241
221
  css_errors << new_error(element: e, type: 111, description: "Make sure the property _#{property}_ is in the selector **#{item}**")
242
222
  end
243
223
  else
@@ -12,30 +12,6 @@ class CodeTerminator::Html
12
12
  @source_type = args[:source_type]
13
13
  end
14
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
15
 
40
16
  # Get html elements of a html file. Return a list of Nokogiri XML objects.
41
17
  #
@@ -56,16 +32,21 @@ class CodeTerminator::Html
56
32
  end
57
33
  #remove empty spaces from reader
58
34
  reader = remove_empty_text(reader)
59
- node = Hash.new
60
- node[:parent] = ""
61
- node[:tag] = "html"
62
- @elements << node
35
+ if reader.css('html').any?
36
+ node = Hash.new
37
+ node[:parent] = ""
38
+ node[:tag] = "html"
39
+ node[:pointer] = reader.css('html').first.pointer_id
40
+ @elements << node
41
+ end
63
42
 
64
43
  #search elements from body section
65
44
  if reader.at('body')
66
45
  node = Hash.new
67
46
  node[:parent] = "html"
68
47
  node[:tag] = "body"
48
+ node[:pointer] = reader.css('body').first.pointer_id
49
+ node[:parent_pointer] = reader.css('html').first.pointer_id
69
50
  @elements << node
70
51
 
71
52
  reader.at('body').attribute_nodes.each do |element_attribute|
@@ -75,6 +56,7 @@ class CodeTerminator::Html
75
56
  node[:attribute] = element_attribute.name if element_attribute.name
76
57
  node[:value] = element_attribute.value if element_attribute.value
77
58
  node[:pointer] = element_attribute.pointer_id
59
+ node[:parent_pointer] = reader.css('html').first.pointer_id
78
60
  @elements << node
79
61
  end
80
62
  end
@@ -85,7 +67,10 @@ class CodeTerminator::Html
85
67
  node = Hash.new
86
68
  node[:parent] = "html"
87
69
  node[:tag] = "head"
70
+ node[:pointer] = reader.css('head').first.pointer_id
71
+ node[:parent_pointer] = reader.css('html').first.pointer_id
88
72
  @elements << node
73
+
89
74
  reader.at('head').children.each do |child|
90
75
  if child.attribute_nodes.empty?
91
76
  node = Hash.new
@@ -94,7 +79,6 @@ class CodeTerminator::Html
94
79
  node[:content] = child.text if child.text or child.comment?
95
80
  node[:pointer] = child.pointer_id
96
81
  node[:parent_pointer] = child.parent.pointer_id
97
-
98
82
  @elements << node
99
83
  else
100
84
  child.attribute_nodes.each do |element_attribute|
@@ -105,8 +89,7 @@ class CodeTerminator::Html
105
89
  else
106
90
  node[:tag] = child.name
107
91
  end
108
- # node[:tag] = ( ? "text", child.name)
109
- node[:content] = child.text if !child.text.nil?
92
+ node[:content] = child.text if child.text
110
93
  node[:attribute] = element_attribute.name if element_attribute.name
111
94
  node[:value] = element_attribute.value if element_attribute.value
112
95
  node[:pointer] = element_attribute.pointer_id
@@ -131,6 +114,13 @@ class CodeTerminator::Html
131
114
  node[:parent_pointer] = child.parent.pointer_id
132
115
  @elements << node
133
116
  else
117
+ node = Hash.new
118
+ node[:parent] = "body"
119
+ node[:tag] = child.name
120
+ node[:content] = child.text if child.text? or child.comment?
121
+ node[:pointer] = child.pointer_id
122
+ node[:parent_pointer] = child.parent.pointer_id
123
+ @elements << node
134
124
  child.attribute_nodes.each do |element_attribute|
135
125
  node = Hash.new
136
126
  node[:parent] = "body"
@@ -146,130 +136,9 @@ class CodeTerminator::Html
146
136
  end
147
137
  end
148
138
  #end search elements
149
-
150
139
  @elements
151
140
  end
152
141
 
153
- # Validate if the syntax is correct. Return an array with Nokogiri errors.
154
- #
155
- # Example:
156
- # >> CodeTerminator::Html.validate_syntax("<h1>Hola Mundo!</h1")
157
- # => [#<Nokogiri::XML::SyntaxError: expected '>'>]
158
- #
159
- # Arguments:
160
- # code: (String)
161
-
162
- def validate_syntax(code)
163
- errors = Array.new
164
-
165
- begin
166
- Nokogiri::XML(code) { |config| config.strict }
167
-
168
- #validate if html follow w3, uncomment when check all the page
169
- #"<!DOCTYPE html>
170
- # <html>
171
- # <head>
172
- # <h1>asdasd</h1>
173
- # <title>asdasd</title>
174
- # </head>
175
- # <body>
176
- # <h1>hola</h1>
177
- # </body>
178
- # </html>"
179
- # @validator = Html5Validator::Validator.new
180
- # @validator.validate_text(@html)
181
-
182
- rescue Nokogiri::XML::SyntaxError => e
183
- #errors[0] = "Check if you close your tags"
184
- errors[0] = e
185
- end
186
-
187
- errors
188
- end
189
-
190
- # Read a html file. Return the text of the file.
191
- #
192
- # Example:
193
- # >> CodeTerminator::Html.read_file("hola_mundo.html")
194
- # => "<h1>Hola Mundo!</h1>\n"
195
- #
196
- # Arguments:
197
- # source: (String)
198
-
199
- def read_file(source)
200
- if @source_type == "url"
201
- fileHtml = open(source).read
202
- else
203
- fileHtml = File.open(source, "r")
204
- end
205
-
206
- text = ""
207
- begin
208
- fileHtml.each_line do |line|
209
- text << line
210
- end
211
- fileHtml.close
212
- rescue
213
- text = false
214
- ensure
215
- #fileHtml.close unless fileHtml.nil?
216
- end
217
-
218
- text
219
- end
220
-
221
- # Get the elements of the code in html format. Return a string with elements in html.
222
- #
223
- # Example:
224
- # >> CodeTerminator::Html.print_elements("exercises/hola_mundo.html" )
225
- # => "name = h1<br><hr>name = text<br>content = hola mundo<br><hr>"
226
- #
227
- # Arguments:
228
- # elements: (Array)
229
-
230
- def print_elements(elements)
231
- text = ""
232
- elements.each do |child|
233
- text << "parent = " + child[:parent] + "<br>" if child[:parent]
234
- text << "tag = " + child[:tag] + "<br>" if child[:tag]
235
- text << "attribute = " + child[:attribute] + "<br>" if child[:attribute]
236
- text << "value = " + child[:value] + "<br>" if child[:value]
237
- text << "content = " + child[:content] + "<br>" if child[:content]
238
- text << "<hr>"
239
- end
240
- text
241
- end
242
-
243
- # Get the instructions to recreate the html code. Return an array with strings .
244
- #
245
- # Example:
246
- # >> CodeTerminator::Html.get_instructions(file.get_elements("exercises/test.html"))
247
- # => ["Add the tag h2 in body", "Add the tag text in h2 with content 'hola test' ", "Add the tag p in body"]
248
- #
249
- # Arguments:
250
- # instructions: (Array)
251
-
252
- def get_instructions(source)
253
- elements = get_elements(source)
254
- text = ""
255
- instructions = Array.new
256
- elements.each do |child|
257
- if child[:tag]!="text"
258
- text << "Add the tag " + child[:tag]
259
- text << " in " + child[:parent] if !child[:parent].nil?
260
- text << " with an attribute '" + child[:attribute] + "' " if !child[:attribute].nil?
261
- text << " with value '" + child[:value] + "' " if !child[:value].nil?
262
- elsif child[:tag] == "comment"
263
- text << " In " + child[:tag]+ " add the text '" + child[:content] + "' " if !child[:content].nil?
264
- else
265
- text << " In " + child[:parent]+ " add the text '" + child[:content] + "' " if !child[:content].nil?
266
- end
267
- instructions.push(text)
268
- text = ""
269
- end
270
- instructions
271
- end
272
-
273
142
 
274
143
 
275
144
  # Match if the code have the same elements than the exercise. Return an array with the mismatches.
@@ -288,214 +157,182 @@ class CodeTerminator::Html
288
157
 
289
158
  def match(source, code)
290
159
  @html_errors = Array.new
291
- html_errors = @html_errors
292
-
293
160
  code = Nokogiri::HTML(code)
161
+ @elements = get_elements(source)
294
162
 
295
- elements = get_elements(source)
163
+ @elements.each do |e|
164
+ p css_string = build_css(e,'').strip
296
165
 
166
+ #search_attribute()
167
+ if e[:attribute]
168
+ # search_attribute = code.css(css_string).first
169
+ # if !search_attribute
170
+ # @html_errors << new_error(element: e, type: 334, description: "`<#{e[:tag]}>` should have an attribute named #{e[:attribute]} with the value #{e[:value]}")
171
+ # end
297
172
 
298
- exist_in_body = Array.new
173
+ #search_text()
174
+ elsif e[:tag] == "text" || e[:tag] == "comment"
175
+ element_name = e[:tag]=="comment" ? "comment":e[:parent]
176
+ search_elements = code.css(css_string)
177
+ if e[:content].strip != ""
178
+ element = search_elements.select{|hash| hash.text.strip == e[:content].strip}
179
+ if element.empty?
180
+ @html_errors << new_error(element: e, type: 330, description: "The text inside `<#{element_name}>` should be #{e[:content]}")
181
+ end
182
+ end
183
+ #search_element()
184
+ else
299
185
 
300
- error_elements = Array.new
186
+ search_element = code.css(css_string).first
187
+ if !search_element
188
+ @html_errors << new_error(element: e[:tag], type: 404, description: "Remember to add the `<#{e[:tag]}>` tag in " + css_string.chomp(e[:tag]))
189
+ # else
190
+ # if !are_all_elements(code,e[:tag], css_string)
191
+ # # @html_errors << new_error(element: e[:tag], type: 404, description: "Remember to add the `<#{e[:tag]}>` tag.")
192
+ # end
193
+ end
301
194
 
302
- elements_count = Array.new
195
+ end
303
196
 
304
- error333 = nil
197
+ end
305
198
 
306
- #lista de relaciones entre tags y elementos
307
- css_code_checked = Array.new
199
+ count_elements(code)
200
+ search_attribute_value(code)
308
201
 
202
+ p @html_errors
203
+ end
309
204
 
310
- elements.each do |e|
311
205
 
312
- if elements_count.select {|element| element[:parent_pointer].to_s == e[:parent_pointer].to_s && element[:tag].to_s == e[:tag]}.count < 1
313
- error_element = Hash.new
314
- error_element[:tag] = e[:tag]
315
- error_element[:pointer] = e[:pointer]
316
- error_element[:parent_pointer] = e[:parent_pointer]
317
- error_element[:count] = 0
318
- elements_count << error_element
319
- end
320
206
 
321
- item = e[:tag]
207
+ private
322
208
 
323
- if item == "text" or item == "comment"
324
- # Check the text
325
- if e[:content]
326
- if code.css(e[:parent]).count < 2
327
- if code.css(e[:parent]).class == Nokogiri::XML::NodeSet
328
- #look for children elements with texts or comments
329
- look_comment_or_text(code,e)
330
- end
331
- else
332
- #check if parent tag of the user code has text apart from the children tags
333
- look_parent_text(code,e)
334
- end
335
- end
336
- #end if content is null
337
- else
338
- #item class is different to text or comment
339
-
340
- code.css(e[:tag]).each do |tag|
341
- tag_element = nil
342
- e_check = css_code_checked.select {|element| element[:original_pointer].to_s == e[:pointer].to_s }
343
- # p "echeck " + e_check.to_s
344
- e_check2 = css_code_checked.select {|element| element[:pointer].to_s == tag.pointer_id.to_s }
345
-
346
- #original_pointer es el pointer del elemento e[]
347
- #busca si el original_pointer esta en la lista de relaciones
348
- #busca si el pointer del tag esta en la lista de relaciones
349
- #cuando un original pointer o un pointer esta en la lista de relaciones, ya no puede volver a ser ingresado en la lista
350
- #si el original pointer ya esta en la lista de relaciones, ya no es necesario volver a checarlo
351
- check_original_pointer = css_code_checked.select {|element| element[:original_pointer].to_s == e[:pointer].to_s }
352
-
353
- check_add_pointer = css_code_checked.select {|element| element[:pointer].to_s == tag.pointer_id.to_s }
354
-
355
- #look for same tags in code
356
- if check_original_pointer.count == 0
357
- if check_add_pointer.count < 1
358
- element_checked = Hash.new
359
- element_checked[:pointer] = tag.pointer_id
360
- element_checked[:tag] = e[:tag]
361
- element_checked[:original_pointer] = e[:pointer]
362
- element_checked[:original_parent_pointer] = e[:parent_pointer]
363
- css_code_checked << element_checked
364
-
365
- error_element = elements_count.select {|element| element[:tag].to_s == e[:tag].to_s && element[:parent_pointer].to_s == e[:parent_pointer].to_s}.first
366
- error_element[:count] += 1
367
- end
368
- end
369
- # end
370
- # p "checked = " + elements_count.to_s
371
-
372
- if code.css(e[:tag]).length > 0
373
-
374
- #tag es el elemento reccorrido en el codigo
375
- #e es el elemento original
376
- #elementscount son los elementos que existen en codigo y original
377
-
378
- # if tag_element
379
- if e[:attribute]
380
-
381
- # p "e --- " + e[:tag].to_s
382
- # p "e pt--- " + e[:pointer].to_s
383
- # p "e parent pt--- " + e[:parent_pointer].to_s
384
- # p "e attribute --- " + e[:attribute].to_s
385
-
386
-
387
- # if tag.attribute(e[:attribute])
388
- # p "elements count = " + css_code_checked.to_s
389
- tag_element = css_code_checked.select {|element| element[:pointer].to_s == tag.pointer_id.to_s && element[:original_pointer] == e[:pointer] }.first
390
- # p "tag --" + tag.name.to_s
391
- # p "tag --" + tag.to_s
392
- # p "tag parent -- " + tag.parent.name.to_s
393
- # p "tag pointer -- " + tag.pointer_id.to_s
394
- # p "tag parent pointer -- " + tag.parent.pointer_id.to_s
395
- # p "tag attribute -- " + tag.attribute(e[:attribute]).to_s
396
- # p "parent_element --- " + tag_element.to_s
397
- # else
398
- # end
399
-
400
- # Check the tag's attributes
401
- if tag.attribute(e[:attribute]).nil?
402
- if tag_element
403
- # p "attribute element " + e[:attribute].to_s
404
- # p "attribute tag " + tag.attribute(e[:attribute]).name.to_s
405
- # if e[:attribute] != tag.attribute(e[:attribute]).name
406
- html_errors << new_error(element: e, type: 334, description: "`<#{e[:tag]}>` should have an attribute named #{e[:attribute]}")
407
- # end
408
- end
409
- else
410
- if tag.attribute(e[:attribute]).value != e[:value]
411
- exist_in_body << false
412
- # p "type " + e[:tag] + " with attribute " + e[:attribute] + " value " + e[:value]
413
- # Check if the img have attribute src and value is null, the user can write whatever image he wants
414
- if !(e[:tag] == "img" && e[:attribute] == "src" && e[:value] == "")
415
- error333 = new_error(element: e, type: 333, description: "Make sure that the attribute #{e[:attribute]} in `<#{e[:tag]}>` has the value #{e[:value]}")
416
- end
417
- else
418
- # p "add code_checked"
419
- # css_code_checked << element_checked
420
- exist_in_body << true
421
- end
422
- end
423
- # end
209
+ def build_css(element, css)
210
+ if !element[:parent].empty?
211
+ if !element[:attribute]
212
+ if element[:tag]=="comment"
213
+ css += "//comment()"
214
+ else
215
+ parent = @elements.select{|hash| hash[:pointer].to_s == element[:parent_pointer].to_s}.first
216
+ parent_css = parent[:tag].to_s if parent
217
+ css += parent_css
218
+
219
+ parent_attributes = @elements.select{|hash| hash[:parent_pointer].to_s == element[:parent_pointer].to_s && hash[:attribute]}
220
+ parent_attributes.each do |par_attr|
221
+ css += css_attribute_type(par_attr)
222
+ end
223
+ css += " "
224
+ css += element[:tag].to_s + " " if element[:tag] != "text"
225
+ end
424
226
 
227
+ else
425
228
 
426
- # p "respond" + tag.parent.to_s
427
- # Check that tags exist within parent tags
428
- if tag.first.respond_to? :parent
229
+ search_attribute = @elements.select{|hash| hash[:parent_pointer].to_s == element[:parent_pointer].to_s && hash[:attribute].to_s == element[:attribute]}.first
230
+ css += search_attribute[:tag].to_s
231
+ attribute_css = css_attribute_type(search_attribute) if search_attribute
232
+ css += attribute_css
429
233
 
430
- p "check if exists in parent tags"
234
+ end
235
+ else
236
+ css += element[:tag].to_s + " " if element[:tag] != "text"
237
+ end
238
+ css
239
+ end
240
+
241
+ def css_attribute_type(element)
242
+ case element[:attribute]
243
+ when "id"
244
+ css_symbol = '#'
245
+ css = css_symbol.to_s + element[:value].to_s
246
+ when "class"
247
+ css_symbol = '.'
248
+ css = css_symbol.to_s + element[:value].to_s
249
+ when "src"
250
+ css_symbol = "[src]"
251
+ css = css_symbol.to_s
252
+ when "href"
253
+ css_symbol = "[href]"
254
+ css = css_symbol.to_s
255
+ when "alt"
256
+ css_symbol = "[alt]"
257
+ css = css_symbol.to_s
258
+ else
259
+ css_symbol = element[:attribute]
260
+ css = css_symbol.to_s
261
+ end
262
+ css
263
+ end
431
264
 
432
- # e_check4 = css_code_checked.select {|element| element[:pointer].to_s == e[:pointer].to_s }
433
- # e_check5 = css_code_checked.select {|element| element[:target_parent_pointer].to_s == e[:parent_pointer].to_s }
265
+ def are_all_elements(code, tag, css_string)
266
+ element_count = @elements.select{|hash| hash[:tag] == tag && !hash[:attribute]}.count
267
+ code_count = code.css(css_string).count
268
+ element_count > code_count ? false:true
269
+ end
434
270
 
435
- if (tag.count < 2 && tag.first)
436
- if tag.first.parent.name != e[:parent]
437
- html_errors << new_error(element: e, type: 440, description: "Remember to add the `<#{e[:tag]}>` tag inside `<#{e[:parent]}>`")
438
- end
271
+ def count_elements(code)
272
+ uniq_elements = @elements.group_by{|h| h[:tag]}
273
+ uniq_elements.each do |e|
274
+ if e[0] != "text"
275
+ # "element " + e[0].to_s
276
+ element_count = e[1].select{|hash| !hash[:attribute]}.count
277
+ if e[0] != "comment"
278
+ code_count = code.css(e[0]).count
439
279
  else
440
- exist_in_parent = false
441
- tag.each do |code_css|
442
- exist_in_parent = true if code_css.parent.name == e[:parent]
443
- end
444
- html_errors << new_error(element: e, type: 440, description: "Remember to add the `<#{e[:tag]}>` tag inside `<#{e[:parent]}>`") if !exist_in_parent
445
- end
446
- end
447
-
448
- end
280
+ code_count = code.css("//comment()").count
281
+ end
449
282
 
283
+ if element_count > code_count
284
+ @html_errors << new_error(element: e[0], type: 404, description: "Remember to add the `<#{e[0]}>` tag.")
285
+ end
450
286
  end
287
+ end
288
+ end
451
289
 
452
- end
290
+ # def search_comments(code)
291
+ # comment_elements = code.css('//comment()')
292
+ #
293
+ # end
453
294
 
454
- # end #end tag
295
+ def search_attribute_value(code)
296
+ uniq_elements = @elements.group_by{|h| h[:tag]}
297
+ uniq_elements.each do |e|
455
298
 
299
+ element_with_attributes = e[1].select{|hash| hash[:attribute]}
300
+ element_with_attributes.each do |ewa|
456
301
 
457
- if exist_in_body && !exist_in_body.include?(true) && error333
458
- html_errors << error333
459
- end
460
- exist_in_body = []
302
+ css_string = build_css(ewa, '')
461
303
 
462
- end
304
+ if code.css(css_string).empty?
305
+ @html_errors << new_error(element: ewa, type: 334, description: "`<#{ewa[:tag]}>` should have an attribute named #{ewa[:attribute]}")
306
+ else
463
307
 
464
- end
308
+ if ewa[:value] != "" && code.css(css_string).select{|x| x[ewa[:attribute]].to_s == ewa[:value].to_s}.empty?
309
+ @html_errors << new_error(element: ewa, type: 333, description: "Make sure that the attribute #{ewa[:attribute]} in `<#{ewa[:tag]}>` has the value #{ewa[:value]}")
310
+ end
465
311
 
466
- # p elements_count.to_s
467
-
468
- elements_count.each do |x|
469
- #filtrar por parent
470
- # tag_count = code.css(x[:tag]).length
471
- tag_count = elements.select {|element| element[:parent_pointer].to_s == x[:parent_pointer].to_s && element[:tag].to_s == x[:tag]}.count
472
- # p x[:tag]!="body"
473
- if tag_count >= 1 && !(x[:tag]=="body" || x[:tag]=="head" || x[:tag]=="text" || x[:tag]=="comment" || x[:tag]=="img")
474
- # if tag_count >= 1 && !(x[:tag]!="div")
475
- if x[:count] < tag_count
476
- html_errors << new_error(element: x[:tag], type: 404, description: "Remember to add the `<#{x[:tag]}>` tag")
477
- end
478
- end
479
- end
312
+ if code.css(css_string).select{|x| x[ewa[:attribute]].to_s == ""}.any?
313
+ @html_errors << new_error(element: ewa, type: 335, description: "`<#{ewa[:attribute]}>` in `<#{ewa[:tag]}>` can't be empty")
314
+ end
480
315
 
481
- html_errors
316
+ end
482
317
 
483
- end
318
+ end
319
+
320
+ end
484
321
 
485
- private
322
+
323
+ end
486
324
 
487
325
  def add_children(parent)
488
326
  parent.children.each do |child|
489
327
  if child.attribute_nodes.empty?
490
328
  node = Hash.new
491
329
  node[:parent] = parent.name
492
- # node[:tag] = child.name
493
330
  if child.name == "#cdata-section"
494
331
  node[:tag] = "text"
495
332
  else
496
333
  node[:tag] = child.name
497
334
  end
498
- node[:content] = child.text if !child.text.nil? and child.class!=Nokogiri::XML::Element
335
+ node[:content] = child.text.strip if child.text and child.class != Nokogiri::XML::Element
499
336
  node[:pointer] = child.pointer_id
500
337
  node[:parent_pointer] = child.parent.pointer_id
501
338
  @elements << node
@@ -503,16 +340,13 @@ class CodeTerminator::Html
503
340
  child.attribute_nodes.each do |element_attribute|
504
341
  node = Hash.new
505
342
  node[:parent] = parent.name
506
- # node[:tag] = child.namecode
507
343
  if element_attribute.name == "#cdata-section"
508
344
  node[:tag] = "text"
509
- elsif element_attribute.name == "href"
510
- node[:tag] = child.name
511
345
  else
512
- node[:tag] = element_attribute.name
346
+ node[:tag] = child.name
513
347
  end
514
- node[:attribute] = element_attribute.name if !element_attribute.name.nil?
515
- node[:value] = element_attribute.value if !element_attribute.value.nil?
348
+ node[:attribute] = element_attribute.name if element_attribute.name
349
+ node[:value] = element_attribute.value if element_attribute.value
516
350
  node[:pointer] = element_attribute.pointer_id
517
351
  node[:parent_pointer] = child.pointer_id
518
352
  @elements << node
@@ -564,82 +398,4 @@ class CodeTerminator::Html
564
398
  end
565
399
 
566
400
 
567
- #methods of match
568
- def look_comment_or_text(code,e)
569
- error330 = nil
570
- text_found = false
571
- @comment_found = false if e[:tag] == "comment"
572
-
573
- #look for comments or text in code
574
- #code, e
575
- if code.css(e[:parent]).children.any?
576
- #look for comments and text in children of body
577
- # code, e
578
- #save
579
- #return
580
- code.css(e[:parent]).children.each do |node_child|
581
- #if class of the node is a comment, look in the code
582
- # @e, node_child
583
- #save error330
584
- #return true (flag)
585
- if node_child.class == Nokogiri::XML::Comment
586
- 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!
587
- @comment_found = true
588
- end
589
-
590
- #if class of node is text and element is not a comment
591
- #@e, node_child
592
- #save a error330, text_found
593
- #return true (flag)
594
- if node_child.class == Nokogiri::XML::Text && e[:tag] != "comment"
595
- 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
596
- end
597
- end #each
598
-
599
- else
600
- #validate if comment exist and has the expected content in body
601
- #code, @e
602
- #save @comment_found, text_found
603
- if code.css(e[:parent]).text.strip != e[:content].strip
604
- if e[:tag] == "comment"
605
- error330 = new_error(element: e, type: 330, description: "The text inside the comment should be #{e[:content]}")
606
- @comment_found = true
607
- else
608
- error330 = new_error(element: e, type: 330, description: "The text inside `<#{e[:parent]}>` should be #{e[:content]}")
609
- end
610
- else
611
- text_found = true
612
- end
613
- end #end if parent has children
614
-
615
- #throw errors of comment or text
616
- #if comment not found, throw error
617
- if (defined? @comment_found) && !@comment_found
618
- @html_errors << new_error(element: e, type: 404, description: "Remember to add the comment tag")
619
- remove_instance_variable(:@comment_found) if !@comment_found
620
- end
621
-
622
- if !text_found && error330
623
- @html_errors << error330
624
- error330 = nil
625
- end
626
- #end throw errors
627
- end #end look_comment_or_text
628
-
629
- def look_parent_text(code,e)
630
- exist = false
631
- #look for text in parent, if found check flag true
632
- code.css(e[:parent]).each do |code_css|
633
- if code_css.text == e[:content]
634
- exist = true
635
- end
636
- end
637
- if !exist
638
- @html_errors << new_error(element: e, type: 330, description: "The text inside `<#{e[:parent]}>` should be #{e[:content]}")
639
- end
640
- end
641
-
642
-
643
- #end
644
-
645
401
  end