openstax_kitchen 4.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/changelog.yml +24 -0
  3. data/.github/workflows/rubocop.yml +28 -0
  4. data/CHANGELOG.md +58 -0
  5. data/Gemfile.lock +15 -6
  6. data/README.md +16 -0
  7. data/codecov.yaml +1 -0
  8. data/docker/rubocop +22 -0
  9. data/lib/kitchen/book_document.rb +1 -1
  10. data/lib/kitchen/chapter_element.rb +2 -2
  11. data/lib/kitchen/composite_chapter_element_enumerator.rb +21 -0
  12. data/lib/kitchen/composite_page_element.rb +19 -2
  13. data/lib/kitchen/config.rb +7 -0
  14. data/lib/kitchen/directions/bake_appendix.rb +3 -1
  15. data/lib/kitchen/directions/bake_chapter_introductions.rb +22 -15
  16. data/lib/kitchen/directions/bake_chapter_introductions/chapter_introduction.xhtml.erb +0 -0
  17. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +1 -1
  18. data/lib/kitchen/directions/bake_chapter_references/main.rb +15 -0
  19. data/lib/kitchen/directions/bake_chapter_references/v1.rb +49 -0
  20. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +2 -2
  21. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +2 -1
  22. data/lib/kitchen/directions/bake_chapter_solutions/main.rb +11 -0
  23. data/lib/kitchen/directions/bake_chapter_solutions/v1.rb +37 -0
  24. data/lib/kitchen/directions/bake_chapter_summary.rb +13 -6
  25. data/lib/kitchen/directions/bake_composite_chapters.rb +1 -1
  26. data/lib/kitchen/directions/bake_composite_pages.rb +1 -1
  27. data/lib/kitchen/directions/bake_equations.rb +1 -1
  28. data/lib/kitchen/directions/bake_example.rb +4 -1
  29. data/lib/kitchen/directions/bake_figure.rb +13 -0
  30. data/lib/kitchen/directions/bake_first_elements.rb +7 -1
  31. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  32. data/lib/kitchen/directions/bake_footnotes/v1.rb +11 -8
  33. data/lib/kitchen/directions/bake_further_research.rb +2 -0
  34. data/lib/kitchen/directions/bake_index/v1.rb +3 -14
  35. data/lib/kitchen/directions/bake_inline_lists.rb +22 -0
  36. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/main.rb +43 -0
  37. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v1.rb +37 -0
  38. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v2.rb +25 -0
  39. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v3.rb +32 -0
  40. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +3 -2
  41. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +10 -1
  42. data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +29 -0
  43. data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -0
  44. data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -24
  45. data/lib/kitchen/directions/bake_numbered_table/v2.rb +31 -0
  46. data/lib/kitchen/directions/bake_preface/main.rb +2 -2
  47. data/lib/kitchen/directions/bake_preface/v1.rb +3 -2
  48. data/lib/kitchen/directions/bake_references/main.rb +7 -0
  49. data/lib/kitchen/directions/bake_references/v2.rb +35 -0
  50. data/lib/kitchen/directions/bake_toc.rb +3 -1
  51. data/lib/kitchen/directions/book_answer_key_container/eob_answer_key_outer_container.xhtml.erb +9 -0
  52. data/lib/kitchen/directions/book_answer_key_container/main.rb +2 -2
  53. data/lib/kitchen/directions/book_answer_key_container/v1.rb +4 -3
  54. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +3 -3
  55. data/lib/kitchen/directions/chapter_review_container/main.rb +2 -2
  56. data/lib/kitchen/directions/chapter_review_container/v1.rb +4 -2
  57. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +13 -0
  58. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +10 -0
  59. data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +49 -0
  60. data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +6 -2
  61. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +27 -0
  62. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +84 -0
  63. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/uphysics.rb +2 -2
  64. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +11 -7
  65. data/lib/kitchen/document.rb +19 -52
  66. data/lib/kitchen/element_base.rb +48 -12
  67. data/lib/kitchen/element_enumerator_base.rb +24 -1
  68. data/lib/kitchen/element_enumerator_factory.rb +19 -7
  69. data/lib/kitchen/exercise_element.rb +2 -2
  70. data/lib/kitchen/id_tracker.rb +68 -0
  71. data/lib/kitchen/oven.rb +5 -1
  72. data/lib/kitchen/page_element.rb +7 -5
  73. data/lib/kitchen/patches/i18n.rb +34 -0
  74. data/lib/kitchen/patches/integer.rb +24 -0
  75. data/lib/kitchen/patches/nokogiri.rb +62 -0
  76. data/lib/kitchen/patches/nokogiri_profiling.rb +60 -0
  77. data/lib/kitchen/search_query.rb +6 -0
  78. data/lib/kitchen/selector.rb +3 -2
  79. data/lib/kitchen/version.rb +1 -1
  80. data/lib/locales/en.yml +2 -1
  81. data/lib/locales/es.yml +33 -0
  82. data/lib/locales/pl.yml +4 -2
  83. data/lib/openstax_kitchen.rb +1 -5
  84. data/openstax_kitchen.gemspec +1 -0
  85. metadata +42 -7
  86. data/.github/config.yml +0 -14
  87. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +0 -51
  88. data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +0 -9
  89. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +0 -19
  90. data/lib/kitchen/transliterations.rb +0 -21
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeNumberedNotes
4
+ class V2
5
+ def bake(book:, classes:)
6
+ classes.each do |klass|
7
+ book.chapters.pages.notes("$.#{klass}").each do |note|
8
+ note.wrap_children(class: 'os-note-body')
9
+ note_count = note.count_in(:page)
10
+ note.prepend(child:
11
+ <<~HTML
12
+ <h3 class="os-title">
13
+ <span class="os-title-label">#{note.autogenerated_title}</span>
14
+ <span class="os-number">##{note_count}</span>
15
+ </h3>
16
+ HTML
17
+ )
18
+ note.exercises.each do |exercise|
19
+ Kitchen::Directions::BakeNumberedNotes.bake_note_exercise(note: note, exercise: exercise, divider: '. ')
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeNumberedNotes
4
+ class V3
5
+ # for the try it notes, must be called AFTER bake_exercises
6
+ def bake(book:, classes:, suppress_solution: true)
7
+ classes.each do |klass|
8
+ book.chapters.notes("$.#{klass}").each do |note|
9
+ note.wrap_children(class: 'os-note-body')
10
+ previous_example = note.previous
11
+ os_number = previous_example&.first('.os-number')&.children&.to_s
12
+
13
+ note.prepend(child:
14
+ <<~HTML
15
+ <h3 class="os-title">
16
+ <span class="os-title-label">#{note.autogenerated_title}</span>
17
+ <span class="os-number">#{os_number}</span>
18
+ </h3>
19
+ HTML
20
+ )
21
+
22
+ note.title&.trash
23
+ note.exercises.each do |exercise|
24
+ Kitchen::Directions::BakeNumberedNotes.bake_note_exercise(
25
+ note: note, exercise: exercise, divider: '. ', suppress_solution: suppress_solution
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,8 +3,9 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeNumberedExercise
6
- def self.v1(exercise:, number:, suppress_solution: false)
7
- V1.new.bake(exercise: exercise, number: number, suppress_solution: suppress_solution)
6
+ def self.v1(exercise:, number:, suppress_solution_if: false, note_suppressed_solutions: false)
7
+ V1.new.bake(exercise: exercise, number: number, suppress_solution_if: suppress_solution_if,
8
+ note_suppressed_solutions: note_suppressed_solutions)
8
9
  end
9
10
 
10
11
  def self.bake_solution_v1(exercise:, number:, divider: '. ')
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Kitchen::Directions::BakeNumberedExercise
4
4
  class V1
5
- def bake(exercise:, number:, suppress_solution: false)
5
+ def bake(exercise:, number:, suppress_solution_if: false, note_suppressed_solutions: false)
6
6
  problem = exercise.problem
7
7
  solution = exercise.solution
8
8
 
@@ -12,9 +12,18 @@ module Kitchen::Directions::BakeNumberedExercise
12
12
  )
