openstax_kitchen 2.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +37 -17
  3. data/.github/config.yml +14 -0
  4. data/.github/workflows/tests.yml +5 -15
  5. data/.gitignore +2 -2
  6. data/.inch.yml +6 -0
  7. data/.rubocop.yml +65 -0
  8. data/CHANGELOG.md +85 -1
  9. data/Gemfile +5 -3
  10. data/Gemfile.lock +65 -17
  11. data/README.md +65 -11
  12. data/Rakefile +5 -3
  13. data/bin/console +4 -3
  14. data/docker/Dockerfile +36 -0
  15. data/docker/Dockerfile.ci +10 -0
  16. data/docker/bash +5 -1
  17. data/docker/build +10 -0
  18. data/docker/ci +15 -0
  19. data/docker/run +9 -0
  20. data/docker/tag_and_push_latest +17 -0
  21. data/lefthook.yml +6 -0
  22. data/lib/kitchen/ancestor.rb +38 -1
  23. data/lib/kitchen/book_document.rb +20 -2
  24. data/lib/kitchen/book_element.rb +40 -5
  25. data/lib/kitchen/book_element_enumerator.rb +4 -0
  26. data/lib/kitchen/book_recipe.rb +15 -1
  27. data/lib/kitchen/chapter_element.rb +43 -6
  28. data/lib/kitchen/chapter_element_enumerator.rb +9 -1
  29. data/lib/kitchen/clipboard.rb +35 -4
  30. data/lib/kitchen/composite_chapter_element.rb +21 -6
  31. data/lib/kitchen/composite_page_element.rb +35 -7
  32. data/lib/kitchen/composite_page_element_enumerator.rb +9 -1
  33. data/lib/kitchen/config.rb +20 -6
  34. data/lib/kitchen/counter.rb +9 -2
  35. data/lib/kitchen/debug/print_recipe_error.rb +53 -35
  36. data/lib/kitchen/directions/.rubocop.yml +22 -0
  37. data/lib/kitchen/directions/bake_appendix.rb +4 -4
  38. data/lib/kitchen/directions/bake_chapter_glossary/main.rb +18 -0
  39. data/lib/kitchen/directions/bake_chapter_glossary/v1.rb +30 -0
  40. data/lib/kitchen/directions/bake_chapter_introductions.rb +7 -7
  41. data/lib/kitchen/directions/bake_chapter_key_concepts/main.rb +16 -0
  42. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +35 -0
  43. data/lib/kitchen/directions/bake_chapter_key_equations.rb +30 -20
  44. data/lib/kitchen/directions/bake_chapter_references/main.rb +16 -0
  45. data/lib/kitchen/directions/bake_chapter_references/v1.rb +35 -0
  46. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +11 -0
  47. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +28 -0
  48. data/lib/kitchen/directions/bake_chapter_summary.rb +45 -36
  49. data/lib/kitchen/directions/bake_chapter_title/main.rb +11 -0
  50. data/lib/kitchen/directions/bake_chapter_title/v1.rb +24 -0
  51. data/lib/kitchen/directions/bake_checkpoint.rb +44 -0
  52. data/lib/kitchen/directions/bake_composite_chapters.rb +14 -0
  53. data/lib/kitchen/directions/bake_composite_pages.rb +2 -2
  54. data/lib/kitchen/directions/bake_equations.rb +37 -0
  55. data/lib/kitchen/directions/bake_example.rb +39 -11
  56. data/lib/kitchen/directions/bake_figure.rb +8 -5
  57. data/lib/kitchen/directions/bake_first_elements.rb +16 -0
  58. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  59. data/lib/kitchen/directions/bake_footnotes/v1.rb +6 -5
  60. data/lib/kitchen/directions/bake_free_response/free_response.xhtml.erb +10 -0
  61. data/lib/kitchen/directions/bake_free_response/main.rb +11 -0
  62. data/lib/kitchen/directions/bake_free_response/v1.rb +29 -0
  63. data/lib/kitchen/directions/bake_further_research.rb +59 -0
  64. data/lib/kitchen/directions/bake_index/main.rb +2 -2
  65. data/lib/kitchen/directions/bake_index/v1.rb +46 -18
  66. data/lib/kitchen/directions/bake_link_placeholders.rb +24 -0
  67. data/lib/kitchen/directions/bake_math_in_paragraph.rb +5 -3
  68. data/lib/kitchen/directions/bake_non_introduction_pages.rb +26 -0
  69. data/lib/kitchen/directions/bake_notes/bake_autotitled_notes.rb +29 -0
  70. data/lib/kitchen/directions/bake_notes/bake_note_subtitle.rb +22 -0
  71. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +51 -0
  72. data/lib/kitchen/directions/bake_notes/bake_unclassified_notes.rb +30 -0
  73. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +15 -0
  74. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +47 -0
  75. data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -4
  76. data/lib/kitchen/directions/bake_numbered_table/v1.rb +37 -18
  77. data/lib/kitchen/directions/bake_page_abstracts.rb +30 -0
  78. data/lib/kitchen/directions/bake_preface/main.rb +11 -0
  79. data/lib/kitchen/directions/bake_preface/v1.rb +18 -0
  80. data/lib/kitchen/directions/bake_references/main.rb +16 -0
  81. data/lib/kitchen/directions/bake_references/v1.rb +48 -0
  82. data/lib/kitchen/directions/bake_stepwise.rb +8 -12
  83. data/lib/kitchen/directions/bake_suggested_reading.rb +31 -0
  84. data/lib/kitchen/directions/bake_theorem/main.rb +11 -0
  85. data/lib/kitchen/directions/bake_theorem/v1.rb +28 -0
  86. data/lib/kitchen/directions/bake_toc.rb +49 -22
  87. data/lib/kitchen/directions/bake_unit_title/main.rb +11 -0
  88. data/lib/kitchen/directions/bake_unit_title/v1.rb +23 -0
  89. data/lib/kitchen/directions/bake_unnumbered_tables.rb +7 -5
  90. data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +9 -0
  91. data/lib/kitchen/directions/book_answer_key_container/main.rb +11 -0
  92. data/lib/kitchen/directions/book_answer_key_container/v1.rb +13 -0
  93. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +9 -0
  94. data/lib/kitchen/directions/chapter_review_container/main.rb +11 -0
  95. data/lib/kitchen/directions/chapter_review_container/v1.rb +13 -0
  96. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +20 -0
  97. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +27 -0
  98. data/lib/kitchen/directions/move_exercises_to_eoc/v1.rb +36 -0
  99. data/lib/kitchen/directions/move_exercises_to_eoc/v2.rb +49 -0
  100. data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +14 -0
  101. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +19 -0
  102. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/calculus.rb +41 -0
  103. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/uphysics.rb +63 -0
  104. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +34 -0
  105. data/lib/kitchen/directions/move_title_text_into_span.rb +2 -2
  106. data/lib/kitchen/document.rb +83 -13
  107. data/lib/kitchen/element.rb +20 -3
  108. data/lib/kitchen/element_base.rb +373 -63
  109. data/lib/kitchen/element_enumerator.rb +8 -0
  110. data/lib/kitchen/element_enumerator_base.rb +297 -28
  111. data/lib/kitchen/element_enumerator_factory.rb +64 -53
  112. data/lib/kitchen/element_factory.rb +27 -12
  113. data/lib/kitchen/errors.rb +5 -0
  114. data/lib/kitchen/example_element.rb +21 -6
  115. data/lib/kitchen/example_element_enumerator.rb +9 -1
  116. data/lib/kitchen/exercise_element.rb +42 -0
  117. data/lib/kitchen/exercise_element_enumerator.rb +21 -0
  118. data/lib/kitchen/figure_element.rb +36 -5
  119. data/lib/kitchen/figure_element_enumerator.rb +9 -1
  120. data/lib/kitchen/metadata_element.rb +34 -0
  121. data/lib/kitchen/metadata_element_enumerator.rb +21 -0
  122. data/lib/kitchen/mixins/block_error_if.rb +24 -4
  123. data/lib/kitchen/note_element.rb +48 -20
  124. data/lib/kitchen/note_element_enumerator.rb +9 -1
  125. data/lib/kitchen/oven.rb +66 -15
  126. data/lib/kitchen/page_element.rb +84 -14
  127. data/lib/kitchen/page_element_enumerator.rb +9 -1
  128. data/lib/kitchen/pantry.rb +28 -1
  129. data/lib/kitchen/patches/nokogiri.rb +59 -2
  130. data/lib/kitchen/patches/renderable.rb +9 -3
  131. data/lib/kitchen/patches/string.rb +8 -0
  132. data/lib/kitchen/recipe.rb +69 -32
  133. data/lib/kitchen/reference_element.rb +27 -0
  134. data/lib/kitchen/references_element_enumerator.rb +20 -0
  135. data/lib/kitchen/search_history.rb +43 -4
  136. data/lib/kitchen/search_query.rb +106 -0
  137. data/lib/kitchen/selector.rb +24 -0
  138. data/lib/kitchen/selectors/base.rb +65 -0
  139. data/lib/kitchen/selectors/standard_1.rb +21 -0
  140. data/lib/kitchen/table_element.rb +55 -7
  141. data/lib/kitchen/table_element_enumerator.rb +9 -1
  142. data/lib/kitchen/templates/eob_section_title_template.xhtml.erb +10 -0
  143. data/lib/kitchen/templates/eoc_section_title_template.xhtml.erb +10 -0
  144. data/lib/kitchen/term_element.rb +15 -4
  145. data/lib/kitchen/term_element_enumerator.rb +9 -1
  146. data/lib/kitchen/transliterations.rb +7 -5
  147. data/lib/kitchen/type_casting_element_enumerator.rb +17 -1
  148. data/lib/kitchen/unit_element.rb +45 -0
  149. data/lib/kitchen/unit_element_enumerator.rb +20 -0
  150. data/lib/kitchen/utils.rb +10 -13
  151. data/lib/kitchen/version.rb +5 -1
  152. data/lib/locales/en.yml +18 -7
  153. data/lib/locales/pl.yml +24 -0
  154. data/lib/openstax_kitchen.rb +44 -42
  155. data/openstax_kitchen.gemspec +26 -20
  156. data/tutorials/00/solution1.rb +9 -0
  157. data/tutorials/00/solution2.rb +8 -0
  158. data/tutorials/01/solution1.rb +18 -0
  159. data/tutorials/01/solution2.rb +26 -0
  160. data/tutorials/02/solution1.rb +31 -0
  161. data/tutorials/03/{solution_1.rb → solution1.rb} +6 -4
  162. data/tutorials/03/solution2.rb +18 -0
  163. data/tutorials/04/{solution_1.rb → solution1.rb} +4 -2
  164. data/tutorials/04/{solution_2.rb → solution2.rb} +6 -4
  165. data/tutorials/05/solution1.rb +11 -0
  166. data/tutorials/check_it +16 -15
  167. data/tutorials/setup_my_recipes +7 -6
  168. metadata +149 -24
  169. data/Dockerfile +0 -19
  170. data/docker-compose.yml +0 -12
  171. data/docker/entrypoint +0 -9
  172. data/lib/kitchen/directions/bake_chapter_glossary.rb +0 -34
  173. data/lib/kitchen/directions/bake_exercises.rb +0 -164
  174. data/lib/kitchen/directions/bake_notes.rb +0 -58
  175. data/tutorials/00/solution_1.rb +0 -7
  176. data/tutorials/00/solution_2.rb +0 -6
  177. data/tutorials/01/solution_1.rb +0 -16
  178. data/tutorials/01/solution_2.rb +0 -24
  179. data/tutorials/02/solution_1.rb +0 -29
  180. data/tutorials/03/solution_2.rb +0 -15
  181. data/tutorials/05/solution_1.rb +0 -9
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An enumerator for book elements
5
+ #
2
6
  class BookElementEnumerator < ElementEnumeratorBase
