openstax_kitchen 10.0.0 → 11.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Gemfile.lock +2 -2
  4. data/lib/kitchen/chapter_element.rb +8 -0
  5. data/lib/kitchen/directions/bake_annotation_classes/main.rb +12 -0
  6. data/lib/kitchen/directions/bake_annotation_classes/v1.rb +32 -0
  7. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +0 -1
  8. data/lib/kitchen/directions/bake_chapter_references/v1.rb +1 -3
  9. data/lib/kitchen/directions/bake_chapter_summary.rb +1 -1
  10. data/lib/kitchen/directions/bake_eoc_section_content/change_subsection_title_tag.rb +13 -0
  11. data/lib/kitchen/directions/bake_example.rb +2 -0
  12. data/lib/kitchen/directions/bake_first_elements.rb +7 -3
  13. data/lib/kitchen/directions/bake_folio.rb +12 -0
  14. data/lib/kitchen/directions/bake_free_response/v1.rb +1 -1
  15. data/lib/kitchen/directions/bake_further_research.rb +1 -2
  16. data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +57 -16
  17. data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -1
  18. data/lib/kitchen/directions/bake_numbered_table/v2.rb +2 -2
  19. data/lib/kitchen/directions/bake_unit_page_title/v1.rb +4 -2
  20. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +32 -21
  21. data/lib/kitchen/directions/move_custom_section_to_eoc_container/main.rb +1 -3
  22. data/lib/kitchen/directions/move_custom_section_to_eoc_container/v1.rb +2 -2
  23. data/lib/kitchen/directions/move_exercises_to_eoc/v1.rb +1 -2
  24. data/lib/kitchen/directions/move_exercises_to_eoc/v2.rb +0 -1
  25. data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +1 -2
  26. data/lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_exercise_section.rb +40 -0
  27. data/lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_numbered_note.rb +33 -0
  28. data/lib/kitchen/directions/move_solutions_to_answer_key/solution_area_snippet.rb +12 -0
  29. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/calculus.rb +1 -1
  30. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/contemporary_math.rb +4 -21
  31. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +1 -1
  32. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +18 -39
  33. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/uphysics.rb +6 -48
  34. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +3 -2
  35. data/lib/kitchen/element_base.rb +0 -4
  36. data/lib/kitchen/page_element.rb +12 -1
  37. data/lib/kitchen/table_element.rb +25 -0
  38. data/lib/kitchen/version.rb +1 -1
  39. data/lib/locales/en.yml +3 -0
  40. data/lib/locales/es.yml +3 -0
  41. metadata +9 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a071ba6e289c222a7333f401c7d6bd25d6dba9527253b6c6ae123169d9b6425
4
- data.tar.gz: 2debc535f61a289f6668019f1eeb5cd639efaf8d49172d668f8b602e02e91b07
3
+ metadata.gz: e6964a7fe85234e82e7f54f3b6d4980633f4f4c29c49d3123743c214d9f46653
4
+ data.tar.gz: 2426f1990ae74d35d2ac098bcf7d5c09aa5094eeef598dd9658d8fedf97916c4
5
5
  SHA512:
6
- metadata.gz: 6bfeae3a664c95c17249ab32a8bba863091fb1e23f501273fd57d9752688c29ba9877b5a6404393dc88ae993f16af3f89fa768e3984cf81233908ab238b0350a
7
- data.tar.gz: '086fa06f8f7eb33f3908c15ba0172a02a1738c943ba87b25245f63626cda51e5163edbece95cdce2ce1907d5815aefd179db7fb7e3a4fe2a7165c623c5120ede'
6
+ metadata.gz: faba0041d8c958c3ffa369dbe2d0c5453f8a236bedd0654e362afa65c84093ec22771dadaa9a313e688f6644681267b63f263ba60af9d1b81a211bc3c98a5df1
7
+ data.tar.gz: a1e8ff40b3377508904ab62980302f129527755512f58506c805d7ae1507977ce65f1c993786cdeffc5f3871e4448e5d4df264979539d60f995d7f9c7b3ece48
data/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [11.0.0] - 2021-08-6
10
+
11
+ * Add `ChangeSubsectionTitleTag` direction for modifying eoc sections (minor)
12
+ * Add `MoveSolutionsFromNumberedNote`, `MoveSolutionsFromExerciseSection`, and `SolutionAreaSnippet` for answer key baking (minor)
13
+ * Refactor the following `Strategies`: contemporary math, precalculus, uphysics (minor)
14
+ * Fix `BakeUnitPageTite` to utilize only pages which are direct children of the unit (patch)
15
+ * Patch `BakeFirstElements` to include first figure elements (patch)
16
+ * Refactor `MoveCustomSectionToEocContainer` to remove `include_intro_page` (major)
17
+ * Update `BakeFirstElement` to optionally add the `has-first-inline-element` class (patch)
18
+ * Patch `BakeExample` crashing if an example has commentary but no title (patch)
19
+ * Refactor `EocSectionTitleLinkSnippet` to only have v1 with optional params (major)
20
+ * Adds `PageElement#count_in_chapter_without_intro_page` (minor)
21
+ * Adds `ChapterElement#has_introduction?` (minor)
22
+ * Adds `BakeFolio` to set spanish translation variables in the html tag for folio-pdf purposes (minor)
23
+ * Create `BakeAnnotationClasses` v1 for English Composition (minor)
24
+
9
25
  ## [10.0.0] - 2021-07-30
