openstax_kitchen 3.2.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/changelog.yml +27 -0
  3. data/.github/workflows/rubocop.yml +28 -0
  4. data/.gitignore +1 -1
  5. data/CHANGELOG.md +94 -1
  6. data/Gemfile.lock +26 -18
  7. data/README.md +16 -0
  8. data/codecov.yaml +1 -0
  9. data/docker/ci +0 -1
  10. data/docker/rubocop +22 -0
  11. data/lib/kitchen/book_document.rb +1 -1
  12. data/lib/kitchen/book_element.rb +16 -2
  13. data/lib/kitchen/chapter_element.rb +10 -13
  14. data/lib/kitchen/chapter_element_enumerator.rb +1 -1
  15. data/lib/kitchen/composite_chapter_element.rb +7 -11
  16. data/lib/kitchen/composite_chapter_element_enumerator.rb +21 -0
  17. data/lib/kitchen/composite_page_element.rb +15 -10
  18. data/lib/kitchen/composite_page_element_enumerator.rb +1 -1
  19. data/lib/kitchen/config.rb +14 -0
  20. data/lib/kitchen/directions/bake_appendix.rb +3 -1
  21. data/lib/kitchen/directions/bake_chapter_glossary/main.rb +18 -0
  22. data/lib/kitchen/directions/bake_chapter_glossary/v1.rb +30 -0
  23. data/lib/kitchen/directions/bake_chapter_introductions.rb +23 -16
  24. data/lib/kitchen/directions/bake_chapter_introductions/chapter_introduction.xhtml.erb +0 -0
  25. data/lib/kitchen/directions/bake_chapter_key_concepts/main.rb +7 -2
  26. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +12 -7
  27. data/lib/kitchen/directions/bake_chapter_key_equations.rb +26 -21
  28. data/lib/kitchen/directions/bake_chapter_references/main.rb +16 -0
  29. data/lib/kitchen/directions/bake_chapter_references/v1.rb +35 -0
  30. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +2 -2
  31. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +2 -1
  32. data/lib/kitchen/directions/bake_chapter_solutions/main.rb +11 -0
  33. data/lib/kitchen/directions/bake_chapter_solutions/v1.rb +37 -0
  34. data/lib/kitchen/directions/bake_chapter_summary.rb +56 -43
  35. data/lib/kitchen/directions/bake_composite_chapters.rb +1 -1
  36. data/lib/kitchen/directions/bake_composite_pages.rb +1 -1
  37. data/lib/kitchen/directions/bake_equations.rb +2 -2
  38. data/lib/kitchen/directions/bake_example.rb +8 -1
  39. data/lib/kitchen/directions/bake_figure.rb +14 -1
  40. data/lib/kitchen/directions/bake_first_elements.rb +22 -0
  41. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  42. data/lib/kitchen/directions/bake_footnotes/v1.rb +13 -9
  43. data/lib/kitchen/directions/bake_free_response/free_response.xhtml.erb +10 -0
  44. data/lib/kitchen/directions/{bake_chapter_review → bake_free_response}/main.rb +3 -3
  45. data/lib/kitchen/directions/bake_free_response/v1.rb +29 -0
  46. data/lib/kitchen/directions/bake_further_research.rb +61 -0
  47. data/lib/kitchen/directions/bake_index/v1.rb +36 -26
  48. data/lib/kitchen/directions/bake_link_placeholders.rb +1 -1
  49. data/lib/kitchen/directions/bake_notes/bake_note_subtitle.rb +4 -0
  50. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/main.rb +43 -0
  51. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v1.rb +37 -0
  52. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v2.rb +25 -0
  53. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v3.rb +32 -0
  54. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +7 -2
  55. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +34 -12
  56. data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +29 -0
  57. data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -0
  58. data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -24
  59. data/lib/kitchen/directions/bake_numbered_table/v2.rb +31 -0
  60. data/lib/kitchen/directions/bake_page_abstracts.rb +1 -1
  61. data/lib/kitchen/directions/bake_preface/main.rb +2 -2
  62. data/lib/kitchen/directions/bake_preface/v1.rb +3 -2
  63. data/lib/kitchen/directions/bake_references/main.rb +16 -0
  64. data/lib/kitchen/directions/bake_references/v1.rb +48 -0
  65. data/lib/kitchen/directions/bake_suggested_reading.rb +5 -0
  66. data/lib/kitchen/directions/bake_toc.rb +4 -2
  67. data/lib/kitchen/directions/book_answer_key_container/eob_answer_key_outer_container.xhtml.erb +9 -0
  68. data/lib/kitchen/directions/book_answer_key_container/main.rb +11 -0
  69. data/lib/kitchen/directions/book_answer_key_container/v1.rb +14 -0
  70. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +9 -0
  71. data/lib/kitchen/directions/chapter_review_container/main.rb +11 -0
  72. data/lib/kitchen/directions/chapter_review_container/v1.rb +15 -0
  73. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +14 -1
  74. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +37 -0
  75. data/lib/kitchen/directions/{bake_chapter_review_exercises → move_exercises_to_eoc}/v1.rb +8 -10
  76. data/lib/kitchen/directions/{bake_chapter_review_exercises → move_exercises_to_eoc}/v2.rb +8 -9
  77. data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +49 -0
  78. data/lib/kitchen/directions/{bake_chapter_answer_key → move_solutions_to_answer_key}/main.rb +7 -3
  79. data/lib/kitchen/directions/{bake_chapter_answer_key → move_solutions_to_answer_key}/strategies/calculus.rb +1 -1
  80. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +27 -0
  81. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +84 -0
  82. data/lib/kitchen/directions/{bake_chapter_answer_key → move_solutions_to_answer_key}/strategies/uphysics.rb +7 -5
  83. data/lib/kitchen/directions/{bake_chapter_answer_key → move_solutions_to_answer_key}/v1.rb +12 -6
  84. data/lib/kitchen/document.rb +20 -42
  85. data/lib/kitchen/element.rb +9 -3
  86. data/lib/kitchen/element_base.rb +108 -21
  87. data/lib/kitchen/element_enumerator_base.rb +33 -2
  88. data/lib/kitchen/element_enumerator_factory.rb +28 -12
  89. data/lib/kitchen/element_factory.rb +3 -3
  90. data/lib/kitchen/example_element.rb +8 -11
  91. data/lib/kitchen/example_element_enumerator.rb +1 -1
  92. data/lib/kitchen/exercise_element.rb +7 -10
  93. data/lib/kitchen/exercise_element_enumerator.rb +1 -1
  94. data/lib/kitchen/figure_element.rb +8 -11
  95. data/lib/kitchen/figure_element_enumerator.rb +1 -1
  96. data/lib/kitchen/id_tracker.rb +68 -0
  97. data/lib/kitchen/metadata_element.rb +8 -2
  98. data/lib/kitchen/metadata_element_enumerator.rb +1 -1
  99. data/lib/kitchen/note_element.rb +8 -11
  100. data/lib/kitchen/note_element_enumerator.rb +1 -1
  101. data/lib/kitchen/oven.rb +5 -1
  102. data/lib/kitchen/page_element.rb +27 -12
  103. data/lib/kitchen/page_element_enumerator.rb +1 -1
  104. data/lib/kitchen/patches/i18n.rb +34 -0
  105. data/lib/kitchen/patches/integer.rb +24 -0
  106. data/lib/kitchen/patches/nokogiri.rb +62 -0
  107. data/lib/kitchen/patches/nokogiri_profiling.rb +60 -0
  108. data/lib/kitchen/reference_element.rb +27 -0
  109. data/lib/kitchen/references_element_enumerator.rb +20 -0
  110. data/lib/kitchen/search_query.rb +31 -3
  111. data/lib/kitchen/selector.rb +25 -0
  112. data/lib/kitchen/selectors/base.rb +39 -0
  113. data/lib/kitchen/selectors/standard_1.rb +13 -0
  114. data/lib/kitchen/table_element.rb +8 -11
  115. data/lib/kitchen/table_element_enumerator.rb +1 -1
  116. data/lib/kitchen/templates/eob_section_title_template.xhtml.erb +10 -0
  117. data/lib/kitchen/templates/eoc_section_title_template.xhtml.erb +10 -0
  118. data/lib/kitchen/term_element.rb +5 -8
  119. data/lib/kitchen/term_element_enumerator.rb +1 -1
  120. data/lib/kitchen/unit_element.rb +13 -7
  121. data/lib/kitchen/unit_element_enumerator.rb +1 -1
  122. data/lib/kitchen/version.rb +1 -1
  123. data/lib/locales/en.yml +5 -1
  124. data/lib/locales/es.yml +33 -0
  125. data/lib/locales/pl.yml +3 -2
  126. data/lib/openstax_kitchen.rb +2 -5
  127. data/openstax_kitchen.gemspec +1 -0
  128. metadata +66 -25
  129. data/.github/config.yml +0 -14
  130. data/lib/kitchen/directions/bake_book_answer_key/eob_solutions_container.xhtml.erb +0 -9
  131. data/lib/kitchen/directions/bake_book_answer_key/main.rb +0 -11
  132. data/lib/kitchen/directions/bake_book_answer_key/v1.rb +0 -13
  133. data/lib/kitchen/directions/bake_chapter_glossary.rb +0 -39
  134. data/lib/kitchen/directions/bake_chapter_key_concepts/key_concepts.xhtml.erb +0 -16
  135. data/lib/kitchen/directions/bake_chapter_review/chapter_review.xhtml.erb +0 -9
  136. data/lib/kitchen/directions/bake_chapter_review/v1.rb +0 -13
  137. data/lib/kitchen/directions/bake_chapter_review_exercises/main.rb +0 -15
  138. data/lib/kitchen/directions/bake_chapter_review_exercises/review_exercises.xhtml.erb +0 -10
  139. data/lib/kitchen/directions/bake_exercises/main.rb +0 -12
  140. data/lib/kitchen/directions/bake_exercises/v1.rb +0 -169
  141. data/lib/kitchen/directions/bake_notes/bake_notes.rb +0 -48
  142. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +0 -63
  143. data/lib/kitchen/directions/bake_problem_first_elements.rb +0 -16
  144. data/lib/kitchen/transliterations.rb +0 -21
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeChapterSolutions
4
+ class V1
5
+ renderable
6
+
7
+ def bake(chapter:, metadata_source:, uuid_prefix: '')
8
+ @metadata = metadata_source.children_to_keep.copy
9
+ @klass = 'solutions'
10
+ @title = I18n.t(:eoc_solutions_title)
11
+ @uuid_prefix = uuid_prefix
12
+
13
+ solutions_clipboard = Kitchen::Clipboard.new
14
+
15
+ chapter.search('section.free-response').each do |free_response_question|
16
+ exercises = free_response_question.exercises
17
+ # must run AFTER .free-response notes are baked
18
+
19
+ next if exercises.none?
20
+
21
+ exercises.each do |exercise|
22
+ solution = exercise.solution
23
+ next unless solution.present?
24
+
25
+ solution.cut(to: solutions_clipboard)
26
+ end
27
+ end
28
+
29
+ @content = solutions_clipboard.paste
30
+
31
+ @in_composite_chapter = false
32
+
33
+ chapter.append(child: render(file:
34
+ '../../templates/eoc_section_title_template.xhtml.erb'))
35
+ end
36
+ end
37
+ end
@@ -5,51 +5,64 @@ module Kitchen
5
5
  # Bake directions for eoc summary