3
7
  # Unsure if this class is needed; there is only one book element per document
4
8
  end
@@ -1,17 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # A specialized +Recipe+ that yields a +BookDocument+ instead of a plain
5
+ # +Document+
6
+ #
2
7
  class BookRecipe < Recipe
3
8
 
9
+ # The book's short name
10
+ #
11
+ # @return [Symbol]
12
+ #
4
13
  attr_reader :book_short_name
5
14
 
6
15
  # Make a new BookRecipe
7
16
  #
17
+ # @param book_short_name [Symbol, String] the book's short name
8
18
  # @yieldparam doc [BookDocument] an object representing an XML document
9
19
  #
10
20
  def initialize(book_short_name: :not_set, &block)
11
- @book_short_name = book_short_name
21
+ @book_short_name = book_short_name.to_sym
12
22
  super(&block)
13
23
  end
14
24
 
25
+ # Overrides +document=+ to ensure a +BookDocument+ is stored
26
+ #
27
+ # @param document [Document, Nokogiri::XML::Document] the document
28
+ #
15
29
  def document=(document)
16
30
  super(document)
17
31
  @document = Kitchen::BookDocument.new(
@@ -1,34 +1,71 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An element for a chapter
5
+ #
2
6
  class ChapterElement < ElementBase
3
7
 
8
+ # Creates a new +ChapterElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
4
13
  def initialize(node:, document: nil)
5
14
  super(node: node,
6
15
  document: document,
7
- enumerator_class: ChapterElementEnumerator,
8
- short_type: :chapter)
16
+ enumerator_class: ChapterElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :chapter
9
24
  end
10
25
 
26
+ # Returns the title element (the one in the immediate children, not the one in the metadata)
27
+ #
28
+ # @raise [ElementNotFoundError] if no matching element is found
29
+ # @return [Element]
30
+ #
11
31
  def title
12
32
  # Get the title in the immediate children, not the one in the metadata. Could use
13
- # CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
33
+ # CSS of ":not([data-type='metadata']) >
34
+ # [data-type='document-title'], [data-type='document-title']"
14
35
  # but xpath is shorter
15
36
  first!("./*[@data-type = 'document-title']")
16
37
  end
17
38
 
39
+ # Returns the introduction page
40
+ #
41
+ # @return [Element, nil]
42
+ #
18
43
  def introduction_page
19
44
  pages('.introduction').first
20
45
  end
21
46
 
47
+ # Returns an enumerator for the glossaries
48
+ #
49
+ # @return [ElementEnumerator]
50
+ #
22
51
  def glossaries
23
52
  search("div[data-type='glossary']")
24
53
  end
25
54
 
55
+ # Returns an enumerator for the key equations
56
+ #
57
+ # @return [ElementEnumerator]
58
+ #
26
59
  def key_equations
27
- search("section.key-equations")
60
+ search('section.key-equations')
28
61
  end
29
62
 
30
- def self.is_the_element_class_for?(node)
31
- node['data-type'] == "chapter"
63
+ # Returns an enumerator for the abstracts
64
+ #
65
+ # @return [ElementEnumerator]
66
+ #
67
+ def abstracts
68
+ search('[data-type="abstract"]')
32
69
  end
33
70
 
34
71
  end
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An enumerator for chapter elements
5
+ #
2
6
  class ChapterElementEnumerator < ElementEnumeratorBase
3
7
 
8
+ # Returns a factory for this enumerator
9
+ #
10
+ # @return [ElementEnumeratorFactory]
11
+ #
4
12
  def self.factory
5
13
  ElementEnumeratorFactory.new(
6
- default_css_or_xpath: "div[data-type='chapter']", # TODO element.document.selectors.chapter
14
+ default_css_or_xpath: Selector.named(:chapter),
7
15
  sub_element_class: ChapterElement,
8
16
  enumerator_class: self
9
17
  )
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
2
4
  # A place to store lists of things during recipe work. Essentially a
3
5
  # slightly fancy array.
@@ -5,33 +7,62 @@ module Kitchen
5
7
  class Clipboard
6
8
  include Enumerable
7
9
 
8
- attr_reader :items
10
+ # The underlying array
11
+ # @return [Array<ElementBase>]
12
+ #
13
+ def items
14
+ @items.clone
15
+ end
9
16
 
17
+ # Creates a new +Clipboard+
18
+ #
10
19
  def initialize
11
20
  clear
12
21
  end
13
22
 
23
+ # Add an element to the clipboard
24
+ #
25
+ # @param item [ElementBase]
26
+ #
14
27
  def add(item)
15
28
  @items.push(item)
29
+ self
16
30
  end
17
31
 
32
+ # Clears the clipboard
33
+ #
18
34
  def clear
19
35
  @items = []
36
+ self
20
37
  end
21
38
 
39
+ # Returns a concatenation of the pasting of each item on the clipboard
40
+ # @return [String]
41
+ #
22
42
  def paste
23
- @items.map(&:paste).join("")
43
+ @items.map(&:paste).join('')
24
44
  end
25
45
 
46
+ # Iterates over each item on the clipboard
47
+ # @yield each item
48
+ # @return [Clipboard] self
49
+ #
26
50
  def each(&block)
27
- @items.each do |item|
28
- block.call(item)
51
+ if block_given?
52
+ @items.each do |item|
53
+ block.call(item)
54
+ end
29
55
  end
30
56
  self
31
57
  end
32
58
 
59
+ # Sorts the clipboard using the provided block
60
+ # @yield each item
61
+ # @return [Clipboard] self
62
+ #
33
63
  def sort_by!(&block)
34
64
  @items.sort_by!(&block)
65
+ self
35
66
  end
36
67
  end
37
68
  end
@@ -1,13 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An element for a composite chapter
5
+ #
2
6
  class CompositeChapterElement < ElementBase
3
7
 
8
+ # Creates a new +CompositeChapterElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
4
13
  def initialize(node:, document: nil)
5
14
  super(node: node,
6
15
  document: document,
7
- enumerator_class: ElementEnumerator,
8
- short_type: :composite_chapter)
16
+ enumerator_class: ElementEnumerator)
17
+ end
18
+
19
+ # Returns short type
20
+ #
21
+ def self.short_type
22
+ :composite_chapter
9
23
  end