13
13
  problem_number = "<span class='os-number'>#{number}</span>"
14
14
 
15
+ suppress_solution =
16
+ case suppress_solution_if
17
+ when Symbol
18
+ number.send(suppress_solution_if)
19
+ else
20
+ suppress_solution_if
21
+ end
22
+
15
23
  if solution.present?
16
24
  if suppress_solution
17
25
  solution.trash
26
+ exercise.add_class('os-hasSolution-trashed') if note_suppressed_solutions
18
27
  else
19
28
  problem_number = "<a class='os-number' href='##{exercise.id}-solution'>#{number}</a>"
20
29
  bake_solution(exercise: exercise, number: number)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ # Bake directions for table body
6
+ #
7
+ module BakeTableBody
8
+ def self.v1(table:, number:)
9
+ table.remove_attribute('summary')
10
+ table.wrap(%(<div class="os-table">))
11
+
12
+ table_label = "#{I18n.t(:table_label)} #{number}"
13
+ table.pantry(name: :link_text).store table_label, label: table.id
14
+
15
+ if table.top_titled?
16
+ table.parent.add_class('os-top-titled-container')
17
+ table.prepend(sibling:
18
+ <<~HTML
19
+ <div class="os-table-title">#{table.title}</div>
20
+ HTML
21
+ )
22
+ table.title_row.trash
23
+ end
24
+
25
+ table.parent.add_class('os-column-header-container') if table.column_header?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -6,6 +6,10 @@ module Kitchen
6
6
  def self.v1(table:, number:, always_caption: false)