10
26
 
11
27
  * Add support for baking multipart questions to `BakeNumberedExercise` (minor)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openstax_kitchen (10.0.0)
4
+ openstax_kitchen (11.0.0)
5
5
  activesupport
6
6
  i18n
7
7
  nokogiri
@@ -99,7 +99,7 @@ GEM
99
99
  tins (~> 1.0)
100
100
  tins (1.26.0)
101
101
  sync
102
- twitter_cldr (6.6.0)
102
+ twitter_cldr (6.7.0)
103
103
  camertron-eprun
104
104
  cldr-plurals-runtime-rb (~> 1.1)
105
105
  tzinfo
@@ -44,6 +44,14 @@ module Kitchen
44
44
  pages('$.introduction').first
45
45
  end
46
46
 
47
+ # Returns true if the chapter has an introduction
48
+ #
49
+ # @return [Boolean]
50
+ #
51
+ def has_introduction?
52
+ @has_introduction ||= introduction_page.present?
53
+ end
54
+
47
55
  # Returns an enumerator for the glossaries
48
56
  #
49
57
  # @return [ElementEnumerator]
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeAnnotationClasses
6
+ def self.v1(chapter:)
7
+ V1.new.bake(
8
+ chapter: chapter)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeAnnotationClasses
4
+ class V1
5
+ def bake(chapter:)
6
+ chapter.search('p.annotation').each do |annotation|
7
+ annotation.wrap_children('span', class: 'os-text')
8
+ annotation.prepend(child:
9
+ <<~HTML
10
+ <div class="os-icons"></div>
11
+ HTML
12
+ )
13
+ end
14
+ annotation_icon_classes = %w[linguistic-icon
15
+ culture-icon
16
+ dreaming-icon
17
+ visual-icon
18
+ speech-icon
19
+ auditory-icon
20
+ kinesthetic-icon]
21
+ annotation_icon_classes.each do |annotation_icon_class|
22
+ chapter.search("p.#{annotation_icon_class}").each do |annotation_with_icon_class|
23
+ annotation_with_icon_class.search('div.os-icons').first.append(child:
24
+ <<~HTML
25
+ <span class = "#{annotation_icon_class}"></span>
26
+ HTML
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -10,7 +10,6 @@ module Kitchen::Directions::BakeChapterKeyConcepts
10
10
  uuid_key: "#{uuid_prefix}key-concepts",
11
11
  section_selector: 'section.key-concepts',
12
12
  append_to: append_to || chapter,
13
- include_intro_page: false,
14
13
  wrap_section: true, wrap_content: true
15
14
  ) do |section|
16
15
  Kitchen::Directions::RemoveSectionTitle.v1(section: section)
@@ -3,9 +3,7 @@
3
3
  module Kitchen::Directions::BakeChapterReferences
4
4
  class V1
5
5
  def bake(chapter:, metadata_source:, uuid_prefix: '.', klass: 'references')
6
- bake_page_references(page: chapter.introduction_page)
7
-
8
- chapter.non_introduction_pages.each do |page|
6
+ chapter.pages.each do |page|
9
7
  bake_page_references(page: page)
10
8
  end
11
9
 
@@ -18,7 +18,7 @@ module Kitchen
18
18
  def bake(chapter:, metadata_source:, uuid_prefix: '.', klass: 'summary')
19
19
  summaries = Clipboard.new
20
20
 
21
- chapter.non_introduction_pages.each do |page|
21
+ chapter.pages.each do |page|
22
22
  summary = page.summary
23
23
 
24
24
  next if summary.nil?
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module ChangeSubsectionTitleTag
6
+ def self.v1(section:)
7
+ section.search('section').each do |subsection|
8
+ subsection.first('h4').name = 'h5'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -54,6 +54,8 @@ module Kitchen
54
54
  next unless commentary.present?
55
55
 
56
56
  commentary_title = commentary.titles.first
57
+ next unless commentary_title.present?
58
+
57
59
  commentary_title.name = 'h4'
58
60
  commentary_title['data-type'] = 'commentary-title'
59
61
  commentary_title.wrap_children('span', class: 'os-title-label')
@@ -3,13 +3,15 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeFirstElements
6
- def self.v1(within:)
6
+ def self.v1(within:, first_inline_list: false)
7
7
  # add has-first-element class
