Class: Qti::Models::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/qti/models/base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, package_root: nil, html: false, resource: nil) ⇒ Base

Returns a new instance of Base.

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
# File 'lib/qti/models/base.rb', line 25

def initialize(path:, package_root: nil, html: false, resource: nil)
  @path = path
  @resource = resource
  self.package_root = package_root || File.dirname(path)
  @doc = html ? parse_html(File.read(path)) : parse_xml(File.read(path))
  raise ArgumentError unless @doc
  preprocess_xml_doc(@doc) unless html
end

Instance Attribute Details

#docObject (readonly)

Returns the value of attribute doc.



13
14
15
# File 'lib/qti/models/base.rb', line 13

def doc
  @doc
end

#manifestObject

Returns the value of attribute manifest.



14
15
16
# File 'lib/qti/models/base.rb', line 14

def manifest
  @manifest
end

#package_rootObject

Returns the value of attribute package_root.



13
14
15
# File 'lib/qti/models/base.rb', line 13

def package_root
  @package_root
end

#pathObject (readonly)

Returns the value of attribute path.



13
14
15
# File 'lib/qti/models/base.rb', line 13

def path
  @path
end

#resourceObject (readonly)

Returns the value of attribute resource.



13
14
15
# File 'lib/qti/models/base.rb', line 13

def resource
  @resource
end

Class Method Details

.from_path!(path, package_root = nil, resource = nil) ⇒ Object



21
22
23
# File 'lib/qti/models/base.rb', line 21

def self.from_path!(path, package_root = nil, resource = nil)
  new(path: path, package_root: package_root, resource: resource)
end

Instance Method Details

#css_with_single_check(css) ⇒ Object

Raises:



54
55
56
57
58
# File 'lib/qti/models/base.rb', line 54

def css_with_single_check(css)
  node_list = @doc.css(css)
  raise Qti::ParseError, 'Too many matches' if node_list.count > 1
  node_list.first
end

#parse_html(html_string) ⇒ Object



64
65
66
# File 'lib/qti/models/base.rb', line 64

def parse_html(html_string)
  Nokogiri.HTML(html_string, @path.to_s, &:noblanks)
end

#parse_xml(xml_string) ⇒ Object



60
61
62
# File 'lib/qti/models/base.rb', line 60

def parse_xml(xml_string)
  Nokogiri.XML(xml_string, @path.to_s, &:noblanks)
end

#preprocess_xml_doc(xml_doc) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/qti/models/base.rb', line 34

def preprocess_xml_doc(xml_doc)
  converter = Mathml2latex::Converter.new
  converter.replace_with_latex(xml_doc)
  nodes = xml_doc.xpath('//mm:latex', 'mm' => Mathml2latex::INSTUCTURE_LATEX_NS)

  nodes.each do |node|
    # convert all #160 space to regular #32 whitespace
    # latex parser won't work for #160 space
    text = node.text.tr("\u00a0", ' ')
    latex_string = " \\(#{text}\\) "
    node.replace(latex_string)
  end
end

#raise_unsupported(message = 'Unsupported QTI version') ⇒ Object



81
82
83
# File 'lib/qti/models/base.rb', line 81

def raise_unsupported(message = 'Unsupported QTI version')
  raise Qti::UnsupportedSchema, message
end

#remap_href_path(href) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/qti/models/base.rb', line 68

def remap_href_path(href)
  return nil unless href
  path = File.join(File.dirname(@path), href)
  if @package_root.nil?
    raise Qti::ParseError, "Potentially unsafe href '#{href}'" if href.split('/').include?('..')
  else
    unless Pathname.new(path).cleanpath.to_s.start_with?(@package_root)
      raise Qti::ParseError, "Unsafe href '#{href}'"
    end
  end
  path
end

#sanitize_content!(html) ⇒ Object



17
18
19
# File 'lib/qti/models/base.rb', line 17

def sanitize_content!(html)
  sanitizer.clean(html)
end

#xpath_with_single_check(xpath) ⇒ Object

Raises:



48
49
50
51
52
# File 'lib/qti/models/base.rb', line 48

def xpath_with_single_check(xpath)
  node_list = @doc.xpath(xpath)
  raise Qti::ParseError, 'Too many matches' if node_list.count > 1
  node_list.first
end