10
24
 
25
+ # Returns the title element (the one in the immediate children, not the one in the metadata)
26
+ #
27
+ # @raise [ElementNotFoundError] if no matching element is found
28
+ # @return [Element]
29
+ #
11
30
  def title
12
31
  # Get the title in the immediate children, not the one in the metadata. Could use
13
32
  # CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
@@ -15,9 +34,5 @@ module Kitchen
15
34
  first!("./*[@data-type = 'document-title']")
16
35
  end
17
36
 
18
- def self.is_the_element_class_for?(node)
19
- node['data-type'] == "composite-chapter"
20
- end
21
-
22
37
  end
23
38
  end
@@ -1,26 +1,54 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An element for a composite page
5
+ #
2
6
  class CompositePageElement < ElementBase
3
7
 
8
+ # Creates a new +CompositePageElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
4
13
  def initialize(node:, document: nil)
5
14
  super(node: node,
6
15
  document: document,
7
- enumerator_class: CompositePageElementEnumerator,
8
- short_type: :composite_page)
16
+ enumerator_class: CompositePageElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :composite_page
9
24
  end
10
25
 
26
+ # Returns the title element (the one in the immediate children, not the one in the metadata)
27
+ #
28
+ # @raise [ElementNotFoundError] if no matching element is found
29
+ # @return [Element]
30
+ #
11
31
  def title