8
8
  selectors = [
9
9
  'div.os-problem-container > div.os-table',
10
10
  'div.os-problem-container > span[data-type="media"]',
11
+ 'div.os-problem-container > div.os-figure',
11
12
  'div.os-solution-container > div.os-table',
12
- 'div.os-solution-container > span[data-type="media"]'
13
+ 'div.os-solution-container > span[data-type="media"]',
14
+ 'div.os-solution-container > div.os-figure'
13
15
  ]
14
16
  selectors.each do |selector|
15
17
  within.search("#{selector}:first-child").each do |problem|
@@ -18,9 +20,11 @@ module Kitchen
18
20
  end
19
21
  end
20
22
 
23
+ return unless first_inline_list
24
+
21
25
  # add first-inline-element class
22
26
  inline_selector = 'div.os-solution-container > ol[type="1"]:first-child,' \
23
- 'div.os-problem-container > ol[type="1"]:first-child'
27
+ 'div.os-problem-container > ol[type="1"]:first-child'
24
28
  within.search(inline_selector).each do |inline_list|
25
29
  inline_list.add_class('first-inline-list-element')
26
30
  inline_list.parent.add_class('has-first-inline-list-element')
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeFolio
6
+ def self.v1(book:)
7
+ book['data-pdf-folio-preface-message'] = I18n.t(:"folio.preface")
8
+ book['data-pdf-folio-access-message'] = I18n.t(:"folio.access_for_free")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -8,7 +8,7 @@ module Kitchen::Directions::BakeFreeResponse
8
8
  @metadata_elements = metadata_source.children_to_keep.copy
9
9
 
10
10
  @free_response_clipboard = Kitchen::Clipboard.new
11
- chapter.non_introduction_pages.each do |page|
11
+ chapter.pages.each do |page|
12
12
  free_response_questions = page.free_response
13
13
  next if free_response_questions.none?
14
14
 
@@ -20,8 +20,7 @@ module Kitchen
20
20
  container_key: 'further-research',
21
21
  uuid_key: "#{uuid_prefix}further-research",
22
22
  section_selector: 'section.further-research',
23
- append_to: nil,
24
- include_intro_page: false
23
+ append_to: nil
25
24
  ) do |further_research|
26
25
  RemoveSectionTitle.v1(section: further_research)
27
26
  title = EocSectionTitleLinkSnippet.v1(page: further_research.ancestor(:page))
@@ -5,24 +5,65 @@ module Kitchen
5
5
  # Bake directions for table body
6
6
  #
7
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 if 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
8
+ class V1
9
+ renderable
10
+ class CustomBody
11
+ attr_reader :table
12
+ attr_reader :klass
13
+ attr_reader :fake_title_class
14
+ attr_reader :fake_title
15
+ attr_reader :to_trash
16
+
17
+ def initialize(table:, klass:, fake_title_class: nil, fake_title: nil, to_trash: nil)
18
+ @table = table
19
+ @klass = klass
20
+ @fake_title_class = fake_title_class
21
+ @fake_title = fake_title
22
+ @to_trash = to_trash
23
+ end
24
+
25
+ def modify_body(has_fake_title: false)
26
+ @table.parent.add_class("os-#{@klass}-container")
27
+
28
+ return unless has_fake_title
29
+
30
+ @table.prepend(sibling:
31
+ <<~HTML
32
+ <div class="#{@fake_title_class}">#{@fake_title}</div>
33
+ HTML
34
+ )
35
+ @to_trash.trash
36
+ end
23
37
  end
24
38
 
25
- table.parent.add_class('os-column-header-container') if table.column_header?
39
+ def bake(table:, number:)
40
+ table.remove_attribute('summary')
41
+ table.wrap(%(<div class="os-table">))
42
+
43
+ table_label = "#{I18n.t(:table_label)} #{number}"
44
+ table.pantry(name: :link_text).store table_label, label: table.id if table.id
45
+
46
+ if table.top_titled?
47
+ custom_table = CustomBody.new(table: table,
48
+ klass: 'top-titled',
49
+ fake_title_class: 'os-table-title',
50
+ fake_title: table.title,
51
+ to_trash: table.title_row)
52
+
53
+ custom_table.modify_body(has_fake_title: true)
54
+ elsif table.top_captioned?
55
+ custom_table = CustomBody.new(table: table,
56
+ klass: 'top-captioned',
57
+ fake_title_class: 'os-top-caption',
58
+ fake_title: table.caption_title,
59
+ to_trash: table.top_caption)
60
+
61
+ custom_table.modify_body(has_fake_title: true)
62
+ elsif table.column_header?
63
+ custom_table = CustomBody.new(table: table, klass: 'column-header')
64
+ custom_table.modify_body(has_fake_title: false)
65
+ end
66
+ end
26
67
  end
27
68
  end
28
69
  end
