Class: OpenStax::Content::Page

Inherits:
Object
  • Object
show all
Defined in:
lib/openstax/content/page.rb

Constant Summary collapse

ROOT_CSS =

Start parsing here

'html > body'
SNAP_LAB_CSS =

Find snap lab notes

'.snap-lab'
SNAP_LAB_TITLE_CSS =
'[data-type="title"]'
LO_DEF_NODE_CSS =

Find nodes that define relevant tags

'.ost-learning-objective-def'
STD_DEF_NODE_CSS =
'.ost-standards-def'
TEKS_DEF_NODE_CSS =
'.ost-standards-teks'
APBIO_DEF_NODE_CSS =
'.ost-standards-apbio'
STD_NAME_NODE_CSS =
'.ost-standards-name'
STD_DESC_NODE_CSS =
'.ost-standards-description'
LO_REGEX =

Find specific tags and extract the relevant parts

/ost-tag-lo-([\w+-]+)/
STD_REGEX =
/ost-tag-std-([\w+-]+)/
TEKS_REGEX =
/ost-tag-(teks-[\w+-]+)/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(book: nil, hash: {}, uuid: nil, url: nil, title: nil, slug: nil, content: nil) ⇒ Page

Returns a new instance of Page.

Raises:

  • (ArgumentError)


35
36
37
38
39
40
41
42
43
44
45
# File 'lib/openstax/content/page.rb', line 35

def initialize(book: nil, hash: {}, uuid: nil, url: nil, title: nil, slug: nil, content: nil)
  @uuid    = uuid || hash['id']&.split('@', 2)&.first
  raise ArgumentError, 'Either uuid or hash with id key is required' if @uuid.nil?

  @book    = book
  @hash    = hash
  @url     = url
  @title   = title || hash['title']
  @slug    = slug || hash['slug']
  @content = content
end

Instance Attribute Details

#chapter_sectionObject

Returns the value of attribute chapter_section.



47
48
49
# File 'lib/openstax/content/page.rb', line 47

def chapter_section
  @chapter_section
end

#hashObject (readonly)

Returns the value of attribute hash.



48
49
50
# File 'lib/openstax/content/page.rb', line 48

def hash
  @hash
end

#slugObject (readonly)

Returns the value of attribute slug.



48
49
50
# File 'lib/openstax/content/page.rb', line 48

def slug
  @slug
end

#uuidObject (readonly)

Returns the value of attribute uuid.



48
49
50
# File 'lib/openstax/content/page.rb', line 48

def uuid
  @uuid
end

Class Method Details

.feature_node(node, feature_ids) ⇒ Object



27
28
29
30
31
32
33
# File 'lib/openstax/content/page.rb', line 27

def self.feature_node(node, feature_ids)
  feature_ids = [feature_ids].flatten
  return if feature_ids.empty?

  feature_id_css = feature_ids.map { |feature_id| "##{feature_id}" }.join(', ')
  node.at_css(feature_id_css)
end

Instance Method Details

#aplosObject



118
119
120
# File 'lib/openstax/content/page.rb', line 118

def aplos
  @aplos ||= tags.select { |tag| tag[:type] == :aplo }.map { |tag| tag[:value] }
end

#bookObject

Raises:

  • (ArgumentError)


50
51
52
53
54
# File 'lib/openstax/content/page.rb', line 50

def book
  raise ArgumentError, 'Book was not specified' if @book.nil?

  @book
end

#book_locationObject



64
65
66
# File 'lib/openstax/content/page.rb', line 64

def book_location
  parsed_title.book_location
end

#contentObject



80
81
82
# File 'lib/openstax/content/page.rb', line 80

def content
  @content ||= full_hash.fetch('content')
end

#convert_content!Object

Replaces links to embeddable sims (and maybe videos in the future) with iframes Changes exercise urls in the doc to be absolute



98
99
100
101
102
103
104
# File 'lib/openstax/content/page.rb', line 98

def convert_content!
  OpenStax::Content::Fragment::Interactive.replace_interactive_links_with_iframes!(doc)
  OpenStax::Content::Fragment::Exercise.absolutize_exercise_urls!(doc)
  map_note_format!(doc)
  @content = doc.to_html
  @root = nil
end

#docObject



84
85
86
# File 'lib/openstax/content/page.rb', line 84

def doc
  @doc ||= Nokogiri::HTML(content)
end

#footnotesObject



92
93
94
# File 'lib/openstax/content/page.rb', line 92

def footnotes
  @footnotes ||= doc.css('[role=doc-footnote]')
end

#full_hashObject



72
73
74
# File 'lib/openstax/content/page.rb', line 72

def full_hash
  @full_hash ||= book.archive.json url
end

#losObject



114
115
116
# File 'lib/openstax/content/page.rb', line 114

def los
  @los ||= tags.select { |tag| tag[:type] == :lo }.map { |tag| tag[:value] }
end

#parsed_titleObject



60
61
62
# File 'lib/openstax/content/page.rb', line 60

def parsed_title
  @parsed_title ||= OpenStax::Content::Title.new @title
end

#rootObject



88
89
90
# File 'lib/openstax/content/page.rb', line 88

def root
  @root ||= doc.at_css(ROOT_CSS)
end

#short_idObject



76
77
78
# File 'lib/openstax/content/page.rb', line 76

def short_id
  @short_id ||= full_hash.fetch('shortId', nil)
end

#snap_lab_nodesObject



106
107
108
# File 'lib/openstax/content/page.rb', line 106

def snap_lab_nodes
  root.css(SNAP_LAB_CSS)
end

#snap_lab_title(snap_lab) ⇒ Object



110
111
112
# File 'lib/openstax/content/page.rb', line 110

def snap_lab_title(snap_lab)
  snap_lab.at_css(SNAP_LAB_TITLE_CSS).try(:text)
end

#tagsObject



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/openstax/content/page.rb', line 122

def tags
  return @tags.values unless @tags.nil?

  # Start with default cnxmod tag
  cnxmod_value = "context-cnxmod:#{uuid}"
  @tags = { cnxmod_value => { value: cnxmod_value, type: :cnxmod } }

  # Extract tag name and description from .ost-standards-def and .os-learning-objective-def.

  # LO tags
  root.css(LO_DEF_NODE_CSS).each do |node|
    klass = node.attr('class')
    lo_value = LO_REGEX.match(klass).try(:[], 1)
    next if lo_value.nil?

    teks_value = TEKS_REGEX.match(klass).try(:[], 1)
    description = node.content.strip

    @tags[lo_value] = {
      value: lo_value,
      description: description,
      teks: teks_value,
      type: :lo
    }
  end

  # Other standards
  root.css(STD_DEF_NODE_CSS).each do |node|
    klass = node.attr('class')
    name = node.at_css(STD_NAME_NODE_CSS).try(:content).try(:strip)
    description = node.at_css(STD_DESC_NODE_CSS).try(:content).try(:strip)
    value = nil

    if node.matches?(TEKS_DEF_NODE_CSS)
      value = TEKS_REGEX.match(klass).try(:[], 1)
      type = :teks
    elsif node.matches?(APBIO_DEF_NODE_CSS)
      value = LO_REGEX.match(klass).try(:[], 1)
      type = :aplo
    end

    next if value.nil?

    @tags[value] = {
      value: value,
      name: name,
      description: description,
      type: type
    }
  end

  @tags.values
end

#titleObject



68
69
70
# File 'lib/openstax/content/page.rb', line 68

def title
  parsed_title.text
end

#urlObject



56
57
58
# File 'lib/openstax/content/page.rb', line 56

def url
  @url ||= "#{book.url_fragment}:#{uuid}.json"
end