12
32
  # Get the title in the immediate children, not the one in the metadata. Could use
13
33
  # CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
14
34
  # but xpath is shorter
15
- first!("./*[@data-type = 'document-title']")
35
+ first!("./*[@data-type = 'document-title' or @data-type = 'title']")
16
36
  end
17
37
 
18
- def self.is_the_element_class_for?(node)
19
- node['data-type'] == "composite-page"
38
+ # Returns true if this page is a book index
39
+ #
40
+ # @return [Boolean]
41
+ #
42
+ def is_index?
43
+ has_class?('os-index-container')
20
44
  end
21
45
 
22
- def is_index?
23
- has_class?("os-index-container")
46
+ # Returns true if this page is a book reference
47
+ #
48
+ # @return [Boolean]
49
+ #
50
+ def is_reference?
51
+ has_class?('os-reference-container')
24
52
  end
25
53
 
26
54
  end
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An enumerator for composite page elements
5
+ #
2
6
  class CompositePageElementEnumerator < ElementEnumeratorBase
3
7
 
8
+ # Returns a factory for this enumerator
9
+ #
10
+ # @return [ElementEnumeratorFactory]
11
+ #
4
12
  def self.factory
5
13
  ElementEnumeratorFactory.new(
6
- default_css_or_xpath: "div[data-type='composite-page']",
14
+ default_css_or_xpath: Selector.named(:composite_page),
7
15
  sub_element_class: CompositePageElement,
8
16
  enumerator_class: self
9
17
  )
