openstax_kitchen 3.2.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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