7
7
  V1.new.bake(table: table, number: number, always_caption: always_caption)
8
8
  end
9
+
10
+ def self.v2(table:, number:)
11
+ V2.new.bake(table: table, number: number)
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -4,39 +4,19 @@ module Kitchen::Directions::BakeNumberedTable
4
4
  class V1
5
5
 
6
6
  def bake(table:, number:, always_caption: false)
7
- table.wrap(%(<div class="os-table">))
8
-
9
- table_label = "#{I18n.t(:table_label)} #{number}"
10
- table.pantry(name: :link_text).store table_label, label: table.id
11
-
12
- if table.top_titled?
13
- table.parent.add_class('os-top-titled-container')
14
- table.prepend(sibling:
15
- <<~HTML
16
- <div class="os-table-title">#{table.title}</div>
17
- HTML
18
- )
19
- table.title_row.trash
20
- end
21
-
22
- table.parent.add_class('os-column-header-container') if table.column_header?
7
+ Kitchen::Directions::BakeTableBody.v1(table: table, number: number)
23
8
 
24
9
  # TODO: extra spaces added here to match legacy implementation, but probably not meaningful?
25
- new_summary = "#{table_label} "
26
10
  new_caption = ''
27
11
  caption_title = ''
28
12
 
29
13
  if (title = table.first("span[data-type='title']")&.cut)
30
- new_summary += title.text
31
14
  caption_title = <<~HTML
32
15
  \n<span class="os-title" data-type="title">#{title.children}</span>
33
16
  HTML
34
17
  end
35
18
 
36
- new_summary += ' '
37
-
38
19
  if (caption = table.caption&.cut)
39
- new_summary += caption.text
40
20
  new_caption = <<~HTML
41
21
  \n<span class="os-caption">#{caption.children}</span>
42
22
  HTML
@@ -46,8 +26,6 @@ module Kitchen::Directions::BakeNumberedTable
46
26
  HTML
47
27
  end
48
28
 
49
- table[:summary] = new_summary
50
-
51
29
  return if table.unnumbered?
52
30
 
53
31
  table.append(sibling:
@@ -61,6 +39,5 @@ module Kitchen::Directions::BakeNumberedTable
61
39
  HTML
62
40
  )
63
41
  end
64
-
65
42
  end