@@ -1,20 +1,34 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # Kitchen configuration
5
+ #
2
6
  class Config
3
7
 
8
+ # Named CSS or XPath selectors
9
+ #
10
+ # @return [Selectors::Base]
11
+ #
4
12
  attr_reader :selectors
5
13
 
6
- def self.new_from_file(file)
7
- raise "NYI"
8
- end
14
+ # @!attribute [rw] enable_all_namespaces
15
+ #
16
+ # @return [Boolean]
17
+ #
18
+ attr_accessor :enable_all_namespaces
9
19
 
10
- def self.new_default
11
- new
20
+ # Creates a new config from a file (not implemented)
21
+ #
22
+ def self.new_from_file(_file)
23
+ raise 'NYI'
12
24
  end
13
25
 
26
+ # Creates a new Config instance
27
+ #
14
28
  def initialize(hash: {}, selectors: nil)
15
29
  @selectors = selectors || Kitchen::Selectors::Standard1.new
30
+ @enable_all_namespaces = hash[:enable_all_namespaces] || true
16
31
  @hash = hash
17
32
  end
18
-
19
33
  end
20
34
  end
@@ -1,6 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
2
- class Counter # hehe
4
+ # A simple counting object
5
+ #
6
+ # hehe
7
+ class Counter
3
8
 
