Class: CodeTerminator::Html

Inherits:
Object
  • Object
show all
Defined in:
lib/code_terminator/html.rb,
lib/code_terminator/html2.rb,
lib/code_terminator/html_deprecated.rb

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Html

Returns a new instance of Html.



5
6
7
8
9
10
11
12
13
# File 'lib/code_terminator/html.rb', line 5

def initialize(args = {})
  @code = args[:code]
  @source = args[:source]
  @tags = Array.new
  @elements = Array.new

  args[:source_type] ||= "file"
  @source_type = args[:source_type]
end

Instance Method Details

#get_elements(source) ⇒ Object

Get html elements of a html file. Return a list of Nokogiri XML objects.

Example:

>> CodeTerminator::Html.get_elements("hola_mundo.html")
=> [#<Nokogiri::XML::Element:0x3fe3391547d8 name="h1" children=[#<Nokogiri::XML::Text:0x3fe33915474c "Hola Mundo!">]>, #<Nokogiri::XML::Text:0x3fe33915474c "Hola Mundo!">]

Arguments:

source: (String)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/code_terminator/html.rb', line 25

def get_elements(source)
  @elements = Array.new
  #How to read if is an url
  if @source_type == "url"
    reader = Nokogiri::HTML(open(source).read)
  else
    reader = Nokogiri::HTML(File.open(source))
  end
  #remove empty spaces from reader
  reader = remove_empty_text(reader)
  if reader.css('html').any?
    node = Hash.new
    node[:parent] = ""
    node[:tag] = "html"
    node[:pointer] = reader.css('html').first.pointer_id
    @elements << node
  end

  #search elements from body section
    if reader.at('body')
      node = Hash.new
      node[:parent] = "html"
      node[:tag] = "body"
      node[:pointer] = reader.css('body').first.pointer_id
      node[:parent_pointer] = reader.css('html').first.pointer_id
      @elements << node

      reader.at('body').attribute_nodes.each do |element_attribute|
        node = Hash.new
        node[:parent] = "html"
        node[:tag] = "body"
        node[:attribute] = element_attribute.name if element_attribute.name
        node[:value] = element_attribute.value if element_attribute.value
        node[:pointer] = element_attribute.pointer_id
        node[:parent_pointer] = reader.css('html').first.pointer_id
        @elements << node
      end
   end
   #end search

   #search elements from head section
  if reader.at('head')
    node = Hash.new
    node[:parent] = "html"
    node[:tag] = "head"
    node[:pointer] = reader.css('head').first.pointer_id
    node[:parent_pointer] = reader.css('html').first.pointer_id
    @elements << node

    reader.at('head').children.each do |child|
      if child.attribute_nodes.empty?
        node = Hash.new
        node[:parent] = "head"
        node[:tag] = child.name
        node[:content] = child.text if child.text or child.comment?
        node[:pointer] = child.pointer_id
        node[:parent_pointer] = child.parent.pointer_id
        @elements << node
      else
        child.attribute_nodes.each do |element_attribute|
          node = Hash.new
          node[:parent] = "head"
          if child.name == "#cdata-section"
            node[:tag] = "text"
          else
            node[:tag] = child.name
          end
          node[:content] = child.text if child.text
          node[:attribute] = element_attribute.name if element_attribute.name
          node[:value] = element_attribute.value if element_attribute.value
          node[:pointer] = element_attribute.pointer_id
          node[:parent_pointer] = child.pointer_id
          @elements << node
        end
      end
      add_children(child) if child.children.any?
    end
 end
 #end search elements

 #search elements inside body (children)
 if reader.at('body')
   reader.at('body').children.each do |child|
     if child.attribute_nodes.empty?
       node = Hash.new
       node[:parent] = "body"
       node[:tag] = child.name
       node[:content] = child.text if child.text? or child.comment?
       node[:pointer] = child.pointer_id
       node[:parent_pointer] = child.parent.pointer_id
       @elements << node
     else
       node = Hash.new
       node[:parent] = "body"
       node[:tag] = child.name
       node[:content] = child.text if child.text? or child.comment?
       node[:pointer] = child.pointer_id
       node[:parent_pointer] = child.parent.pointer_id
       @elements << node
       child.attribute_nodes.each do |element_attribute|
         node = Hash.new
         node[:parent] = "body"
         node[:tag] = child.name
         node[:attribute] = element_attribute.name if element_attribute.name
         node[:value] = element_attribute.value if element_attribute.value
         node[:pointer] = element_attribute.pointer_id
         node[:parent_pointer] = child.pointer_id
         @elements << node
       end
     end
     add_children(child) if child.children.any?
   end
  end
  #end search elements
  @elements
end

#get_instructions(source) ⇒ Object

Get the instructions to recreate the html code. Return an array with strings .

Example:

>> CodeTerminator::Html.get_instructions(file.get_elements("exercises/test.html"))
=> ["Add the tag h2 in body", "Add the tag text in h2 with content 'hola test' ", "Add the tag p in body"]

Arguments:

instructions: (Array)


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/code_terminator/html2.rb', line 252

def get_instructions(source)
  elements = get_elements(source)
  text = ""
  instructions = Array.new
  elements.each do |child|
    if child[:tag]!="text"
      text << "Add the tag " + child[:tag]
      text << " in "  + child[:parent]  if !child[:parent].nil?
      text << " with an attribute '" + child[:attribute] + "' " if !child[:attribute].nil?
      text << " with value '" + child[:value] + "' " if !child[:value].nil?
    elsif child[:tag] == "comment"
     text << " In " + child[:tag]+ " add the text '" + child[:content]  + "' "  if !child[:content].nil?
    else
      text << " In " + child[:parent]+ " add the text '" + child[:content]  + "' "  if !child[:content].nil?
    end
    instructions.push(text)
    text = ""
  end
  instructions
end

#match(source, code) ⇒ Object

Match if the code have the same elements than the exercise. Return an array with the mismatches.

Example:

hola_mundo.html

> <h1>Hola Mundo!</h1>

>> CodeTerminator::Html.match("hola_mundo.html","<h2>Hola Mundo!</h2>")
=> ["h1 not exist"]

Arguments:

source: (String)
code: (String)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/code_terminator/html.rb', line 158

def match(source, code)
  @html_errors = Array.new
  code = Nokogiri::HTML(code)
  @elements = get_elements(source)

  @elements.each do |e|
    p css_string = build_css(e,'').strip

    #search_attribute()
    if e[:attribute]
     #  search_attribute = code.css(css_string).first
     #  if !search_attribute
     #    @html_errors << new_error(element: e, type: 334, description: "`<#{e[:tag]}>` should have an attribute named #{e[:attribute]} with the value #{e[:value]}")
     #  end

    #search_text()
   elsif e[:tag] == "text" || e[:tag] == "comment"
      element_name = e[:tag]=="comment" ? "comment":e[:parent]
      search_elements = code.css(css_string)
      if e[:content].strip != ""
        element = search_elements.select{|hash| hash.text.strip == e[:content].strip}
        if element.empty?
          @html_errors << new_error(element: e, type: 330, description: "The text inside `<#{element_name}>` should be #{e[:content]}")
        end
      end
   #search_element()
    else

      search_element = code.css(css_string).first
      if !search_element
         @html_errors << new_error(element: e[:tag], type: 404, description:  "Remember to add the `<#{e[:tag]}>` tag in " + css_string.chomp(e[:tag]))
     #  else
     #    if !are_all_elements(code,e[:tag], css_string)
     #     #  @html_errors << new_error(element: e[:tag], type: 404, description:  "Remember to add the `<#{e[:tag]}>` tag.")
     #    end
       end

    end

  end

  count_elements(code)
  search_attribute_value(code)

  p @html_errors
end

#new_file(source, code) ⇒ Object

Create a Html file with the code of the editor. Return a boolean that indicate if the file was created or not.

Example:

>> CodeTerminator::Html.new_file("hola_mundo.html", "<h1>Hola Mundo!</h1>")
=> true

Arguments:

source: (String)
code: (String)


25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/code_terminator/html2.rb', line 25

def new_file(source,code)
  fileHtml = File.new(source, "w+")
  result = true
  begin
    fileHtml.puts code
  rescue
    result = false
  ensure
    fileHtml.close unless fileHtml.nil?
  end
  #return true if file was succesfully created
  result
end

Get the elements of the code in html format. Return a string with elements in html.

Example:

>> CodeTerminator::Html.print_elements("exercises/hola_mundo.html" )
=> "name = h1<br><hr>name = text<br>content = hola mundo<br><hr>"

Arguments:

elements: (Array)


230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/code_terminator/html2.rb', line 230

def print_elements(elements)
  text = ""
  elements.each do |child|
    text << "parent = " + child[:parent] + "<br>" if child[:parent]
    text << "tag = " + child[:tag] + "<br>" if child[:tag]
    text << "attribute = " + child[:attribute] + "<br>" if child[:attribute]
    text << "value = " + child[:value] + "<br>" if child[:value]
    text << "content = " + child[:content] + "<br>" if child[:content]
    text << "<hr>"
  end
  text
end

#read_file(source) ⇒ Object

Read a html file. Return the text of the file.

Example:

>> CodeTerminator::Html.read_file("hola_mundo.html")
=> "<h1>Hola Mundo!</h1>\n"

Arguments:

source: (String)


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/code_terminator/html2.rb', line 199

def read_file(source)
  if @source_type == "url"
    fileHtml = open(source).read
  else
    fileHtml = File.open(source, "r")
  end

  text = ""
  begin
    fileHtml.each_line do |line|
      text << line
    end
    fileHtml.close
  rescue
    text = false
  ensure
    #fileHtml.close unless fileHtml.nil?
  end

  text
end

#validate_syntax(code) ⇒ Object

Validate if the syntax is correct. Return an array with Nokogiri errors.

Example:

>> CodeTerminator::Html.validate_syntax("<h1>Hola Mundo!</h1")
=> [#<Nokogiri::XML::SyntaxError: expected '>'>]

Arguments:

code: (String)


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/code_terminator/html2.rb', line 162

def validate_syntax(code)
  errors = Array.new

  begin
    Nokogiri::XML(code) { |config| config.strict }

    #validate if html follow w3, uncomment when check all the page
      #"<!DOCTYPE html>
      # <html>
      #   <head>
      #     <h1>asdasd</h1>
      #     <title>asdasd</title>
      #   </head>
      #   <body>
      #     <h1>hola</h1>
      #   </body>
      # </html>"
    # @validator = Html5Validator::Validator.new
    # @validator.validate_text(@html)

  rescue Nokogiri::XML::SyntaxError => e
    #errors[0] = "Check if you close your tags"
    errors[0] = e
  end

  errors
end