66
43
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeNumberedTable
4
+ # Difference from v1: only in the caption
5
+ # V2 caption titles are nested within an .os-caption span
6
+ class V2
7
+
8
+ def bake(table:, number:)
9
+ Kitchen::Directions::BakeTableBody.v1(table: table, number: number)
10
+
11
+ caption = ''
12
+ if table&.caption&.first("span[data-type='title']")
13
+ caption_el = table.caption
14
+ caption_el.add_class('os-caption')
15
+ caption_el.name = 'span'
16
+ caption = caption_el.cut
17
+ end
18
+
19
+ table.append(sibling:
20
+ <<~HTML
21
+ <div class="os-caption-container">
22
+ <span class="os-title-label">#{I18n.t(:table_label)} </span>
23
+ <span class="os-number">#{number}</span>
24
+ <span class="os-divider"> </span>
25
+ #{caption}
26
+ </div>
27
+ HTML
28
+ )
29
+ end
30
+ end
31
+ end
@@ -3,8 +3,8 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakePreface
6
- def self.v1(book:)
7
- V1.new.bake(book: book)
6
+ def self.v1(book:, title_element: 'h1')
7
+ V1.new.bake(book: book, title_element: title_element)
8
8
  end
9
9
  end
10
10
  end
@@ -2,15 +2,16 @@
2
2
 
3
3
  module Kitchen::Directions::BakePreface
4
4
  class V1
5
- def bake(book:)
5
+ def bake(book:, title_element:)
6
6
  book.pages('$.preface').each do |page|
7
+ page.search('div[data-type="description"], div[data-type="abstract"]').each(&:trash)
7
8
  page.titles.each do |title|
8
9
  title.replace_children(with:
9
10
  <<~HTML
10
11
  <span data-type="" itemprop="" class="os-text">#{title.text}</span>
11
12
  HTML
12
13
  )
13
- title.name = 'h1'
14
+ title.name = title_element
14
15
  end
15
16
  end
16
17
  end
@@ -11,6 +11,13 @@ module Kitchen
11
11
  metadata_source: metadata_source
12
12
  )
13
13
  end
14
+
15
+ def self.v2(book:, metadata_source:)
16
+ V2.new.bake(
17
+ book: book,
18
+ metadata_source: metadata_source
19
+ )
20
+ end
14
21
  end
15
22
  end
16
23
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeReferences
4
+ class V2
5
+ renderable
6
+
7
+ def bake(book:, metadata_source:)
8
+ @metadata = metadata_source.children_to_keep.copy
9
+ @klass = 'references'
10
+ @uuid_prefix = '.'
11
+ @title = I18n.t(:references)
12
+
13
+ book.chapters.each do |chapter|
14
+
15
+ chapter.references.search('h3').trash
16
+
17
+ chapter_references = chapter.pages.references.cut
18
+ chapter_title_no_num = chapter.title.search('.os-text')
19
+
20
+ chapter.append(child:
21
+ <<~HTML
22
+ <div class="os-chapter-area">
23
+ <h2 data-type="document-title">#{chapter_title_no_num}</h2>
24
+ #{chapter_references.paste}
25
+ </div>
26
+ HTML
27
+ )
28
+ end
29
+ chapter_area_references = book.chapters.search('.os-chapter-area').cut
30
+ @content = chapter_area_references.paste
31
+ book.body.append(child: render(file:
32
+ '../../templates/eob_section_title_template.xhtml.erb'))
33
+ end
34
+ end
35
+ end
@@ -96,8 +96,10 @@ module Kitchen
96
96
  when CompositePageElement
97
97
  if page.is_index?
98
98
  'os-toc-index'
99
- elsif page.is_reference?
99
+ elsif page.is_citation_reference?
100
100
  'os-toc-reference'
101
+ elsif page.is_section_reference?
102
+ 'os-toc-references'
101
103
  elsif page.has_ancestor?(:composite_chapter) || page.has_ancestor?(:chapter)
102
104
  'os-toc-chapter-composite-page'
103
105
  else
@@ -0,0 +1,9 @@
1
+ <div class="os-eob os-<%= @solutions_or_solution %>-container" data-type="composite-chapter" data-uuid-key=".<%= @solutions_or_solution %>">
2
+ <h1 data-type="document-title">
3
+ <span class="os-text"><%= I18n.t(:answer_key_title) %></span>
4
+ </h1>
5
+ <div data-type="metadata" style="display: none;">
6
+ <h1 data-type="document-title" itemprop="name"><%= I18n.t(:answer_key_title) %></h1>
7
+ <%= @metadata.paste %>
8
+ </div>
9
+ </div>
@@ -3,8 +3,8 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BookAnswerKeyContainer
6
- def self.v1(book:)
7
- V1.new.bake(book: book)
6
+ def self.v1(book:, solutions_plural: true)
7
+ V1.new.bake(book: book, solutions_plural: solutions_plural)
8
8
  end