9
+ # Creates a new +Counter+ instance
4
10
  def initialize
5
11
  reset
6
12
  end
@@ -13,7 +19,8 @@ module Kitchen
13
19
  @value += by
14
20
  end
15
21
 
16
- # (see #increment)
22
+ # @!method inc
23
+ # @see increment
17
24
  alias_method :inc, :increment
18
25
 
19
26
  # Returns the value of the counter
@@ -1,63 +1,82 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rainbow'
2
4
 
3
5
  module Kitchen
6
+ # Debug helpers
4
7
  module Debug
5
-
6
8
  CONTEXT_LINES = 2
7
9
 
8
10
  def self.print_recipe_error(error:, source_location:, document:)
9
- error_location = error.backtrace.detect do |entry|
10
- entry.start_with?(source_location) || entry.match?(/kitchen\/lib\/kitchen\/directions/)
11
- end
11
+ print_error_message(error)
12
12
 
13
- error_filename, error_line_number = error_location.match(/(.*):(\d+):/)[1..2]
14
- error_line_number = error_line_number.to_i
13
+ error_line_number, error_filename = get_error_location(error, source_location)
14
+ print_file_line_with_context(error_line_number, error_filename)
15
15
 
16
- puts "The recipe has an error: " + Rainbow(error.message).bright
17
- puts "at or near the following #{Rainbow('highlighted').red} line"
18
16
  puts "\n"
19
- puts "-----+ #{Rainbow(error_filename).bright} -----"
20
17
 