@@ -4,7 +4,7 @@ module Kitchen::Directions::BakeNumberedTable
4
4
  class V1
5
5
 
6
6
  def bake(table:, number:, always_caption: false)
7
- Kitchen::Directions::BakeTableBody.v1(table: table, number: number)
7
+ Kitchen::Directions::BakeTableBody::V1.new.bake(table: table, number: number)
8
8
 
9
9
  # TODO: extra spaces added here to match legacy implementation, but probably not meaningful?
10
10
  new_caption = ''
@@ -6,10 +6,10 @@ module Kitchen::Directions::BakeNumberedTable
6
6
  class V2
7
7
 
8
8
  def bake(table:, number:)
9
- Kitchen::Directions::BakeTableBody.v1(table: table, number: number)
9
+ Kitchen::Directions::BakeTableBody::V1.new.bake(table: table, number: number)
10
10
 
11
11
  caption = ''
12
- if table&.caption&.first("span[data-type='title']")
12
+ if table&.caption&.first("span[data-type='title']") && !table.top_captioned?
13
13
  caption_el = table.caption
14
14
  caption_el.add_class('os-caption')
15
15
  caption_el.name = 'span'
@@ -3,8 +3,10 @@
3
3
  module Kitchen::Directions::BakeUnitPageTitle
4
4
  class V1
5
5
  def bake(book:)
6
- book.units.pages.each do |page|
7
- compose_unit_page_title(page: page)
6
+ book.units.each do |unit|
7
+ unit.element_children.only(Kitchen::PageElement).each do |page|
8
+ compose_unit_page_title(page: page)
9
+ end
8
10
  end
9
11
  end
10
12
 
@@ -3,30 +3,41 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module EocSectionTitleLinkSnippet
6
- def self.v1(page:)
7
- chapter = page.ancestor(:chapter)
8
- <<~HTML
9
- <a href="##{page.title.id}">
10
- <h3 data-type="document-title" id="#{page.title.copied_id}">
11
- <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
6
+ def self.v1(page:, title_tag: 'h3', wrapper: 'link')
7
+ if page.is_introduction?
8
+ os_number = ''
9
+ else
10
+ chapter = page.ancestor(:chapter)
11
+ os_number =
12
+ <<~HTML
13
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in_chapter_without_intro_page}</span>
12
14
  <span class="os-divider"> </span>
13
- <span class="os-text" data-type="" itemprop="">#{page.title_text}</span>
14
- </h3>
15
- </a>
16
- HTML
17
- end
15
+ HTML
16
+ end
18
17
 
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>
18
+ title_snippet = <<~HTML
19
+ <#{title_tag} data-type="document-title" id="#{page.title.copied_id}">
20
+ #{os_number}
21
+ <span class="os-text" data-type="" itemprop="">#{page.title_text}</span>
22
+ </#{title_tag}>
29
23
  HTML
24
+
25
+ case wrapper
26
+ when 'link'
27
+ <<~HTML
28
+ <a href="##{page.title.id}">
29
+ #{title_snippet}
30
+ </a>
31
+ HTML
32
+ when 'div'
33
+ <<~HTML
34
+ <div>
35
+ #{title_snippet}
36
+ </div>
37
+ HTML
38
+ else
39
+ title_snippet
40
+ end
30
41
  end
31
42
  end
32
43
  end
@@ -14,11 +14,10 @@ module Kitchen
14
14
  # @param uuid_key [String] the uuid key for the wrapper class, e.g. `'.summary'`
15
15
  # @param section_selector [String] the selector for the section to be moved, e.g. `'section.summary'`
16
16
  # @param append_to [ElementBase] the element to be appended. Defaults to the value of `chapter` param if none given.
17
- # @param include_intro_page [Boolean] control the introduction page for the chapter should be searched for a section to move, default is true
18
17
  # @return [ElementBase] the append_to element with container appended
19
18
  #
20
19
  def self.v1(chapter:, metadata_source:, container_key:, uuid_key:,
21
- section_selector:, append_to: nil, include_intro_page: true,
20
+ section_selector:, append_to: nil,
22
21
  wrap_section: false, wrap_content: false)
23
22
  V1.new.bake(
24
23
  chapter: chapter,
@@ -27,7 +26,6 @@ module Kitchen
27
26
  uuid_key: uuid_key,
28
27
  section_selector: section_selector,
29
28
  append_to: append_to || chapter,
30
- include_intro_page: include_intro_page,
31
29
  wrap_section: wrap_section,
32
30
  wrap_content: wrap_content
33
31
  ) do |section|
@@ -5,10 +5,10 @@
5
5
  module Kitchen::Directions::MoveCustomSectionToEocContainer
6
6
  class V1
7
7
  def bake(chapter:, metadata_source:, container_key:, uuid_key:,
8
- section_selector:, append_to:, include_intro_page:, wrap_section:, wrap_content:,
8
+ section_selector:, append_to:, wrap_section:, wrap_content:,
9
9
  &block)
