openstax_kitchen 10.0.0 → 11.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +2 -2
- data/lib/kitchen/chapter_element.rb +8 -0
- data/lib/kitchen/directions/bake_annotation_classes/main.rb +12 -0
- data/lib/kitchen/directions/bake_annotation_classes/v1.rb +32 -0
- data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +0 -1
- data/lib/kitchen/directions/bake_chapter_references/v1.rb +1 -3
- data/lib/kitchen/directions/bake_chapter_summary.rb +1 -1
- data/lib/kitchen/directions/bake_eoc_section_content/change_subsection_title_tag.rb +13 -0
- data/lib/kitchen/directions/bake_example.rb +2 -0
- data/lib/kitchen/directions/bake_first_elements.rb +7 -3
- data/lib/kitchen/directions/bake_folio.rb +12 -0
- data/lib/kitchen/directions/bake_free_response/v1.rb +1 -1
- data/lib/kitchen/directions/bake_further_research.rb +1 -2
- data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +57 -16
- data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -1
- data/lib/kitchen/directions/bake_numbered_table/v2.rb +2 -2
- data/lib/kitchen/directions/bake_unit_page_title/v1.rb +4 -2
- data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +32 -21
- data/lib/kitchen/directions/move_custom_section_to_eoc_container/main.rb +1 -3
- data/lib/kitchen/directions/move_custom_section_to_eoc_container/v1.rb +2 -2
- data/lib/kitchen/directions/move_exercises_to_eoc/v1.rb +1 -2
- data/lib/kitchen/directions/move_exercises_to_eoc/v2.rb +0 -1
- data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +1 -2
- data/lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_exercise_section.rb +40 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_numbered_note.rb +33 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/solution_area_snippet.rb +12 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/calculus.rb +1 -1
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/contemporary_math.rb +4 -21
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +1 -1
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +18 -39
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/uphysics.rb +6 -48
- data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +3 -2
- data/lib/kitchen/element_base.rb +0 -4
- data/lib/kitchen/page_element.rb +12 -1
- data/lib/kitchen/table_element.rb +25 -0
- data/lib/kitchen/version.rb +1 -1
- data/lib/locales/en.yml +3 -0
- data/lib/locales/es.yml +3 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6964a7fe85234e82e7f54f3b6d4980633f4f4c29c49d3123743c214d9f46653
|
4
|
+
data.tar.gz: 2426f1990ae74d35d2ac098bcf7d5c09aa5094eeef598dd9658d8fedf97916c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 (
|
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.
|
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,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
|
-
|
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
|
|
@@ -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
|
-
|
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.
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
table
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
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.
|
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.
|
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.
|
7
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
14
|
-
|
15
|
-
</a>
|
16
|
-
HTML
|
17
|
-
end
|
15
|
+
HTML
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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,
|
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:,
|
8
|
+
section_selector:, append_to:, wrap_section:, wrap_content:,
|
9
9
|
&block)
|
10
10
|
section_clipboard = Kitchen::Clipboard.new
|
11
|
-
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(
|
data/lib/kitchen/directions/move_solutions_to_answer_key/move_solutions_from_exercise_section.rb
ADDED
@@ -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
|
@@ -4,36 +4,19 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
|
|
4
4
|
module Strategies
|
5
5
|
class ContemporaryMath
|
6
6
|
def bake(chapter:, append_to:)
|
7
|
-
|
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
|
-
|
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.
|
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
|
-
|
13
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
49
|
+
title_snippet = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(
|
50
|
+
page: page,
|
51
|
+
wrapper: 'div'
|
52
|
+
)
|
65
53
|
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
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="
|
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.
|
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
|
data/lib/kitchen/element_base.rb
CHANGED
@@ -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,
|
data/lib/kitchen/page_element.rb
CHANGED
@@ -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]
|
data/lib/kitchen/version.rb
CHANGED
data/lib/locales/en.yml
CHANGED
data/lib/locales/es.yml
CHANGED
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:
|
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-
|
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
|