6
6
  #
7
7
  module BakeChapterSummary
8
- def self.v1(chapter:, metadata_source:)
9
- metadata_elements = metadata_source.children_to_keep.copy
10
-
11
- summaries = Clipboard.new
12
-
13
- # TODO: include specific page types somehow without writing it out
14
- chapter.non_introduction_pages.each do |page|
15
- summary = page.summary
16
- summary.first("[data-type='title']")&.trash # get rid of old title if exists
17
- summary_title = page.title.copy
18
- summary_title.name = 'h3'
19
- summary_title.replace_children(with: <<~HTML
20
- <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
21
- <span class="os-divider"> </span>
22
- <span class="os-text" data-type="" itemprop="">#{summary_title.children}</span>
23
- HTML
24
- )
25
-
26
- summary.prepend(child:
27
- <<~HTML
28
- <a href="##{page.title.id}">
29
- #{summary_title.paste}
30
- </a>
31
- HTML
32
- )
33
- summary.cut(to: summaries)
34
- end
35
-
36
- return if summaries.none?
37
-
38
- chapter.append(child:
39
- <<~HTML
40
- <div class="os-eoc os-summary-container" data-type="composite-page" data-uuid-key=".summary">
41
- <h2 data-type="document-title">
42
- <span class="os-text">#{I18n.t(:eoc_summary_title)}</span>
43
- </h2>
44
- <div data-type="metadata" style="display: none;">
45
- <h1 data-type="document-title" itemprop="name">#{I18n.t(:eoc_summary_title)}</h1>
46
- #{metadata_elements.paste}
47
- </div>
48
- #{summaries.paste}
49
- </div>
50
- HTML
8
+ def self.v1(chapter:, metadata_source:, klass: 'summary', uuid_prefix: '.')
9
+ V1.new.bake(
10
+ chapter: chapter,
11
+ metadata_source: metadata_source,
12
+ uuid_prefix: uuid_prefix,
13
+ klass: klass
51
14
  )
52
15
  end
16
+
17
+ class V1
18
+ renderable
19
+ def bake(chapter:, metadata_source:, uuid_prefix: '.', klass: 'summary')
20
+ @metadata = metadata_source.children_to_keep.copy
21
+ @klass = klass
22
+ @title = I18n.t(:eoc_summary_title)
23
+ @uuid_prefix = uuid_prefix
24
+
25
+ summaries = Clipboard.new
26
+
27
+ # TODO: include specific page types somehow without writing it out
28
+ chapter.non_introduction_pages.each do |page|
29
+ summary = page.summary
30
+
31
+ next if summary.nil?
32
+
33
+ summary.first("[data-type='title']")&.trash # get rid of old title if exists
34
+ summary_title = page.title.copy
35
+ summary_title.name = 'h3'
36
+
37
+ unless summary_title.children.search('span.os-number').present?
38
+ summary_title.replace_children(with:
39
+ <<~HTML
40
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
41
+ <span class="os-divider"> </span>
42
+ <span class="os-text" data-type="" itemprop="">#{summary_title.children}</span>
43
+ HTML
44
+ )
45
+ end
46
+
47
+ summary.prepend(child:
48
+ <<~HTML
49
+ <a href="##{page.title.id}">
50
+ #{summary_title.paste}
51
+ </a>
52
+ HTML
53
+ )
54
+ summary.cut(to: summaries)
55
+ end
56
+
57
+ return if summaries.none?
58
+
59
+ @content = summaries.paste
60
+ @in_composite_chapter = false
61
+
62
+ chapter.append(child: render(file:
63
+ '../templates/eoc_section_title_template.xhtml.erb'))
64
+ end
65
+ end
53
66
  end
54
67
  end
55
68
  end
@@ -4,7 +4,7 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeCompositeChapters
6
6
  def self.v1(book:)
7
- book.search("[data-type='composite-chapter']").each do |chapter|
7
+ book.composite_chapters.each do |chapter|
8
8
  chapter.first("[data-type='document-title']").id =
9
9
  "composite-chapter-#{chapter.count_in(:book)}"
10
10
  end
@@ -4,7 +4,7 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeCompositePages
6
6
  def self.v1(book:)
7
- book.search("[data-type='composite-page']").each do |page|
7
+ book.composite_pages.each do |page|
8
8
  page.id = "composite-page-#{page.count_in(:book)}"
9
9
  end
10
10
  end
@@ -4,13 +4,13 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeEquations
6
6
  def self.v1(book:, number_decorator: :none)
7
- book.chapters.search('[data-type="equation"]:not(.unnumbered)').each do |eq|
7
+ book.chapters.search('div[data-type="equation"]:not(.unnumbered)').each do |eq|
8
8
  chapter = eq.ancestor(:chapter)
9
9
  number = "#{chapter.count_in(:book)}.#{eq.count_in(:chapter)}"
10
10
 
11
11
  # Store label information
12
12
  equation_label = "#{I18n.t(:equation)} #{number}"
13
- book.document.pantry(name: :link_text).store equation_label, label: eq.id
13
+ book.pantry(name: :link_text).store equation_label, label: eq.id
14
14
 
15
15
  decorated_number =
16
16
  case number_decorator
@@ -20,7 +20,14 @@ module Kitchen
20
20
  .pantry(name: :link_text)
21
21
  .store("#{I18n.t(:example_label)} #{number}", label: example.id)
22
22
 
23
- example.titles.each { |title| title.name = 'h4' }
23
+ example.titles.each do |title|
24
+ if title.parent.has_class?('os-caption-container') || \
25
+ title.parent.has_class?('os-caption')
26
+ next
27
+ end
28
+
29
+ title.name = 'h4'
30
+ end
24
31
 
25
32
  example.exercises.each do |exercise|
26
33
  if (problem = exercise.problem)
@@ -4,9 +4,22 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeFigure
6
6
  def self.v1(figure:, number:)
7
+ return if figure.has_class?('unnumbered') && !figure.has_class?('splash')
8
+
7
9
  figure.wrap(%(<div class="os-figure#{' has-splash' if figure.has_class?('splash')}">))
10
+ if figure.has_class?('unnumbered') && figure.has_class?('splash')
11
+ caption = figure.caption&.cut
12
+ figure.append(sibling:
13
+ <<~HTML
14
+ <div class="os-caption-container">
15
+ #{"<span class=\"os-caption\">#{caption.children}</span>" if caption}
16
+ </div>
17
+ HTML
18
+ )
19
+ return
20
+ end
8
21
 
9
- figure.document.pantry(name: :link_text).store "#{I18n.t(:figure)} #{number}", label: figure.id
22
+ figure.pantry(name: :link_text).store "#{I18n.t(:figure)} #{number}", label: figure.id
10
23
  title = figure.title&.cut
11
24
 
12
25
  caption = figure.caption&.cut
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeFirstElements
6
+ def self.v1(within:)
7
+ selectors = [
8
+ 'div.os-problem-container > div.os-table',
9
+ 'div.os-problem-container > span[data-type="media"]',
10
+ 'div.os-solution-container > div.os-table',
11
+ 'div.os-solution-container > span[data-type="media"]'
12
+ ]
13
+ selectors.each do |selector|
14
+ within.search("#{selector}:first-child").each do |problem|
15
+ problem.add_class('first-element')
16
+ problem.parent.add_class('has-first-element')
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -3,8 +3,8 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeFootnotes
6
- def self.v1(book:)
7
- V1.new.bake(book: book)
6
+ def self.v1(book:, number_format: :arabic)
7
+ V1.new.bake(book: book, number_format: number_format)
8
8
  end
9
9
  end
10
10
  end
@@ -3,36 +3,40 @@
3
3
  module Kitchen::Directions::BakeFootnotes
4
4
  class V1
5
5
 
6
- def bake(book:)
6
+ def bake(book:, number_format: :arabic)
7
7
  # Footnotes are numbered either within their top-level pages (preface,
8
8
  # appendices, etc) or within chapters. Tackle each case separately
9
9
 
10
10
  book.body.element_children.only(Kitchen::PageElement,
11
- Kitchen::CompositePageElement).each do |page|
12
- bake_footnotes_within(page)
11
+ Kitchen::CompositePageElement,
12
+ Kitchen::CompositeChapterElement).each do |page|
13
+ bake_footnotes_within(page, number_format: number_format)
13
14
  end
