openstax_kitchen 4.1.1 → 8.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 (76) 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 +62 -0
  5. data/Gemfile.lock +16 -7
  6. data/docker/rubocop +24 -0
  7. data/lib/kitchen/composite_page_element.rb +20 -3
  8. data/lib/kitchen/directions/bake_appendix.rb +3 -1
  9. data/lib/kitchen/directions/bake_chapter_glossary/v1.rb +23 -5
  10. data/lib/kitchen/directions/bake_chapter_introductions.rb +22 -15
  11. data/lib/kitchen/directions/bake_chapter_introductions/chapter_introduction.xhtml.erb +0 -0
  12. data/lib/kitchen/directions/bake_chapter_references/main.rb +1 -2
  13. data/lib/kitchen/directions/bake_chapter_references/v1.rb +26 -12
  14. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +2 -2
  15. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +2 -1
  16. data/lib/kitchen/directions/bake_chapter_solutions/main.rb +11 -0
  17. data/lib/kitchen/directions/bake_chapter_solutions/v1.rb +37 -0
  18. data/lib/kitchen/directions/bake_chapter_summary.rb +13 -6
  19. data/lib/kitchen/directions/bake_example.rb +11 -2
  20. data/lib/kitchen/directions/bake_figure.rb +13 -0
  21. data/lib/kitchen/directions/bake_first_elements.rb +7 -1
  22. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  23. data/lib/kitchen/directions/bake_footnotes/v1.rb +11 -8
  24. data/lib/kitchen/directions/bake_further_research.rb +2 -0
  25. data/lib/kitchen/directions/bake_index/v1.rb +3 -14
  26. data/lib/kitchen/directions/bake_inline_lists.rb +22 -0
  27. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/main.rb +43 -0
  28. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v1.rb +37 -0
  29. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v2.rb +25 -0
  30. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v3.rb +32 -0
  31. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +3 -2
  32. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +10 -1
  33. data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +29 -0
  34. data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -0
  35. data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -24
  36. data/lib/kitchen/directions/bake_numbered_table/v2.rb +31 -0
  37. data/lib/kitchen/directions/bake_preface/main.rb +2 -2
  38. data/lib/kitchen/directions/bake_preface/v1.rb +3 -2
  39. data/lib/kitchen/directions/bake_references/main.rb +7 -0
  40. data/lib/kitchen/directions/bake_references/v2.rb +35 -0
  41. data/lib/kitchen/directions/bake_toc.rb +3 -1
  42. data/lib/kitchen/directions/book_answer_key_container/eob_answer_key_outer_container.xhtml.erb +9 -0
  43. data/lib/kitchen/directions/book_answer_key_container/main.rb +2 -2
  44. data/lib/kitchen/directions/book_answer_key_container/v1.rb +4 -3
  45. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +3 -3
  46. data/lib/kitchen/directions/chapter_review_container/main.rb +2 -2
  47. data/lib/kitchen/directions/chapter_review_container/v1.rb +4 -2
  48. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +13 -0
  49. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +10 -0
  50. data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +49 -0
  51. data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +6 -2
  52. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +27 -0
  53. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +84 -0
  54. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +11 -7
  55. data/lib/kitchen/document.rb +17 -42
  56. data/lib/kitchen/element_base.rb +31 -7
  57. data/lib/kitchen/i18n_string.rb +16 -0
  58. data/lib/kitchen/id_tracker.rb +68 -0
  59. data/lib/kitchen/oven.rb +3 -1
  60. data/lib/kitchen/page_element.rb +2 -3
  61. data/lib/kitchen/patches/array.rb +15 -0
  62. data/lib/kitchen/patches/i18n.rb +34 -0
  63. data/lib/kitchen/patches/integer.rb +24 -0
  64. data/lib/kitchen/patches/nokogiri.rb +7 -0
  65. data/lib/kitchen/version.rb +1 -1
  66. data/lib/locales/en.yml +2 -1
  67. data/lib/locales/es.yml +33 -0
  68. data/lib/locales/pl.yml +3 -1
  69. data/lib/openstax_kitchen.rb +2 -5
  70. data/openstax_kitchen.gemspec +1 -0
  71. metadata +40 -7
  72. data/.github/config.yml +0 -14
  73. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +0 -51
  74. data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +0 -9
  75. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +0 -19
  76. data/lib/kitchen/transliterations.rb +0 -21
@@ -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('div.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('div.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
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::MoveExercisesToEOC
4
+ # The difference from v1 is the presence of a section title
5
+ # and from v2 the lack of additional "os-section-area" and os-#{@klass} wrappers
6
+ class V3
7
+ renderable
8
+
9
+ def bake(chapter:, metadata_source:, klass:, append_to: nil, uuid_prefix: '.')
10
+ @klass = klass
11
+ @metadata = metadata_source.children_to_keep.copy
12
+ @title = I18n.t(:"eoc.#{klass}")
13
+ @uuid_prefix = uuid_prefix
14
+
15
+ exercise_clipboard = Kitchen::Clipboard.new
16
+
17
+ chapter.non_introduction_pages.each do |page|
18
+ sections = page.search("section.#{@klass}")
19
+
20
+ sections.each do |exercise_section|
21
+ exercise_section.first("[data-type='title']")&.trash
22
+
23
+ section_title = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(page: page)
24
+
25
+ exercise_section.exercises.each do |exercise|
26
+ exercise.document.pantry(name: :link_text).store(
27
+ "#{I18n.t(:exercise_label)} #{chapter.count_in(:book)}.#{exercise.count_in(:chapter)}",
28
+ label: exercise.id
29
+ )
30
+ end
31
+
32
+ # Configure section title
33
+ exercise_section.prepend(child: section_title)
34
+ exercise_section.cut(to: exercise_clipboard)
35
+ end
36
+ end
37
+
38
+ return if exercise_clipboard.none?
39
+
40
+ @content = exercise_clipboard.paste
41
+
42
+ append_to_element = append_to || chapter
43
+ @in_composite_chapter = append_to_element.is?(:composite_chapter)
44
+
45
+ append_to_element.append(child: render(file:
46
+ '../../templates/eoc_section_title_template.xhtml.erb'))
47
+ end
48
+ end
49
+ end
@@ -3,11 +3,15 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module MoveSolutionsToAnswerKey
6
- def self.v1(chapter:, metadata_source:, strategy:, append_to:)
6
+ def self.v1(chapter:, metadata_source:, strategy:, append_to:, strategy_options: {}, solutions_plural: true)
7
7
  V1.new.bake(
8
8
  chapter: chapter,
9
9
  metadata_source: metadata_source,
10
- strategy: strategy, append_to: append_to)
10
+ strategy: strategy,
11
+ append_to: append_to,
12
+ strategy_options: strategy_options,
13
+ solutions_plural: solutions_plural
14
+ )
11
15
  end
12
16
  end
13
17
  end