21
- line_numbers_before = (error_line_number-CONTEXT_LINES..error_line_number-1)
22
- line_numbers_after = (error_line_number+1..error_line_number+CONTEXT_LINES)
18
+ print_specific_help_line(error)
19
+ print_line_in_document_where_error_occurred(document)
20
+ print_backtrace_info(error)
21
+ end
23
22
 
24
- File.readlines(error_filename).each.with_index do |line, line_index|
25
- line_number = line_index + 1
23
+ def self.verbose?
24
+ !ENV['VERBOSE'].nil?
25
+ end
26
26
 
27
- if line_numbers_before.include?(line_number) ||
28
- line_numbers_after.include?(line_number)
29
- print_file_line(line_number, line)
30
- end
27
+ def self.print_error_message(error)
28
+ puts "The recipe has an error: #{Rainbow(error.message).bright}"
29
+ end
31
30
 
32
- if line_number == error_line_number
33
- print_file_line(line_number, Rainbow(line.chomp).red)
34
- end
31
+ def self.print_backtrace_info(error)
32
+ if verbose?
33
+ puts "Full backtrace:\n"
34
+ puts(error.backtrace.map { |line| Rainbow(line).blue })
35
+ else
36
+ puts 'Full backtrace suppressed; enable by setting the VERBOSE env variable to something'
35
37
  end
38
+ end
36
39
 
40
+ def self.print_line_in_document_where_error_occurred(document)
41
+ current_node = document&.location&.raw
42
+ return unless current_node
43
+
44
+ puts "Encountered on line #{Rainbow(current_node.line).red} in the input document on element:"
45
+ puts current_node.dup.tap { |node| node.inner_html = '...' if node.inner_html != '' }.to_s
37
46
  puts "\n"
47
+ end
38
48
 
39
- print_specific_help_line(error)
49
+ def self.print_file_line_with_context(line_number, filename)
50
+ puts "at or near the following #{Rainbow('highlighted').red} line"
51
+ puts "\n"
52
+ puts "-----+ #{Rainbow(filename).bright} -----"
40
53
 
41
- current_node = document.location&.raw
54
+ line_numbers_before = (line_number - CONTEXT_LINES..line_number - 1)
55
+ line_numbers_after = (line_number + 1..line_number + CONTEXT_LINES)
42
56
 
43
- if current_node
44
- puts "Encountered on line #{Rainbow(current_node.line).red} in the input document on element:"
45
- puts current_node.dup.tap{|node| node.inner_html="..." if node.inner_html != ""}.to_s
46
- puts "\n"
47
- end
57
+ File.readlines(filename).each.with_index do |line, line_index|
58
+ current_line_number = line_index + 1
48
59
 
49
- if ENV['VERBOSE']
50
- puts "Full backtrace:\n"
51
- puts error.backtrace.map{|line| Rainbow(line).blue}
52
- else
53
- puts "Full backtrace suppressed (enable by setting the VERBOSE environment variable to something)"
60
+ if line_numbers_before.include?(current_line_number) ||
61
+ line_numbers_after.include?(current_line_number)
62
+ print_file_line(current_line_number, line)
63
+ elsif current_line_number == line_number
64
+ print_file_line(current_line_number, Rainbow(line.chomp).red)
65
+ end
54
66
  end
55
67
  end
56
68
 
57
- protected
69
+ def self.get_error_location(error, source_location)
70
+ error_location = error.backtrace.detect do |entry|
71
+ entry.start_with?(source_location) || entry.match?(/kitchen\/lib\/kitchen\/directions/)
72
+ end
73
+
74
+ error_filename, error_line_number = error_location.match(/(.*):(\d+):/)[1..2]
75
+ [error_line_number.to_i, error_filename]
76
+ end
58
77
 
59
78
  def self.print_file_line(line_number, line)
60
- puts "#{"%5s" % line_number}| #{line}"
79
+ puts "#{format('%5s', line_number)}| #{line}"
61
80
  end
62
81
 
63
82
  def self.print_specific_help_line(error)
@@ -75,6 +94,5 @@ module Kitchen
75
94
  # puts "\n"
76
95
  # end
77
96
  end
78
-
79
97
  end
80
98
  end