14
15
 
15
16
  book.chapters.each do |chapter|
16
- bake_footnotes_within(chapter)
17
+ bake_footnotes_within(chapter, number_format: number_format)
17
18
  end
18
19
  end
19
20
 
20
- def bake_footnotes_within(container)
21
- footnote_number = 0
21
+ def bake_footnotes_within(container, number_format:)
22
+ footnote_count = 0
22
23
  aside_id_to_footnote_number = {}
23
24
 
24
25
  container.search("a[role='doc-noteref']").each do |anchor|
25
- footnote_number += 1
26
- anchor.replace_children(with: footnote_number.to_s)
26
+ footnote_count += 1
27
+ footnote_number = footnote_count.to_format(number_format)
28
+ anchor.replace_children(with: footnote_number)
27
29
  aside_id = anchor[:href][1..-1]
28
30
  aside_id_to_footnote_number[aside_id] = footnote_number
31
+ anchor.parent.add_class('has-noteref') if anchor.parent.name == 'p'
29
32
  end
30
33
 
31
34
  container.search('aside').each do |aside|
32
35
  footnote_number = aside_id_to_footnote_number[aside.id]
33
36
  aside.prepend(child: "<div data-type='footnote-number'>#{footnote_number}</div>")
34
37
  end
35
- end
36
38
 
