openstax_kitchen 3.0.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/CHANGELOG.md +77 -3
  4. data/Gemfile.lock +13 -14
  5. data/README.md +23 -0
  6. data/codecov.yaml +1 -0
  7. data/docker/ci +0 -1
  8. data/lib/kitchen/book_document.rb +1 -1
  9. data/lib/kitchen/book_element.rb +16 -2
  10. data/lib/kitchen/chapter_element.rb +10 -13
  11. data/lib/kitchen/chapter_element_enumerator.rb +1 -1
  12. data/lib/kitchen/composite_chapter_element.rb +7 -11
  13. data/lib/kitchen/composite_chapter_element_enumerator.rb +21 -0
  14. data/lib/kitchen/composite_page_element.rb +15 -10
  15. data/lib/kitchen/composite_page_element_enumerator.rb +1 -1
  16. data/lib/kitchen/config.rb +14 -0
  17. data/lib/kitchen/directions/bake_chapter_glossary/main.rb +18 -0
  18. data/lib/kitchen/directions/bake_chapter_glossary/v1.rb +30 -0
  19. data/lib/kitchen/directions/bake_chapter_introductions.rb +1 -1
  20. data/lib/kitchen/directions/bake_chapter_key_concepts/main.rb +16 -0
  21. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +35 -0
  22. data/lib/kitchen/directions/bake_chapter_key_equations.rb +27 -20
  23. data/lib/kitchen/directions/bake_chapter_references/main.rb +16 -0
  24. data/lib/kitchen/directions/bake_chapter_references/v1.rb +35 -0
  25. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +11 -0
  26. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +28 -0
  27. data/lib/kitchen/directions/bake_chapter_summary.rb +48 -42
  28. data/lib/kitchen/directions/bake_checkpoint.rb +44 -0
  29. data/lib/kitchen/directions/bake_composite_chapters.rb +14 -0
  30. data/lib/kitchen/directions/bake_composite_pages.rb +1 -1
  31. data/lib/kitchen/directions/bake_equations.rb +37 -0
  32. data/lib/kitchen/directions/bake_example.rb +34 -8
  33. data/lib/kitchen/directions/bake_figure.rb +1 -1
  34. data/lib/kitchen/directions/bake_first_elements.rb +16 -0
  35. data/lib/kitchen/directions/bake_footnotes/v1.rb +2 -1
  36. data/lib/kitchen/directions/bake_free_response/free_response.xhtml.erb +10 -0
  37. data/lib/kitchen/directions/bake_free_response/main.rb +11 -0
  38. data/lib/kitchen/directions/bake_free_response/v1.rb +29 -0
  39. data/lib/kitchen/directions/bake_further_research.rb +59 -0
  40. data/lib/kitchen/directions/bake_index/v1.rb +35 -14
  41. data/lib/kitchen/directions/bake_link_placeholders.rb +1 -1
  42. data/lib/kitchen/directions/bake_non_introduction_pages.rb +26 -0
  43. data/lib/kitchen/directions/bake_notes/bake_autotitled_notes.rb +29 -0
  44. data/lib/kitchen/directions/bake_notes/bake_note_subtitle.rb +22 -0
  45. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +51 -0
  46. data/lib/kitchen/directions/bake_notes/bake_unclassified_notes.rb +30 -0
  47. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +15 -0
  48. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +47 -0
  49. data/lib/kitchen/directions/bake_numbered_table/main.rb +2 -2
  50. data/lib/kitchen/directions/bake_numbered_table/v1.rb +18 -4
  51. data/lib/kitchen/directions/bake_page_abstracts.rb +16 -0
  52. data/lib/kitchen/directions/bake_references/main.rb +16 -0
  53. data/lib/kitchen/directions/bake_references/v1.rb +48 -0
  54. data/lib/kitchen/directions/bake_stepwise.rb +1 -5
  55. data/lib/kitchen/directions/bake_suggested_reading.rb +5 -0
  56. data/lib/kitchen/directions/bake_theorem/main.rb +11 -0
  57. data/lib/kitchen/directions/bake_theorem/v1.rb +28 -0
  58. data/lib/kitchen/directions/bake_toc.rb +10 -2
  59. data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +9 -0
  60. data/lib/kitchen/directions/{bake_exercises → book_answer_key_container}/main.rb +1 -1
  61. data/lib/kitchen/directions/book_answer_key_container/v1.rb +13 -0
  62. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +9 -0
  63. data/lib/kitchen/directions/chapter_review_container/main.rb +11 -0
  64. data/lib/kitchen/directions/chapter_review_container/v1.rb +13 -0
  65. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +20 -0
  66. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +27 -0
  67. data/lib/kitchen/directions/move_exercises_to_eoc/v1.rb +36 -0
  68. data/lib/kitchen/directions/move_exercises_to_eoc/v2.rb +49 -0
  69. data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +14 -0
  70. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +19 -0
  71. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/calculus.rb +41 -0
  72. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/uphysics.rb +63 -0
  73. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +34 -0
  74. data/lib/kitchen/document.rb +3 -0
  75. data/lib/kitchen/element.rb +9 -3
  76. data/lib/kitchen/element_base.rb +118 -16
  77. data/lib/kitchen/element_enumerator_base.rb +118 -8
  78. data/lib/kitchen/element_enumerator_factory.rb +28 -12
  79. data/lib/kitchen/element_factory.rb +3 -3
  80. data/lib/kitchen/example_element.rb +8 -11
  81. data/lib/kitchen/example_element_enumerator.rb +1 -1
  82. data/lib/kitchen/exercise_element.rb +42 -0
  83. data/lib/kitchen/exercise_element_enumerator.rb +21 -0
  84. data/lib/kitchen/figure_element.rb +8 -11
  85. data/lib/kitchen/figure_element_enumerator.rb +1 -1
  86. data/lib/kitchen/metadata_element.rb +8 -2
  87. data/lib/kitchen/metadata_element_enumerator.rb +1 -1
  88. data/lib/kitchen/note_element.rb +25 -27
  89. data/lib/kitchen/note_element_enumerator.rb +1 -1
  90. data/lib/kitchen/oven.rb +2 -0
  91. data/lib/kitchen/page_element.rb +33 -9
  92. data/lib/kitchen/page_element_enumerator.rb +1 -1
  93. data/lib/kitchen/patches/nokogiri.rb +55 -0
  94. data/lib/kitchen/patches/nokogiri_profiling.rb +60 -0
  95. data/lib/kitchen/recipe.rb +35 -2
  96. data/lib/kitchen/reference_element.rb +27 -0
  97. data/lib/kitchen/references_element_enumerator.rb +20 -0
  98. data/lib/kitchen/search_query.rb +31 -3
  99. data/lib/kitchen/selector.rb +25 -0
  100. data/lib/kitchen/selectors/base.rb +39 -0
  101. data/lib/kitchen/selectors/standard_1.rb +13 -0
  102. data/lib/kitchen/table_element.rb +8 -11
  103. data/lib/kitchen/table_element_enumerator.rb +1 -1
  104. data/lib/kitchen/templates/eob_section_title_template.xhtml.erb +10 -0
  105. data/lib/kitchen/templates/eoc_section_title_template.xhtml.erb +10 -0
  106. data/lib/kitchen/term_element.rb +5 -8
  107. data/lib/kitchen/term_element_enumerator.rb +1 -1
  108. data/lib/kitchen/unit_element.rb +13 -7
  109. data/lib/kitchen/unit_element_enumerator.rb +1 -1
  110. data/lib/kitchen/version.rb +1 -1
  111. data/lib/locales/en.yml +12 -7
  112. data/lib/locales/pl.yml +24 -0
  113. data/lib/openstax_kitchen.rb +2 -1
  114. metadata +54 -6
  115. data/lib/kitchen/directions/bake_chapter_glossary.rb +0 -37
  116. data/lib/kitchen/directions/bake_exercises/v1.rb +0 -166
  117. data/lib/kitchen/directions/bake_notes.rb +0 -58