9
9
  end
10
10
  end
@@ -4,10 +4,11 @@ module Kitchen::Directions::BookAnswerKeyContainer
4
4
  class V1
5
5
  renderable
6
6
 
7
- def bake(book:)
7
+ def bake(book:, solutions_plural: true)
8
8
  @metadata = book.metadata.children_to_keep.copy
9
- book.body.append(child: render(file: 'eob_solutions_container.xhtml.erb'))
10
- book.body.first('.os-eob.os-solutions-container')
9
+ @solutions_or_solution = solutions_plural ? 'solutions' : 'solution'
10
+ book.body.append(child: render(file: 'eob_answer_key_outer_container.xhtml.erb'))
11
+ book.body.first("div.os-eob.os-#{@solutions_or_solution}-container")
11
12
  end
12
13
  end
13
14
  end
@@ -1,9 +1,9 @@
1
- <div class="os-eoc os-chapter-review-container" data-type="composite-chapter" data-uuid-key=".chapter-review">
1
+ <div class="os-eoc os-<%= @klass %>-container" data-type="composite-chapter" data-uuid-key=".<%= @klass %>">
2
2
  <h2 data-type="document-title">
3
- <span class="os-text"><%= I18n.t(:eoc_chapter_review) %></span>
3
+ <span class="os-text"><%= @title %></span>
4
4
  </h2>
5
5
  <div data-type="metadata" style="display: none;">
6
- <h1 data-type="document-title" itemprop="name"><%= I18n.t(:eoc_chapter_review) %></h1>
6
+ <h1 data-type="document-title" itemprop="name"><%= @title %></h1>
7
7
  <%= @metadata.paste %>
8
8
  </div>
9
9
  </div>
@@ -3,8 +3,8 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module ChapterReviewContainer
6
- def self.v1(chapter:, metadata_source:)
7
- V1.new.bake(chapter: chapter, metadata_source: metadata_source)
6
+ def self.v1(chapter:, metadata_source:, klass: 'chapter-review')
7
+ V1.new.bake(chapter: chapter, metadata_source: metadata_source, klass: klass)
8
8
  end
9
9
  end
10
10
  end
@@ -4,10 +4,12 @@ module Kitchen::Directions::ChapterReviewContainer
4
4
  class V1
5
5
  renderable
6
6
 
7
- def bake(chapter:, metadata_source:)
7
+ def bake(chapter:, metadata_source:, klass: 'chapter-review')
8
8
  @metadata = metadata_source.children_to_keep.copy
9
+ @klass = klass
10
+ @title = I18n.t(:"eoc.#{klass}")
9
11
  chapter.append(child: render(file: 'chapter_review.xhtml.erb'))
10
- chapter.first('.os-eoc.os-chapter-review-container')
12
+ chapter.element_children[-1]
11
13
  end
12
14
  end
13
15
  end
@@ -15,6 +15,19 @@ module Kitchen
15
15
  </a>
16
16
  HTML
17
17
  end
18
+
19
+ def self.v2(page:)
20
+ chapter = page.ancestor(:chapter)
21
+ <<~HTML
22
+ <div>
23
+ <h3 data-type="document-title" id="#{page.title.copied_id}">
24
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
25
+ <span class="os-divider"> </span>
26
+ <span class="os-text" data-type="" itemprop="">#{page.title_text}</span>
27
+ </h3>
28
+ </div>
29
+ HTML
30
+ end
18
31
  end
19
32
  end
20
33
  end
@@ -22,6 +22,16 @@ module Kitchen
22
22
  uuid_prefix: uuid_prefix
23
23
  )
24
24
  end
25
+
26
+ def self.v3(chapter:, metadata_source:, klass:, append_to: nil, uuid_prefix: '.')
27
+ V3.new.bake(
28
+ chapter: chapter,
29
+ metadata_source: metadata_source,
30
+ append_to: append_to,
31
+ klass: klass,
32
+ uuid_prefix: uuid_prefix
33
+ )
34
+ end
25
35
  end
26
36
  end
27
37
  end