39
+ footnote_count
40
+ end
37
41
  end
38
42
  end
@@ -0,0 +1,10 @@
1
+ <div class="os-eoc os-free-response-container" data-type="composite-page" data-uuid-key=".free-response">
2
+ <<%= @title_tag %> data-type="document-title">
3
+ <span class="os-text"><%= I18n.t(:eoc_free_response) %></span>
4
+ </<%= @title_tag %>>
5
+ <div data-type="metadata" style="display: none;">
6
+ <h1 data-type="document-title" itemprop="name"><%= I18n.t(:eoc_free_response) %></h1>
7
+ <%= @metadata_elements.paste %>
8
+ </div>
9
+ <%= @free_response_clipboard.paste %>
10
+ </div>
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Kitchen
4
4
  module Directions
5
- module BakeChapterReview
6
- def self.v1(chapter:, metadata_source:)
7
- V1.new.bake(chapter: chapter, metadata_source: metadata_source)
5
+ module BakeFreeResponse
6
+ def self.v1(chapter:, metadata_source:, append_to: nil)
7
+ V1.new.bake(chapter: chapter, metadata_source: metadata_source, append_to: append_to)
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeFreeResponse
4
+ class V1
5
+ renderable
6
+
7
+ def bake(chapter:, metadata_source:, append_to:)
8
+ @metadata_elements = metadata_source.children_to_keep.copy
9
+
10
+ @free_response_clipboard = Kitchen::Clipboard.new
11
+ chapter.non_introduction_pages.each do |page|
12
+ free_response_questions = page.free_response
13
+ next if free_response_questions.none?
14
+
15
+ free_response_questions.search('h3').trash
16
+ title = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(page: page)
17
+ free_response_questions.each do |free_response_question|
18
+ free_response_question.prepend(child: title)
19
+ free_response_question.cut(to: @free_response_clipboard)
20
+ end
21
+ end
22
+
23
+ append_to_element = append_to || chapter
24
+ @title_tag = append_to ? 'h3' : 'h2'
25
+
26
+ append_to_element.append(child: render(file: 'free_response.xhtml.erb'))
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ # Bake directions for further research
6
+ #
7
+ module BakeFurtherResearch
8
+ def self.v1(chapter:, metadata_source:, uuid_prefix: '.')
9
+ V1.new.bake(
10
+ chapter: chapter,
11
+ metadata_source: metadata_source,
12
+ uuid_prefix: uuid_prefix)
13
+ end
14
+
15
+ class V1
16
+ renderable
17
+ def bake(chapter:, metadata_source:, uuid_prefix: '.')
18
+ @metadata = metadata_source.children_to_keep.copy
19
+ @klass = 'further-research'
20
+ @title = I18n.t(:eoc_further_research_title)
21
+ @uuid_prefix = uuid_prefix
22
+
23
+ further_researches = Clipboard.new
24
+
25
+ chapter.non_introduction_pages.each do |page|
26
+ further_research = page.first('.further-research')
27
+ next unless further_research.present?
28
+
29
+ further_research.first("[data-type='title']")&.trash # get rid of old title if exists
30
+ further_research_title = page.title.copy
31
+ further_research_title.name = 'h3'
32
+ further_research_title.replace_children(with: <<~HTML
33
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
34
+ <span class="os-divider"> </span>
35
+ <span class="os-text" data-type="" itemprop="">#{further_research_title.children}</span>
36
+ HTML
37
+ )
38
+
39
+ further_research.prepend(child:
40
+ <<~HTML
41
+ <a href="##{page.title.id}">
42
+ #{further_research_title.paste}
43
+ </a>
44
+ HTML
45
+ )
46
+ further_research.cut(to: further_researches)
47
+ end
48
+
49
+ return if further_researches.none?
50
+
51
+ @content = further_researches.paste
52
+
53
+ @in_composite_chapter = false
54
+
55
+ chapter.append(child: render(file:
56
+ '../templates/eoc_section_title_template.xhtml.erb'))
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -27,13 +27,6 @@ module Kitchen::Directions::BakeIndex
27
27
  def initialize(term_text:)