@@ -70,6 +70,60 @@ module Kitchen
70
70
  chain_to(PageElementEnumerator, css_or_xpath: css_or_xpath, only: only, except: except)
71
71
  end
72
72
 
73
+ # Returns an enumerator that iterates through composite pages within the scope of this enumerator
74
+ #
75
+ # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
76
+ # a "$" in this argument will be replaced with the default selector for the element being
77
+ # iterated over.
78
+ # @param only [Symbol, Callable] the name of a method to call on an element or a
79
+ # lambda or proc that accepts an element; elements will only be included in the
80
+ # search results if the method or callable returns true
81
+ # @param except [Symbol, Callable] the name of a method to call on an element or a
82
+ # lambda or proc that accepts an element; elements will not be included in the
83
+ # search results if the method or callable returns false
84
+ #
85
+ def composite_pages(css_or_xpath=nil, only: nil, except: nil)
86
+ block_error_if(block_given?)
87
+ chain_to(CompositePageElementEnumerator,
88
+ css_or_xpath: css_or_xpath,
89
+ only: only,
90
+ except: except)
91
+ end
92
+
93
+ # Returns an enumerator that iterates through composite chapters within the scope of this enumerator
94
+ #
95
+ # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
96
+ # a "$" in this argument will be replaced with the default selector for the element being
97
+ # iterated over.
98
+ # @param only [Symbol, Callable] the name of a method to call on an element or a
99
+ # lambda or proc that accepts an element; elements will only be included in the
100
+ # search results if the method or callable returns true
101
+ # @param except [Symbol, Callable] the name of a method to call on an element or a
102
+ # lambda or proc that accepts an element; elements will not be included in the
103
+ # search results if the method or callable returns false
104
+ #
105
+ def composite_chapters(css_or_xpath=nil, only: nil, except: nil)
106
+ block_error_if(block_given?)
107
+ chain_to(CompositeChapterElementEnumerator,
108
+ css_or_xpath: css_or_xpath,
109
+ only: only,
110
+ except: except)
111
+ end
112
+
113
+ # Returns an enumerator that iterates through pages that arent the introduction page within the scope of this enumerator
114
+ #
115
+ # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
116
+ # a "$" in this argument will be replaced with the default selector for the element being
117
+ # iterated over.
118
+ #
119
+ def non_introduction_pages(only: nil, except: nil)
120
+ block_error_if(block_given?)
121
+ chain_to(PageElementEnumerator,
122
+ css_or_xpath: '$:not(.introduction)',
123
+ only: only,
124
+ except: except)
125
+ end
126
+
73
127
  # Returns an enumerator that iterates through chapters within the scope of this enumerator