10
10
  section_clipboard = Kitchen::Clipboard.new
11
- pages = include_intro_page ? chapter.pages : chapter.non_introduction_pages
11
+ pages = chapter.pages
12
12
  sections = pages.search(section_selector)
13
13
  sections.each(&block)
14
14
  if wrap_section
@@ -9,8 +9,7 @@ module Kitchen::Directions::MoveExercisesToEOC
9
9
  container_key: klass,
10
10
  uuid_key: "#{uuid_prefix}#{klass}",
11
11
  section_selector: "section.#{klass}",
12
- append_to: append_to || chapter,
13
- include_intro_page: false
12
+ append_to: append_to || chapter
14
13
  ) do |exercise_section|
15
14
  Kitchen::Directions::RemoveSectionTitle.v1(section: exercise_section)
16
15
  end
@@ -12,7 +12,6 @@ module Kitchen::Directions::MoveExercisesToEOC
12
12
  uuid_key: "#{uuid_prefix}#{klass}",
13
13
  section_selector: "section.#{klass}",
14
14
  append_to: append_to || chapter,
15
- include_intro_page: false,
16
15
  wrap_section: true, wrap_content: true
17
16
  ) do |section|
18
17
  Kitchen::Directions::RemoveSectionTitle.v1(section: section)
@@ -11,8 +11,7 @@ module Kitchen::Directions::MoveExercisesToEOC
11
11
  container_key: klass,
12
12
  uuid_key: "#{uuid_prefix}#{klass}",
13
13
  section_selector: "section.#{klass}",
14
- append_to: append_to || chapter,
15
- include_intro_page: false
14
+ append_to: append_to || chapter
16
15
  ) do |exercise_section|
17
16
  Kitchen::Directions::RemoveSectionTitle.v1(section: exercise_section)
18
17
  title = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::MoveSolutionsFromExerciseSection
