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.
- 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
|