28
28
  @term_text = term_text
29
29
  @terms = []
30
-
31
- # Sort by transliterated version first to support accent marks,
32
- # then by the raw text to support the same text with different capitalization
33
- @sortable = [
34
- ActiveSupport::Inflector.transliterate(term_text).downcase,
35
- term_text
36
- ]
37
30
  end
38
31
 
39
32
  def add_term(term)
@@ -44,13 +37,13 @@ module Kitchen::Directions::BakeIndex
44
37
  @term_text = @term_text.uncapitalize
45
38
  end
46
39
 
47
- def <=>(other)
48
- sortable <=> other.sortable
40
+ def capitalize_term_text!
41
+ @term_text = @term_text.capitalize
49
42
  end
50
43
 
51
- protected
52
-
53
- attr_reader :sortable
44
+ def <=>(other)
45
+ I18n.sort_strings(term_text, other.term_text)
46
+ end
54
47
  end
55
48
 
56
49
  class IndexSection
@@ -84,6 +77,11 @@ module Kitchen::Directions::BakeIndex
84
77
  different_caps_item = @items_by_term_text[term.text.uncapitalize]
85
78
  different_caps_item&.uncapitalize_term_text!
86
79
 
80
+ unless different_caps_item
81
+ different_caps_item = @items_by_term_text[term.text.capitalize]
82
+ different_caps_item&.capitalize_term_text!
83
+ end
84
+
87
85
  (different_caps_item || IndexItem.new(term_text: term.text)).tap do |item|