74
128
  #
75
129
  # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
@@ -166,6 +220,52 @@ module Kitchen
166
220
  chain_to(ExampleElementEnumerator, css_or_xpath: css_or_xpath, only: only, except: except)
167
221
  end
168
222
 
223
+ # Returns an enumerator that iterates through titles within the scope of this enumerator
224
+ #
225
+ # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
226
+ # a "$" in this argument will be replaced with the default selector for the element being
227
+ # iterated over.
228
+ # @param only [Symbol, Callable] the name of a method to call on an element or a
229
+ # lambda or proc that accepts an element; elements will only be included in the
230
+ # search results if the method or callable returns true
231
+ # @param except [Symbol, Callable] the name of a method to call on an element or a
232
+ # lambda or proc that accepts an element; elements will not be included in the
233
+ # search results if the method or callable returns false
234
+ #
235
+ def titles(css_or_xpath=nil, only: nil, except: nil)
236
+ block_error_if(block_given?)
237
+ chain_to(ElementEnumerator,
238
+ default_css_or_xpath: '[data-type="title"]',
239
+ css_or_xpath: css_or_xpath,
240
+ only: only,
241
+ except: except)
242
+ end
243
+
244
+ # Returns an enumerator that iterates through references within the scope of this enumerator
245
+ #
246
+ # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
247
+ # a "$" in this argument will be replaced with the default selector for the element being
248
+ # iterated over.
249
+ #
250
+ def references(css_or_xpath=nil)
251
+ block_error_if(block_given?)
252
+ chain_to(ReferenceElementEnumerator, css_or_xpath: css_or_xpath)
253
+ end
254
+
255
+ # Returns an enumerator that iterates through exercises within the scope of this enumerator
256
+ #
257
+ # @param only [Symbol, Callable] the name of a method to call on an element or a
258
+ # lambda or proc that accepts an element; elements will only be included in the
259
+ # search results if the method or callable returns true
260
+ # @param except [Symbol, Callable] the name of a method to call on an element or a
261
+ # lambda or proc that accepts an element; elements will not be included in the
262
+ # search results if the method or callable returns false
263
+ #
264
+ def exercises(css_or_xpath=nil, only: nil, except: nil)
265
+ block_error_if(block_given?)
266
+ chain_to(ExerciseElementEnumerator, css_or_xpath: css_or_xpath, only: only, except: except)
267
+ end
268
+
169
269
  # Returns an enumerator that iterates through metadata within the scope of this enumerator
