Class: Qti::Models::Base

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

Direct Known Subclasses

Manifest, V1::Models::Base, V2::Models::Base

Constant Summary collapse

ELEMENTS_REMAP =
{
  'prompt' => 'div',
  'simpleBlock' => 'div',
  'simpleInline' => 'span',
  'atomicBlock' => 'div',
  'atomicInline' => 'span'
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Base.

Raises:

  • (ArgumentError)


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

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

Instance Attribute Details

#docObject (readonly)

Returns the value of attribute doc.



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

def doc
  @doc
end

#manifestObject

Returns the value of attribute manifest.



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

def manifest
  @manifest
end

#package_rootObject

Returns the value of attribute package_root.



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

def package_root
  @package_root
end

#pathObject (readonly)

Returns the value of attribute path.



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

def path
  @path
end

Class Method Details

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



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

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

Instance Method Details

#css_with_single_check(css) ⇒ Object

Raises:



73
74
75
76
77
# File 'lib/qti/models/base.rb', line 73

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

#object_tag_transformerObject



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

def object_tag_transformer
  lambda do |env|
    return unless env[:node_name] == 'object'
    return if env[:is_whitelisted] || !env[:node].element?
    replace_object_node(env[:node])
  end
end

#parse_html(html_string) ⇒ Object



83
84
85
# File 'lib/qti/models/base.rb', line 83

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

#parse_xml(xml_string) ⇒ Object



79
80
81
# File 'lib/qti/models/base.rb', line 79

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

#remap_href_path(href) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/qti/models/base.rb', line 87

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

#remap_unknown_tags_transformerObject



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

def remap_unknown_tags_transformer
  lambda do |env|
    node_name = env[:node_name]
    node = env[:node]

    return if env[:is_whitelisted] || !node.element?
    return unless ELEMENTS_REMAP.keys.include? node_name

    new_name = ELEMENTS_REMAP[node_name]
    env[:node].name = new_name
    env[:node_name] = new_name
  end
end

#sanitize_config(import_objects: true) ⇒ Object



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

def sanitize_config(import_objects: true)
  transformers = []
  transformers << object_tag_transformer if import_objects
  transformers << remap_unknown_tags_transformer
  Sanitize::Config::RELAXED.merge transformers: transformers
end

#sanitize_content!(html) ⇒ Object



23
24
25
# File 'lib/qti/models/base.rb', line 23

def sanitize_content!(html)
  Sanitize.fragment(html, sanitize_config)
end

#xpath_with_single_check(xpath) ⇒ Object

Raises:



67
68
69
70
71
# File 'lib/qti/models/base.rb', line 67

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