4
+ def self.v1(chapter:, append_to:, section_class:, title_number: nil)
5
+ V1.new.bake(chapter: chapter, append_to: append_to, section_class: section_class,
6
+ title_number: title_number)
7
+ end
8
+
9
+ class V1
10
+ def bake(chapter:, append_to:, section_class:, title_number:)
11
+ solutions_clipboard = Kitchen::Clipboard.new
12
+ chapter.search("section.#{section_class}").exercises.each do |exercise|
13
+ solution = exercise.solution
14
+ next unless solution
15
+
16
+ solution.cut(to: solutions_clipboard)
17
+ end
18
+
19
+ return if solutions_clipboard.items.empty?
20
+
21
+ title_text = \
22
+ if title_number
23
+ I18n.t(:"eoc.#{section_class}", number: title_number)
24
+ else
25
+ I18n.t(:"eoc.#{section_class}")
26
+ end
27
+ title = <<~HTML
28
+ <h3 data-type="title">
29
+ <span class="os-title-label">#{title_text}</span>
30
+ </h3>
31
+ HTML
32
+
33
+ append_to.append(child:
34
+ Kitchen::Directions::SolutionAreaSnippet.v1(
35
+ title: title, solutions_clipboard: solutions_clipboard
36
+ )
37
+ )
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::MoveSolutionsFromNumberedNote
4
+ def self.v1(chapter:, append_to:, note_class:)
5
+ V1.new.bake(chapter: chapter, append_to: append_to, note_class: note_class)
6
+ end
7
+
8
+ class V1
9
+ def bake(chapter:, append_to:, note_class:)
10
+ solutions_clipboard = Kitchen::Clipboard.new
11
+ chapter.notes("$.#{note_class}").exercises.each do |exercise|
12
+ solution = exercise.solution
13
+ next unless solution
14
+
15
+ solution.cut(to: solutions_clipboard)
16
+ end
17
+
18
+ return if solutions_clipboard.items.empty?
19
+
20
+ title = <<~HTML
21
+ <h3 data-type="title">
22
+ <span class="os-title-label">#{I18n.t(:"notes.#{note_class}")}</span>
23
+ </h3>
24
+ HTML
25
+
26
+ append_to.append(child:
27
+ Kitchen::Directions::SolutionAreaSnippet.v1(
28
+ title: title, solutions_clipboard: solutions_clipboard
29
+ )
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::SolutionAreaSnippet
4
+ def self.v1(title:, solutions_clipboard:)
5
+ <<~HTML
6
+ <div class="os-solution-area">
7
+ #{title}
8
+ #{solutions_clipboard.paste}
9
+ </div>
10
+ HTML
11
+ end
12
+ end
@@ -25,7 +25,7 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
25
25
  protected
26
26
 
27
27
  def append_solution_area(title, clipboard, append_to)
28
- append_to.add_child(
28
+ append_to.append(child:
29
29
  <<~HTML
30
30
  <div class="os-solution-area">
31
31
  <h3 data-type="title">
@@ -4,36 +4,19 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
4
4
  module Strategies
5
5
  class ContemporaryMath
6
6
  def bake(chapter:, append_to:)
7
- solutions_clipboard = Kitchen::Clipboard.new
7
+ # Hacky numbering fix
8
8
  chapter.notes('$.your-turn').exercises.each do |exercise|
9
9
  solution = exercise.solution
10
10
  next unless solution
11
11
 
12
- # Hacky numbering fix
13
12
  number = exercise.ancestor(:note).count_in(:chapter)
14
13
  solution.first('a.os-number').inner_html = number.to_s
15
14
  solution.first('span.os-divider').inner_html = '. '
16
- solution.cut(to: solutions_clipboard)
17
15
  end
18
- title = <<~HTML
19
- <h3 data-type="title">
20
- <span class="os-title-label">#{I18n.t(:'notes.your-turn')}</span>
21
- </h3>
22
- HTML
23
- append_solution_area(title: title, solutions: solutions_clipboard,
24
- append_to: append_to)
25
- end
26
-
27
- def append_solution_area(title:, solutions:, append_to:)
28
- append_to = append_to.add_child(
29
- <<~HTML
30
- <div class="os-solution-area">
31
- #{title}
32
- </div>
33
- HTML
34
- ).first
35
16
 
36
- append_to.add_child(solutions.paste)
17
+ Kitchen::Directions::MoveSolutionsFromNumberedNote.v1(
18
+ chapter: chapter, append_to: append_to, note_class: 'your-turn'
19
+ )
37
20
  end
38
21
  end
39
22
  end
@@ -12,7 +12,7 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
12
12
  def bake_section(chapter:, append_to:)
13
13
  @selectors.each do |selector|
14
14
  chapter.search("#{selector} div[data-type='solution']").each do |solution|
15
- append_to.add_child(solution.cut.to_s)
15
+ append_to.append(child: solution.cut.to_s)
16
16
  end
17
17
  end
18
18
  end
@@ -9,40 +9,25 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
9
9
  # Bake section exercises
10
10
  chapter.non_introduction_pages.each do |page|
11
11
  number = "#{chapter.count_in(:book)}.#{page.count_in(:chapter)}"
12
- bake_section(chapter: page, append_to: append_to, klass: 'section-exercises',
13
- number: number)
12
+ Kitchen::Directions::MoveSolutionsFromExerciseSection.v1(
13
+ chapter: page, append_to: append_to, section_class: 'section-exercises',
14
+ title_number: number
15
+ )
14
16
  end
15
17
 
16
18
  # Bake other types of exercises
17
19
  classes = %w[review-exercises practice-test]
18
20
  classes.each do |klass|
19
- bake_section(chapter: chapter, append_to: append_to, klass: klass)
21
+ Kitchen::Directions::MoveSolutionsFromExerciseSection.v1(
22
+ chapter: chapter, append_to: append_to, section_class: klass
23
+ )
20
24
  end
21
25
  end
22
26
 
23
27
  protected
24
28
 
25
- def bake_section(chapter:, append_to:, klass:, number: nil)
26
- section_solutions_set = Kitchen::Clipboard.new
27
- chapter.search("section.#{klass}").each do |section|
28
- section.search('div[data-type="solution"]').each do |solution|
29
- solution.cut(to: section_solutions_set)
30
- end
31
- end
32
-
33
- return if section_solutions_set.items.empty?
34
-
35
- title = <<~HTML
36
- <h3 data-type="title">
37
- <span class="os-title-label">#{I18n.t(:"eoc.#{klass}", number: number)}</span>
38
- </h3>
39
- HTML
40
-
41
- append_solution_area(title: title, solutions: section_solutions_set, append_to: append_to)
42
- end
43
-
44
29
  def try_note_solutions(chapter:, append_to:)
45
- append_to.add_child(
30
+ append_to.append(child:
46
31
  <<~HTML
47
32
  <div class="os-module-reset-solution-area os-try-solution-area">
48
33
  <h3 data-type="title">
@@ -51,7 +36,7 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
51
36
  </div>
52
37
  HTML
53
38
  )
54
- chapter.non_introduction_pages.each do |page|
39
+ chapter.pages.each do |page|
55
40
  solutions = Kitchen::Clipboard.new
56
41
  page.notes('$.try').each do |note|
57
42
  note.exercises.each do |exercise|
@@ -61,24 +46,18 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
61
46
  end
62
47
  next if solutions.items.empty?
63
48
 
64
- title_snippet = Kitchen::Directions::EocSectionTitleLinkSnippet.v2(page: page)
49
+ title_snippet = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(
50
+ page: page,
51
+ wrapper: 'div'
52
+ )
65
53
 
66
- append_solution_area(title: title_snippet, solutions: solutions,
67
- append_to: append_to.search('div.os-try-solution-area').first)
54
+ append_to.first('div.os-try-solution-area').append(child:
55
+ Kitchen::Directions::SolutionAreaSnippet.v1(
56
+ title: title_snippet, solutions_clipboard: solutions
57
+ )
58
+ )
68
59
  end
69
60
  end
70
-
71
- def append_solution_area(title:, solutions:, append_to:)
72
- append_to = append_to.add_child(
73
- <<~HTML
74
- <div class="os-solution-area">
75
- #{title}
76
- </div>
77
- HTML
78
- ).first
79
-
80
- append_to.add_child(solutions.paste)
81
- end
82
61
  end
83
62
  end
84
63
  end
@@ -4,58 +4,16 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
4
4
  module Strategies
5
5
  class UPhysics
6
6
  def bake(chapter:, append_to:)
7
- bake_from_notes(chapter: chapter, append_to: append_to, klass: 'check-understanding')
7
+ Kitchen::Directions::MoveSolutionsFromNumberedNote.v1(
8
+ chapter: chapter, append_to: append_to, note_class: 'check-understanding'
9
+ )
8
10
 
9
11
  classes = %w[review-conceptual-questions review-problems review-additional-problems
10
12
  review-challenge]
11
13
  classes.each do |klass|
12
- bake_section(chapter: chapter, append_to: append_to, klass: klass)
13
- end
14
- end
15
-
16
- protected
17
-
18
- def bake_section(chapter:, append_to:, klass:)
19
- section_solutions_set = []
20
- chapter.search(".#{klass}").each do |section|
21
- section.search('div[data-type="solution"]').each do |solution|
22
- section_solutions_set.push(solution.cut)
23
- end
24
- end
25
-
26
- return if section_solutions_set.empty?
27
-
28
- title = I18n.t(:"eoc.#{klass}")
29
- append_solution_area(title, section_solutions_set, append_to)
30
- end
31
-
32
- def bake_from_notes(chapter:, append_to:, klass:)
33
- solutions = []
34
- chapter.notes("$.#{klass}").each do |note|
35
- note.exercises.each do |exercise|
36
- solution = exercise.solution
37
- solutions.push(solution.cut) if solution
38
- end
39
- end
40
- return if solutions.empty?
41
-
42
- title = I18n.t(:"notes.#{klass}")
43
- append_solution_area(title, solutions, append_to)
44
- end
45
-
46
- def append_solution_area(title, solutions, append_to)
47
- append_to = append_to.add_child(
48
- <<~HTML
49
- <div class="os-solution-area">
50
- <h3 data-type="title">
51
- <span class="os-title-label">#{title}</span>
52
- </h3>
53
- </div>
54
- HTML
55
- ).first
56
-
57
- solutions.each do |solution|
58
- append_to.add_child(solution.raw)
14
+ Kitchen::Directions::MoveSolutionsFromExerciseSection.v1(
15
+ chapter: chapter, append_to: append_to, section_class: klass
16
+ )
59
17
  end
60
18
  end
61
19
  end
@@ -23,10 +23,11 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
23
23
  end
24
24
 
25
25
  solutions_or_solution = solutions_plural ? 'solutions' : 'solution'
26
+ uuid_key = ".#{solutions_or_solution}#{chapter.count_in(:book)}"
26
27
  append_to.append(child:
27
28
  <<~HTML
28
29
  <div class="os-eob os-#{solutions_or_solution}-container" data-type="composite-page" \
29
- data-uuid-key=".#{solutions_or_solution}#{chapter.count_in(:book)}">
30
+ data-uuid-key="#{uuid_key}">
30
31
  <h2 data-type="document-title">
31
32
  <span class="os-text">#{I18n.t(:chapter)} #{chapter.count_in(:book)}</span>
32
33
  </h2>
@@ -37,7 +38,7 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
37
38
  </div>
38
39
  HTML
39
40
  )
40
- strategy.bake(chapter: chapter, append_to: append_to.last_element)
41
+ strategy.bake(chapter: chapter, append_to: append_to.first("[data-uuid-key='#{uuid_key}']"))
41
42
  end
42
43
  # rubocop:enable Metrics/ParameterLists
43
44
  end
@@ -722,10 +722,6 @@ module Kitchen
722
722
  end
723
723
  end
724
724
 
725
- def last_element
726
- node.last_element_child
727
- end
728
-
729
725
  # @!method pages
730
726
  # Returns a pages enumerator
731
727
  def_delegators :as_enumerator, :pages, :chapters, :terms, :figures, :notes, :tables, :examples,
@@ -58,7 +58,18 @@ module Kitchen
58
58
  # @return [Boolean]
59
59
  #
60
60
  def is_introduction?
61
- has_class?('introduction')
61
+ @is_introduction ||= has_class?('introduction')
62
+ end
63
+
64
+ # Returns replaces generic call to page.count_in(:chapter)
65
+ #
66
+ # @raise [StandardError] if called on an introduction page
67
+ # @return [Integer]
68
+ #
69
+ def count_in_chapter_without_intro_page
70
+ raise 'Introduction pages cannot be counted with this method' if is_introduction?
71
+
72
+ count_in(:chapter) - (ancestor(:chapter).has_introduction? ? 1 : 0)
62
73
  end
63
74
 
64
75
  # Returns true if this page is a preface
@@ -48,6 +48,31 @@ module Kitchen
48
48
  has_class?('top-titled')
49
49
  end
50
50
 
51
+ # Returns an element for the top caption, if present
52
+ #
53
+ # @return [Element, nil]
54
+ #
55
+ def top_caption
56
+ top_captioned? ? first('caption') : nil
57
+ end
58
+
59
+ # Returns the caption title nodes
60
+ #
61
+ # @return [Nokogiri::XML::NodeSet]
62
+ #
63
+ def caption_title
64
+ top_caption&.first('span[data-type="title"]')&.children
65
+ end
66
+
67
+ # Returns true if the table has a caption at the top
68
+ # that transforms to top title
69
+ #
70
+ # @return [Boolean]
71
+ #
72
+ def top_captioned?
73
+ has_class?('top-captioned')
74
+ end
75
+
51
76
  # Returns true if the table is unnumbered
52
77
  #
53
78
  # @return [Boolean]
@@ -3,5 +3,5 @@
3
3
  # A library for modifying the structure of OpenStax book XML.
4
4
  #
5
5
  module Kitchen
6
- VERSION = '10.0.0'
6
+ VERSION = '11.0.0'
7
7
  end
data/lib/locales/en.yml CHANGED
@@ -36,3 +36,6 @@ en:
36
36
  key-concepts: Key Concepts
37
37
  references: References
38
38
  solutions: Solutions
39
+ folio:
40
+ preface: Preface
41
+ access_for_free: Access for free at openstax.org
data/lib/locales/es.yml CHANGED
@@ -33,3 +33,6 @@ es:
33
33
  summary: Resumen
34
34
  further-research: Investigación Adicional
35
35
  references: Referencias
36
+ folio:
37
+ preface: Prefacio
38
+ access_for_free: Acceso gratis en openstax.org
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openstax_kitchen
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.0.0
4
+ version: 11.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Slavinsky
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-30 00:00:00.000000000 Z
11
+ date: 2021-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -243,6 +243,8 @@ files:
243
243
  - lib/kitchen/counter.rb
244
244
  - lib/kitchen/debug/print_recipe_error.rb
245
245
  - lib/kitchen/directions/.rubocop.yml
246
+ - lib/kitchen/directions/bake_annotation_classes/main.rb
247
+ - lib/kitchen/directions/bake_annotation_classes/v1.rb
246
248
  - lib/kitchen/directions/bake_appendix.rb
247
249
  - lib/kitchen/directions/bake_chapter_glossary/main.rb
248
250
  - lib/kitchen/directions/bake_chapter_glossary/v1.rb
@@ -263,11 +265,13 @@ files:
263
265
  - lib/kitchen/directions/bake_checkpoint.rb
264
266
  - lib/kitchen/directions/bake_composite_chapters.rb
265
267
  - lib/kitchen/directions/bake_composite_pages.rb
268
+ - lib/kitchen/directions/bake_eoc_section_content/change_subsection_title_tag.rb
266
269
  - lib/kitchen/directions/bake_eoc_section_content/remove_section_title.rb
267
270
  - lib/kitchen/directions/bake_equations.rb
268
271
  - lib/kitchen/directions/bake_example.rb
269
272
  - lib/kitchen/directions/bake_figure.rb
270
273
  - lib/kitchen/directions/bake_first_elements.rb
274
+ - lib/kitchen/directions/bake_folio.rb
271
275
  - lib/kitchen/directions/bake_footnotes/main.rb
272
276
  - lib/kitchen/directions/bake_footnotes/v1.rb
273
277
  - lib/kitchen/directions/bake_free_response/free_response.xhtml.erb
@@ -328,6 +332,9 @@ files:
328
332
  - lib/kitchen/directions/move_exercises_to_eoc/v2.rb
329
333
  - lib/kitchen/directions/move_exercises_to_eoc/v3.rb
330
334
  - lib/kitchen/directions/move_solutions_to_answer_key/main.rb
335
+ - lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_exercise_section.rb
336
+ - lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_numbered_note.rb
337
+ - lib/kitchen/directions/move_solutions_to_answer_key/solution_area_snippet.rb
331
338
  - lib/kitchen/directions/move_solutions_to_answer_key/strategies/calculus.rb
332
339
  - lib/kitchen/directions/move_solutions_to_answer_key/strategies/contemporary_math.rb
333
340
  - lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb