openstax_kitchen 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -3
  3. data/Gemfile.lock +1 -1
  4. data/README.md +7 -0
  5. data/lib/kitchen/directions/bake_book_answer_key/eob_solutions_container.xhtml.erb +9 -0
  6. data/lib/kitchen/directions/bake_book_answer_key/main.rb +11 -0
  7. data/lib/kitchen/directions/bake_book_answer_key/v1.rb +13 -0
  8. data/lib/kitchen/directions/bake_chapter_answer_key/main.rb +14 -0
  9. data/lib/kitchen/directions/bake_chapter_answer_key/strategies/calculus.rb +41 -0
  10. data/lib/kitchen/directions/bake_chapter_answer_key/strategies/uphysics.rb +61 -0
  11. data/lib/kitchen/directions/bake_chapter_answer_key/v1.rb +32 -0
  12. data/lib/kitchen/directions/bake_chapter_glossary.rb +4 -2
  13. data/lib/kitchen/directions/bake_chapter_key_concepts/key_concepts.xhtml.erb +16 -0
  14. data/lib/kitchen/directions/bake_chapter_key_concepts/main.rb +11 -0
  15. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +30 -0
  16. data/lib/kitchen/directions/bake_chapter_key_equations.rb +4 -2
  17. data/lib/kitchen/directions/bake_chapter_review/chapter_review.xhtml.erb +9 -0
  18. data/lib/kitchen/directions/bake_chapter_review/main.rb +11 -0
  19. data/lib/kitchen/directions/bake_chapter_review/v1.rb +13 -0
  20. data/lib/kitchen/directions/bake_chapter_review_exercises/main.rb +15 -0
  21. data/lib/kitchen/directions/bake_chapter_review_exercises/review_exercises.xhtml.erb +10 -0
  22. data/lib/kitchen/directions/bake_chapter_review_exercises/v1.rb +38 -0
  23. data/lib/kitchen/directions/bake_chapter_review_exercises/v2.rb +50 -0
  24. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +11 -0
  25. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +28 -0
  26. data/lib/kitchen/directions/bake_chapter_summary.rb +1 -1
  27. data/lib/kitchen/directions/bake_checkpoint.rb +44 -0
  28. data/lib/kitchen/directions/bake_composite_chapters.rb +14 -0
  29. data/lib/kitchen/directions/bake_equations.rb +27 -0
  30. data/lib/kitchen/directions/bake_example.rb +29 -7
  31. data/lib/kitchen/directions/bake_exercises/main.rb +1 -0
  32. data/lib/kitchen/directions/bake_exercises/v1.rb +34 -31
  33. data/lib/kitchen/directions/bake_non_introduction_pages.rb +26 -0
  34. data/lib/kitchen/directions/bake_notes/bake_autotitled_notes.rb +29 -0
  35. data/lib/kitchen/directions/bake_notes/bake_note_subtitle.rb +18 -0
  36. data/lib/kitchen/directions/{bake_notes.rb → bake_notes/bake_notes.rb} +6 -16
  37. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +63 -0
  38. data/lib/kitchen/directions/bake_notes/bake_unclassified_notes.rb +30 -0
  39. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +11 -0
  40. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +34 -0
  41. data/lib/kitchen/directions/bake_numbered_table/main.rb +2 -2
  42. data/lib/kitchen/directions/bake_numbered_table/v1.rb +17 -3
  43. data/lib/kitchen/directions/bake_page_abstracts.rb +16 -0
  44. data/lib/kitchen/directions/bake_problem_first_elements.rb +16 -0
  45. data/lib/kitchen/directions/bake_stepwise.rb +1 -5
  46. data/lib/kitchen/directions/bake_theorem/main.rb +11 -0
  47. data/lib/kitchen/directions/bake_theorem/v1.rb +28 -0
  48. data/lib/kitchen/directions/bake_toc.rb +6 -0
  49. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +20 -0
  50. data/lib/kitchen/element_base.rb +40 -1
  51. data/lib/kitchen/element_enumerator_base.rb +87 -8
  52. data/lib/kitchen/exercise_element.rb +45 -0
  53. data/lib/kitchen/exercise_element_enumerator.rb +21 -0
  54. data/lib/kitchen/note_element.rb +17 -16
  55. data/lib/kitchen/page_element.rb +8 -0
  56. data/lib/kitchen/recipe.rb +35 -2
  57. data/lib/kitchen/version.rb +1 -1
  58. data/lib/locales/en.yml +9 -7
  59. data/lib/locales/pl.yml +24 -0
  60. data/lib/openstax_kitchen.rb +1 -1
  61. metadata +39 -3
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeChapterReviewExercises
4
+ class V1
5
+ renderable
6
+
7
+ def bake(chapter:, metadata_source:, append_to:, klass:)
8
+ @klass = klass
9
+ @metadata = metadata_source.children_to_keep.copy
10
+ @title = I18n.t(:"eoc.#{klass}")
11
+
12
+ exercise_clipboard = Kitchen::Clipboard.new
13
+
14
+ chapter.non_introduction_pages.each do |page|
15
+ sections = page.search("section.#{@klass}")
16
+
17
+ sections.each do |exercise_section|
18
+ exercise_section.first("[data-type='title']")&.trash
19
+
20
+ exercise_section.exercises.each do |exercise|
21
+ exercise.document.pantry(name: :link_text).store(
22
+ "#{I18n.t(:exercise_label)} #{chapter.count_in(:book)}.#{exercise.count_in(:chapter)}",
23
+ label: exercise.id
24
+ )
25
+ end
26
+
27
+ exercise_section.cut(to: exercise_clipboard)
28
+ end
29
+ end
30
+
31
+ return if exercise_clipboard.none?
32
+
33
+ @content = exercise_clipboard.paste
34
+
35
+ append_to.append(child: render(file: 'review_exercises.xhtml.erb'))
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeChapterReviewExercises
4
+ # Main difference from v1 is the presence of a section title
5
+ # and some additional wrappers
6
+ class V2
7
+ renderable
8
+
9
+ def bake(chapter:, metadata_source:, append_to:, klass:)
10
+ @klass = klass
11
+ @metadata = metadata_source.children_to_keep.copy
12
+ @title = I18n.t(:"eoc.#{klass}")
13
+
14
+ exercise_clipboard = Kitchen::Clipboard.new
15
+
16
+ chapter.non_introduction_pages.each do |page|
17
+ sections = page.search("section.#{@klass}")
18
+
19
+ sections.each do |exercise_section|
20
+ exercise_section.first("[data-type='title']")&.trash
21
+
22
+ # Get parent page title
23
+ section_title = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(page: page)
24
+ exercise_section.exercises.each do |exercise|
25
+ exercise.document.pantry(name: :link_text).store(
26
+ "#{I18n.t(:exercise_label)} #{chapter.count_in(:book)}.#{exercise.count_in(:chapter)}",
27
+ label: exercise.id
28
+ )
29
+ end
30
+
31
+ # Configure section title & wrappers
32
+ exercise_section.prepend(child: section_title)
33
+ exercise_section.wrap('<div class="os-section-area">')
34
+ exercise_section = exercise_section.parent
35
+ exercise_section.cut(to: exercise_clipboard)
36
+ end
37
+ end
38
+
39
+ return if exercise_clipboard.none?
40
+
41
+ @content = <<~HTML
42
+ <div class="os-#{@klass}">
43
+ #{exercise_clipboard.paste}
44
+ </div>
45
+ HTML
46
+
47
+ append_to.append(child: render(file: 'review_exercises.xhtml.erb'))
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeChapterSectionExercises
6
+ def self.v1(chapter:)
7
+ V1.new.bake(chapter: chapter)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeChapterSectionExercises
4
+ class V1
5
+ def bake(chapter:)
6
+ chapter.pages.each do |page|
7
+ page.search('section.section-exercises').each do |section|
8
+ section.wrap(
9
+ %(<div class="os-eos os-section-exercises-container"
10
+ data-uuid-key=".section-exercises">)
11
+ )
12
+
13
+ section_title = I18n.t(
14
+ :section_exercises,
15
+ number: "#{chapter.count_in(:book)}.#{section.count_in(:chapter)}")
16
+
17
+ section.prepend(sibling:
18
+ <<~HTML
19
+ <h3 data-type="document-title">
20
+ <span class="os-text">#{section_title}</span>
21
+ </h3>
22
+ HTML
23
+ )
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -11,7 +11,7 @@ module Kitchen
11
11
  summaries = Clipboard.new
12
12
 
13
13
  # TODO: include specific page types somehow without writing it out
14
- chapter.pages('$:not(.introduction)').each do |page|
14
+ chapter.non_introduction_pages.each do |page|
15
15
  summary = page.summary
16
16
  summary.first("[data-type='title']")&.trash # get rid of old title if exists
17
17
  summary_title = page.title.copy
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeCheckpoint
6
+ def self.v1(checkpoint:, number:)
7
+ checkpoint.wrap_children(class: 'os-note-body')
8
+
9
+ checkpoint.prepend(child:
10
+ <<~HTML
11
+ <div class="os-title">
12
+ <span class="os-title-label">#{I18n.t(:checkpoint)} </span>
13
+ <span class="os-number">#{number}</span>
14
+ <span class="os-divider"> </span>
15
+ </div>
16
+ HTML
17
+ )
18
+
19
+ exercise = checkpoint.exercises.first!
20
+ exercise.search("[data-type='commentary']").trash
21
+
22
+ problem = exercise.problem
23
+ problem.wrap_children(class: 'os-problem-container')
24
+
25
+ solution = exercise.solution
26
+ exercise.add_class('unnumbered') unless solution.present?
27
+ return unless solution.present?
28
+
29
+ solution.id = "#{exercise.id}-solution"
30
+ exercise.add_class('os-hasSolution')
31
+
32
+ solution.replace_children(with:
33
+ <<~HTML
34
+ <span class="os-divider"> </span>
35
+ <a class="os-number" href="##{exercise.id}">#{number}</a>
36
+ <div class="os-solution-container">#{solution.children}</div>
37
+ HTML
38
+ )
39
+
40
+ exercise.add_class('unnumbered')
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeCompositeChapters
6
+ def self.v1(book:)
7
+ book.search("[data-type='composite-chapter']").each do |chapter|
8
+ chapter.first("[data-type='document-title']").id =
9
+ "composite-chapter-#{chapter.count_in(:book)}"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeEquations
6
+ def self.v1(book:)
7
+ book.chapters.search('[data-type="equation"]:not(.unnumbered)').each do |eq|
8
+ chapter = eq.ancestor(:chapter)
9
+ number = "#{chapter.count_in(:book)}.#{eq.count_in(:chapter)}"
10
+
11
+ # Store label information
12
+ equation_label = "#{I18n.t(:equation)} #{number}"
13
+ book.document.pantry(name: :link_text).store equation_label, label: eq.id
14
+
15
+ # Bake the equation
16
+ eq.append(child:
17
+ <<~HTML
18
+ <div class="os-equation-number">
19
+ <span class="os-number">#{number}</span>
20
+ </div>
21
+ HTML
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -4,13 +4,7 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeExample
6
6
  def self.v1(example:, number:, title_tag:)
7
- example.replace_children(with:
8
- <<~HTML
9
- <div class="body">
10
- #{example.children}
11
- </div>
12
- HTML
13
- )
7
+ example.wrap_children(class: 'body')
14
8
 
15
9
  example.prepend(child:
16
10
  <<~HTML
@@ -27,6 +21,34 @@ module Kitchen
27
21
  .store("#{I18n.t(:example_label)} #{number}", label: example.id)
28
22
 
29
23
  example.titles.each { |title| title.name = 'h4' }
24
+
25
+ example.exercises.each do |exercise|
26
+ if (problem = exercise.problem)
27
+ problem.titles.each { |title| title.name = 'h4' }
28
+ problem.wrap_children(class: 'os-problem-container')
29
+ end
30
+
31
+ if (solution = exercise.solution)
32
+ solution.replace_children(with:
33
+ <<~HTML
34
+ <h4 data-type="solution-title">
35
+ <span class="os-title-label">#{I18n.t(:solution)} </span>
36
+ </h4>
37
+ <div class="os-solution-container">#{solution.children}</div>
38
+ HTML
39
+ )
40
+ end
41
+
42
+ exercise.add_class('unnumbered')
43
+
44
+ commentary = exercise.first('[data-type="commentary"]')
45
+ next unless commentary.present?
46
+
47
+ commentary_title = commentary.titles.first
48
+ commentary_title.name = 'h4'
49
+ commentary_title['data-type'] = 'commentary-title'
50
+ commentary_title.wrap_children('span', class: 'os-title-label')
51
+ end
30
52
  end
31
53
  end
32
54
  end
@@ -4,6 +4,7 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeExercises
6
6
  def self.v1(book:)
7
+ warn 'WARNING! deprecated direction used: BakeExecises'
7
8
  V1.new.bake(book: book)
8
9
  end
9
10
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Kitchen::Directions::BakeExercises
4
4
  class V1
5
+ renderable
5
6
  def bake(book:)
6
7
  metadata_elements = book.metadata.children_to_keep.copy
7
8
 
@@ -12,34 +13,20 @@ module Kitchen::Directions::BakeExercises
12
13
  solution_clipboard = Kitchen::Clipboard.new
13
14
  solutions_clipboards.push(solution_clipboard)
14
15
 
15
- chapter.pages('$:not(.introduction)').each do |page|
16
+ chapter.non_introduction_pages.each do |page|
16
17
  exercise_section = page.exercises
17
- exercise_section.first("[data-type='title']")&.trash
18
- exercise_section_title = page.title.copy
19
- exercise_section_title.name = 'h3'
20
- exercise_section_title.replace_children(with: <<~HTML
21
- <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
22
- <span class="os-divider"> </span>
23
- <span class="os-text" data-type="" itemprop="">#{exercise_section_title.children}</span>
24
- HTML
25
- )
18
+ exercise_section.titles.first&.trash
26
19
 
27
- exercise_section.prepend(child:
28
- <<~HTML
29
- <a href="##{page.title.id}">
30
- #{exercise_section_title.paste}
31
- </a>
32
- HTML
33
- )
20
+ bake_exercise_section_title(
21
+ exercise_section: exercise_section, page: page, chapter: chapter)
34
22
 
35
- exercise_section.search("[data-type='exercise']").each do |exercise|
23
+ exercise_section.exercises.each do |exercise|
36
24
  exercise.document.pantry(name: :link_text).store(
37
25
  "#{I18n.t(:exercise_label)} #{chapter.count_in(:book)}.#{exercise.count_in(:chapter)}",
38
26
  label: exercise.id
39
27
  )
40
-
41
28
  bake_exercise_in_place(exercise: exercise)
42
- exercise.first("[data-type='solution']")&.cut(to: solution_clipboard)
29
+ exercise.solution&.cut(to: solution_clipboard)
43
30
  end
44
31
 
45
32
  exercise_section.cut(to: exercise_clipboard)
@@ -65,10 +52,9 @@ module Kitchen::Directions::BakeExercises
65
52
 
66
53
  # Store a paste here to use at end so that uniquifyied IDs match legacy baking
67
54
  eob_metadata = metadata_elements.paste
68
-
69
55
  solutions = solutions_clipboards.map.with_index do |solution_clipboard, index|
70
56
  <<~HTML
71
- <div class="os-eob os-solution-container " data-type="composite-page" data-uuid-key=".solution#{index + 1}">
57
+ <div class="os-eob os-solution-container" data-type="composite-page" data-uuid-key=".solution#{index + 1}">
72
58
  <h2 data-type="document-title">
73
59
  <span class="os-text">#{I18n.t(:chapter)} #{index + 1}</span>
74
60
  </h2>
@@ -83,9 +69,9 @@ module Kitchen::Directions::BakeExercises
83
69
 
84
70
  return if solutions.none?
85
71
 
86
- book.first('body').append(child:
72
+ book.body.append(child:
87
73
  <<~HTML
88
- <div class="os-eob os-solution-container " data-type="composite-chapter" data-uuid-key=".solution">
74
+ <div class="os-eob os-solution-container" data-type="composite-chapter" data-uuid-key=".solution">
89
75
  <h1 data-type="document-title" id="composite-chapter-1">
90
76
  <span class="os-text">#{I18n.t(:eoc_answer_key_title)}</span>
91
77
  </h1>
@@ -99,6 +85,24 @@ module Kitchen::Directions::BakeExercises
99
85
  )
100
86
  end
101
87
 
88
+ def bake_exercise_section_title(exercise_section:, chapter:, page:)
89
+ exercise_section_title = page.title.copy
90
+ exercise_section_title.name = 'h3'
91
+ exercise_section_title.replace_children(with: <<~HTML
92
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
93
+ <span class="os-divider"> </span>
94
+ <span class="os-text" data-type="" itemprop="">#{exercise_section_title.children}</span>
95
+ HTML
96
+ )
97
+ exercise_section.prepend(child:
98
+ <<~HTML
99
+ <a href="##{page.title.id}">
100
+ #{exercise_section_title.paste}
101
+ </a>
102
+ HTML
103
+ )
104
+ end
105
+
102
106
  def bake_exercise_in_place(exercise:)
103
107
  # Bake an exercise in place going from:
104
108
  #
@@ -133,21 +137,20 @@ module Kitchen::Directions::BakeExercises
133
137
  # If there is no solution, don't add the 'os-hasSolution' class and don't
134
138
  # link the number.
135
139
 
136
- problem = exercise.first("[data-type='problem']")
137
- solution = exercise.first("[data-type='solution']")
138
-
139
- problem_number = "<span class='os-number'>#{exercise.count_in(:chapter)}</span>"
140
+ problem = exercise.problem
141
+ solution = exercise.solution
142
+ count_in = exercise.count_in(:chapter)
143
+ problem_number = "<span class='os-number'>#{count_in}</span>"
140
144
 
141
145
  if solution.present?
142
146
  solution.id = "#{exercise.id}-solution"
143
147
 
144
148
  exercise.add_class('os-hasSolution')
145
- problem_number =
146
- "<a href='##{solution.id}' class='os-number' >#{exercise.count_in(:chapter)}</a>"
149
+ problem_number = "<a href='##{solution.id}' class='os-number'>#{count_in}</a>"
147
150
 
148
151
  solution.replace_children(with:
149
152
  <<~HTML
150
- <a class="os-number" href="##{exercise.id}">#{exercise.count_in(:chapter)}</a>
153
+ <a class="os-number" href="##{exercise.id}">#{count_in}</a>
151
154
  <span class="os-divider">. </span>
152
155
  <div class="os-solution-container ">#{solution.children}</div>
153
156
  HTML
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeNonIntroductionPages
6
+ def self.v1(chapter:)
7
+ chapter.non_introduction_pages.each do |page|
8
+ number = "#{chapter.count_in(:book)}.#{page.count_in(:chapter)}"
9
+
10
+ page.search("div[data-type='description']").each(&:trash)
11
+ page.add_class('chapter-content-module')
12
+
13
+ title = page.title
14
+ title.name = 'h2'
15
+ title.replace_children(with:
16
+ <<~HTML
17
+ <span class="os-number">#{number}</span>
18
+ <span class="os-divider"> </span>
19
+ <span data-type="" itemprop="" class="os-text">#{title.text}</span>
20
+ HTML
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeAutotitledNotes
6
+ def self.v1(book:, classes:)
7
+ book.notes.each do |note|
8
+ next unless (note.classes & classes).any?
9
+
10
+ bake_note(note: note)
11
+ end
12
+ end
13
+
14
+ def self.bake_note(note:)
15
+ note.wrap_children(class: 'os-note-body')
16
+
17
+ BakeNoteSubtitle.v1(note: note)
18
+
19
+ note.prepend(child:
20
+ <<~HTML
21
+ <h3 class="os-title" data-type="title">
22
+ <span class="os-title-label">#{note.autogenerated_title}</span>
23
+ </h3>
24
+ HTML
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end