88
86
  @items.add(item)
89
87
  end
@@ -119,27 +117,39 @@ module Kitchen::Directions::BakeIndex
119
117
  @index = Index.new
120
118
 
121
119
  book.pages.terms.each do |term_element|
122
- # Markup the term
123
120
  page = term_element.ancestor(:page)
124
121
  term_element.id = "auto_#{page.id}_term#{term_element.count_in(:book)}"
122
+ page_title = page.title.text
123
+ add_term_to_index(term_element, page_title)
124
+ end
125
125
 
126
- group_by = term_element.text.strip[0]
127
- group_by = I18n.t(:eob_index_symbols_group) unless group_by.match?(/\w/)
128
- term_element['group-by'] = group_by
129
-
130
- # Add it to our index object
131
- @index.add_term(
132
- Term.new(
133
- text: term_element.text,
134
- id: term_element.id,
135
- group_by: group_by,
136
- page_title: page.title.text.gsub(/\n/, '')
137
- )
138
- )
126
+ book.chapters.composite_pages.terms.each do |term_element|
127
+ page = term_element.ancestor(:composite_page)
128
+ chapter = term_element.ancestor(:chapter)
129
+ term_element.id = "auto_composite_page_term#{term_element.count_in(:book)}"
130
+ chapter_number = chapter.count_in(:book)
131
+ page_title = "#{chapter_number} #{page.title.text.strip}".strip
132
+ add_term_to_index(term_element, page_title)
139
133
  end
140
134
 
141
135
  book.first('body').append(child: render(file: 'v1.xhtml.erb'))
142
136
  end
143
137
 
138
+ def add_term_to_index(term_element, page_title)
139
+ group_by = I18n.transliterate(term_element.text.strip[0])
140
+ group_by = I18n.t(:eob_index_symbols_group) unless group_by.match?(/[[:alpha:]]/)
141
+ term_element['group-by'] = group_by
142
+
143
+ # Add it to our index object
144
+ @index.add_term(
145
+ Term.new(
146
+ text: term_element.text,
147
+ id: term_element.id,
148
+ group_by: group_by,
149
+ page_title: page_title.gsub(/\n/, '')
150
+ )
151
+ )
152
+ end
153
+
144
154
  end
145
155
  end