170
270
  #
171
271
  # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
@@ -195,7 +295,12 @@ module Kitchen
195
295
  # Returns an enumerator that iterates through elements within the scope of this enumerator
196
296
  #
197
297
  # @param enumerator_class [ElementEnumeratorBase] the enumerator to use for the iteration
298
+ # @param default_css_or_xpath [String] the default CSS or xpath to use when iterating. Normally,
299
+ # this value is provided by the `enumerator_class`, but that isn't always the case, e.g.
300
+ # when that class is a generic `ElementEnumerator`.
198
301
  # @param css_or_xpath [String] additional selectors to further narrow the element iterated over
302
+ # a "$" in this argument will be replaced with the default selector for the element being
303
+ # iterated over.
199
304
  # @param only [Symbol, Callable] the name of a method to call on an element or a
200
305
  # lambda or proc that accepts an element; elements will only be included in the
201
306
  # search results if the method or callable returns true
@@ -203,16 +308,21 @@ module Kitchen
203
308
  # lambda or proc that accepts an element; elements will not be included in the
204
309
  # search results if the method or callable returns false
205
310
  #
206
- def chain_to(enumerator_class, css_or_xpath: nil, only: nil, except: nil)
311
+ def chain_to(enumerator_class, default_css_or_xpath: nil, css_or_xpath: nil,
312
+ only: nil, except: nil)
207
313
  block_error_if(block_given?)
208
- enumerator_class.factory.build_within(
209
- self,
210
- search_query: SearchQuery.new(
211
- css_or_xpath: css_or_xpath,
212
- only: only,
213
- except: except
214
- )
314
+
315
+ search_query = SearchQuery.new(
316
+ css_or_xpath: css_or_xpath,
317
+ only: only,
318
+ except: except
215
319
  )
320
+
321
+ if default_css_or_xpath
322
+ search_query.apply_default_css_or_xpath_and_normalize(default_css_or_xpath)
323
+ end
324
+
325
+ enumerator_class.factory.build_within(self, search_query: search_query)
216
326
  end
217
327
 
218
328
  # Returns the first element in this enumerator
@@ -12,8 +12,11 @@ module Kitchen
12
12
 
13
13
  # Creates a new instance
14
14
  #
15
- # @param default_css_or_xpath [String] The selectors to substitute for the "$" character
16
- # when this factory is used to build an enumerator.
15
+ # @param default_css_or_xpath [String, Proc, Symbol] The selectors to substitute for the "$" character
16
+ # when this factory is used to build an enumerator. A string argument is used literally. A proc
17
+ # is eventually called given the document's Config object (for accessing selectors). A symbol
18
+ # is interpreted as the name of a selector and is called on the document's Config object's
19
+ # selectors object. The easiest way to get a Proc is to pass `Selector.named(:name_of_selector)`
17
20
  # @param sub_element_class [ElementBase] The element class to use for what the enumerator finds.
18
21
  # @param enumerator_class [ElementEnumeratorBase] The enumerator class to return
19
22
  # @param detect_sub_element_class [Boolean] If true, infers the sub_element_class from the node
@@ -36,14 +39,22 @@ module Kitchen
36
39
  # @return [ElementEnumeratorBase] actually returns the concrete enumerator class
37
40
  # given to the factory in its constructor.
38
41
  #
39
- def build_within(enumerator_or_element, search_query: SearchQuery.new)
40
- search_query.apply_default_css_or_xpath_and_normalize(default_css_or_xpath)
41
-
42
+ def build_within(enumerator_or_element, search_query: SearchQuery.new, reload: false)
42
43
  case enumerator_or_element
43
44
  when ElementBase
44
- build_within_element(enumerator_or_element, search_query: search_query)
45
+ build_within_element(enumerator_or_element,
46
+ search_query: search_query,
47
+ reload: reload)
45
48
  when ElementEnumeratorBase
46
- build_within_other_enumerator(enumerator_or_element, search_query: search_query)
49
+ if enumerator_class != ElementEnumerator && !search_query.expects_substitution?
50
+ raise "Query #{search_query} is missing the substitution character ('$') but " \
51
+ "is run with an enumerator #{enumerator_class.name} that has its own " \
52
+ "selectors for substitution."
53
+ end
54
+
55
+ build_within_other_enumerator(enumerator_or_element,
56
+ search_query: search_query,
57
+ reload: reload)
47
58
  end
48
59
  end
49
60
 
@@ -55,7 +66,7 @@ module Kitchen
55
66
  #
56
67
  def or_with(other_factory)
57
68
  self.class.new(
58
- default_css_or_xpath: "#{default_css_or_xpath}, #{other_factory.default_css_or_xpath}",
69
+ default_css_or_xpath: [default_css_or_xpath, other_factory.default_css_or_xpath],
59
70
  enumerator_class: TypeCastingElementEnumerator,
60
71
  detect_sub_element_class: true
61
72
  )
@@ -63,7 +74,10 @@ module Kitchen
63
74
 
64
75
  protected
65
76
 
66
- def build_within_element(element, search_query:)
77
+ def build_within_element(element, search_query:, reload:)
78
+ search_query.apply_default_css_or_xpath_and_normalize(default_css_or_xpath,
79
+ config: element.config)
80
+
67
81
  enumerator_class.new(search_query: search_query) do |block|
68
82
  grand_ancestors = element.ancestors
69
83
  parent_ancestor = Ancestor.new(element)
@@ -73,7 +87,7 @@ module Kitchen
73
87
  # below, the counts are correct.
74
88
  element.uncount(search_query)
75
89
 
76
- element.raw.search(*search_query.css_or_xpath).each do |sub_node|
90
+ element.raw_search(*search_query.css_or_xpath, reload: reload).each do |sub_node|
77
91
  sub_element = ElementFactory.build_from_node(
78
92
  node: sub_node,
79
93
  document: element.document,
@@ -101,13 +115,15 @@ module Kitchen
101
115
  end
102
116
  end
103
117
 
104
- def build_within_other_enumerator(other_enumerator, search_query:)
118
+ def build_within_other_enumerator(other_enumerator, search_query:, reload:)
105
119
  # Return a new enumerator instance that internally iterates over `other_enumerator`
106
120
  # running a new enumerator for each element returned by that other enumerator.
107
121
  enumerator_class.new(search_query: search_query,
108
122
  upstream_enumerator: other_enumerator) do |block|
109
123
  other_enumerator.each do |element|
110
- build_within_element(element, search_query: search_query).each do |sub_element|
124
+ build_within_element(element,
125
+ search_query: search_query,
126
+ reload: reload).each do |sub_element|
111
127
  block.yield(sub_element)
112
128
  end
113
129
  end
@@ -25,7 +25,7 @@ module Kitchen
25
25
  element_class: nil,
26
26
  default_short_type: nil,
27
27
  detect_element_class: false)
28
- element_class ||= detect_element_class ? specific_element_class_for_node(node) : Element
28
+ element_class ||= detect_element_class ? find_element_class(node, document.config) : Element
29
29
 
30
30
  if element_class == Element
31
31
  element_class.new(node: node,
@@ -37,9 +37,9 @@ module Kitchen
37
37
  end
38
38
  end
39
39
 
40
- def self.specific_element_class_for_node(node)
40
+ def self.find_element_class(node, config)
41
41
  ELEMENT_CLASSES.find do |klass|
42
- klass.is_the_element_class_for?(node)
42
+ klass.is_the_element_class_for?(node, config: config)
43
43
  end || Element
44
44
  end
45
45
 
@@ -13,8 +13,14 @@ module Kitchen
13
13
  def initialize(node:, document: nil)
14
14
  super(node: node,
15
15
  document: document,
16
- enumerator_class: ExampleElementEnumerator,
17
- short_type: :example)
16
+ enumerator_class: ExampleElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :example
18
24
  end
19
25
 
20
26
  # Returns the an enumerator for titles.
@@ -25,14 +31,5 @@ module Kitchen
25
31
  search("span[data-type='title']")
26
32
  end
27
33
 
28
- # Returns true if this class represents the element for the given node
29
- #
30
- # @param node [Nokogiri::XML::Node] the underlying node
31
- # @return [Boolean]
32
- #
33
- def self.is_the_element_class_for?(node)
34
- node['data-type'] == 'example'
35
- end
36
-
37
34
  end
38
35
  end
@@ -11,7 +11,7 @@ module Kitchen
11
11
  #
12
12
  def self.factory
13
13
  ElementEnumeratorFactory.new(
14
- default_css_or_xpath: "div[data-type='example']", # TODO: element.document.selectors.example
14
+ default_css_or_xpath: Selector.named(:example),
15
15
  sub_element_class: ExampleElement,
16
16
  enumerator_class: self
17
17
  )
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ # An element for an example
5
+ #
6
+ class ExerciseElement < ElementBase
7
+
8
+ # Creates a new +ExerciseElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
13
+ def initialize(node:, document: nil)
14
+ super(node: node,
15
+ document: document,
16
+ enumerator_class: ExerciseElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :exercise
24
+ end
25
+
26
+ # Returns the enumerator for problem.
27
+ #
28
+ # @return ElementEnumerator
29
+ #
30
+ def problem
31
+ first("div[data-type='problem']")
32
+ end
33
+
34
+ # Returns the enumerator for solution.
35
+ #
36
+ # @return ElementEnumerator
37
+ #
38
+ def solution
39
+ first("div[data-type='solution']")
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ # An enumerator for example elements
5
+ #
6
+ class ExerciseElementEnumerator < ElementEnumeratorBase
7
+
8
+ # Returns a factory for this enumerator
9
+ #
10
+ # @return [ElementEnumeratorFactory]
11
+ #
12
+ def self.factory
13
+ ElementEnumeratorFactory.new(
14
+ default_css_or_xpath: Selector.named(:exercise),
15
+ sub_element_class: ExerciseElement,
16
+ enumerator_class: self
17
+ )
18
+ end
19
+
20
+ end
21
+ end
@@ -13,8 +13,14 @@ module Kitchen
13
13
  def initialize(node:, document: nil)
14
14
  super(node: node,
15
15
  document: document,
16
- enumerator_class: FigureElementEnumerator,
17
- short_type: :figure)
16
+ enumerator_class: FigureElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :figure
18
24
  end
19
25
 
20
26
  # Returns the caption element
@@ -41,14 +47,5 @@ module Kitchen
41
47
  parent.name == 'figure'
42
48
  end
43
49
 
44
- # Returns true if this class represents the element for the given node
45
- #
46
- # @param node [Nokogiri::XML::Node] the underlying node
47
- # @return [Boolean]
48
- #
49
- def self.is_the_element_class_for?(node)
50
- node.name == 'figure'
51
- end
52
-
53
50
  end
54
51
  end
@@ -11,7 +11,7 @@ module Kitchen
11
11
  #
12
12
  def self.factory
13
13
  ElementEnumeratorFactory.new(
14
- default_css_or_xpath: 'figure', # TODO: get from config?
14
+ default_css_or_xpath: Selector.named(:figure),
15
15
  sub_element_class: FigureElement,
16
16
  enumerator_class: self
17
17
  )
@@ -12,8 +12,14 @@ module Kitchen
12
12
  def initialize(node:, document: nil)
13
13
  super(node: node,
14
14
  document: document,
15
- enumerator_class: MetadataElementEnumerator,
16
- short_type: :metadata)
15
+ enumerator_class: MetadataElementEnumerator)
16
+ end
17
+
18
+ # Returns the short type
19
+ # @return [Symbol]
20
+ #
21
+ def self.short_type
22
+ :metadata
17
23
  end
18
24
 
19
25
  # Returns set of selected data elements
@@ -11,7 +11,7 @@ module Kitchen
11
11
  #
12
12
  def self.factory
13
13
  ElementEnumeratorFactory.new(
14
- default_css_or_xpath: "div[data-type='metadata']",
14
+ default_css_or_xpath: Selector.named(:metadata),
15
15
  sub_element_class: MetadataElement,
16
16
  enumerator_class: self
17
17
  )
@@ -5,13 +5,6 @@ module Kitchen
5
5
  #
6
6
  class NoteElement < ElementBase
7
7
 
8
- TITLE_TRANSLATION_KEYS = %w[
9
- link-to-learning
10
- everyday-life
11
- sciences-interconnect
12
- chemist-portrait
13
- ].freeze
14
-
15
8
  # Creates a new +NoteElement+
16
9
  #
17
10
  # @param node [Nokogiri::XML::Node] the node this element wraps
@@ -20,8 +13,14 @@ module Kitchen
20
13
  def initialize(node:, document: nil)
21
14
  super(node: node,
22
15
  document: document,
23
- enumerator_class: NoteElementEnumerator,
24
- short_type: :note)
16
+ enumerator_class: NoteElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :note
25
24
  end
26
25
 
27
26
  # Returns the note's title element
@@ -38,7 +37,7 @@ module Kitchen
38
37
  # @return [Boolean]
39
38
  #
40
39
  def indicates_autogenerated_title?
41
- translation_key_in(TITLE_TRANSLATION_KEYS).present?
40
+ detected_note_title_key != 0 && detected_note_title_key.present?
42
41
  end
43
42
 
44
43
  # Get the autogenerated title for this note
@@ -46,28 +45,27 @@ module Kitchen
46
45
  # @return [String]
47
46
  #
48
47
  def autogenerated_title
49
- translation_key = translation_key_in(TITLE_TRANSLATION_KEYS)
50
- I18n.t(:"notes.#{document.short_name}.#{translation_key}",
51
- default: :"notes.#{translation_key}")
52
- end
53
-
54
- # Returns true if this class represents the element for the given node
55
- #
56
- # @param node [Nokogiri::XML::Node] the underlying node
57
- # @return [Boolean]
58
- #
59
- def self.is_the_element_class_for?(node)
60
- node['data-type'] == 'note'
48
+ if indicates_autogenerated_title?
49
+ I18n.t(:"notes.#{detected_note_title_key}")
50
+ else
51
+ "unknown title for note with classes #{classes}"
52
+ end
61
53
  end
62
54
 
63
55
  protected
64
56
 
65
- def translation_key_in(possible_translation_keys)
66
- keys = possible_translation_keys & classes
67
- raise("too many translation keys: #{keys.join(', ')}") if keys.many?
57
+ def detected_note_title_key
58
+ @detected_note_title_key ||= begin
59
+ return 0 if classes.empty? || !I18n.t('.').key?(:notes)
68
60
 
69
- keys.first
70
- end
61
+ possible_keys = I18n.t(:notes).keys.map(&:to_s)
62
+ keys = possible_keys & classes
63
+
64
+ raise("too many translation keys: #{keys.join(', ')}") if keys.many?
65
+ return 0 if keys.empty?
71
66
 
67
+ keys.first
68
+ end
69
+ end
72
70
  end
73
71
  end