openstax_kitchen 11.1.0 → 12.2.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 +42 -0
- data/Gemfile.lock +2 -2
- data/lib/kitchen/chapter_element.rb +7 -0
- data/lib/kitchen/directions/bake_accessibility_fixes.rb +11 -0
- data/lib/kitchen/directions/bake_autotitled_exercise/main.rb +11 -0
- data/lib/kitchen/directions/bake_autotitled_exercise/v1.rb +28 -0
- data/lib/kitchen/directions/bake_chapter_introductions/bake_chapter_objectives.rb +2 -0
- data/lib/kitchen/directions/bake_chapter_introductions/v1.rb +8 -48
- data/lib/kitchen/directions/bake_chapter_references/v1.rb +2 -0
- data/lib/kitchen/directions/bake_eoc_section_content/remove_section_title.rb +2 -2
- data/lib/kitchen/directions/bake_example.rb +3 -3
- data/lib/kitchen/directions/bake_figure.rb +3 -2
- data/lib/kitchen/directions/bake_footnotes/v1.rb +5 -1
- data/lib/kitchen/directions/bake_free_response/v1.rb +3 -1
- data/lib/kitchen/directions/bake_injected_exercise/add_injected_exercise_id.rb +16 -0
- data/lib/kitchen/directions/{bake_injected_exercise_question.rb → bake_injected_exercise/bake_injected_exercise_question.rb} +0 -0
- data/lib/kitchen/directions/{bake_page_abstracts.rb → bake_learning_objectives.rb} +10 -5
- data/lib/kitchen/directions/bake_notes/bake_autotitled_notes.rb +36 -4
- data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v3.rb +5 -0
- data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +3 -0
- data/lib/kitchen/directions/bake_numbered_table/v1.rb +2 -0
- data/lib/kitchen/directions/bake_numbered_table/v2.rb +2 -0
- data/lib/kitchen/directions/bake_references/main.rb +3 -2
- data/lib/kitchen/directions/bake_references/v1.rb +8 -3
- data/lib/kitchen/directions/bake_stepwise.rb +1 -1
- data/lib/kitchen/directions/bake_unnumbered_tables.rb +1 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +3 -1
- data/lib/kitchen/element_base.rb +10 -18
- data/lib/kitchen/element_enumerator_base.rb +17 -0
- data/lib/kitchen/example_element.rb +2 -1
- data/lib/kitchen/exercise_element.rb +42 -0
- data/lib/kitchen/figure_element.rb +1 -1
- data/lib/kitchen/metadata_element.rb +6 -1
- data/lib/kitchen/note_element.rb +19 -5
- data/lib/kitchen/table_element.rb +8 -0
- data/lib/kitchen/version.rb +1 -1
- data/lib/locales/en.yml +1 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f36305ee23acfe22fc13a9c06ee76f69243f1cd2cba33fe86c28c8c90b5eb36d
|
4
|
+
data.tar.gz: fd501ef342ff2c7334455cc214139581dadf1619fde7841a29650b4fc10acd79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3b939d8a9851db4940213aae3350f720369eb794b8551627d2a44565af36aeda5ad701b62c2c1ec98fb7dcfabafa8bd2e4531642bf40dd777a635c0117560b6
|
7
|
+
data.tar.gz: 5ec8d3e59faa619a3b23a84ce74514c96b6d360dc1b46d233cd1566b63815a5a7edaa73980f102b4c6656c603c43ea349fcc2eac99149cbafb8fa91d8f0e2fdc
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [12.2.0] - 2021-10-1
|
10
|
+
|
11
|
+
* Add `context_lead_text` to translations (minor)
|
12
|
+
* Make `ElementBase#search_with` callable from an `ElementEnumerator` (minor)
|
13
|
+
* Support top-titled tables in `BakeUnnumberedTables` (minor)
|
14
|
+
* Stop `NoteElement#title` from breaking for empty notes (patch)
|
15
|
+
* Add text heavy tables to `BakeTableBody` (minor)
|
16
|
+
* Modify `BakeAutotitledNotes` to bake unnumbered exercises with solution (minor)
|
17
|
+
* Create `AddInjectedExerciseId` to separate creating ids from `BakeInjectedExerciseQuestion` (minor)
|
18
|
+
* Rework `AddInjectedExerciseId` to use loop inside module (minor)
|
19
|
+
|
20
|
+
## [12.1.0] - 2021-09-24
|
21
|
+
|
22
|
+
* Fix `BakeExample#titles_to_rename` to exclude exercise titles (patch)
|
23
|
+
* Modify `BakeFigure` to bake unnumbered figures with caption (minor)
|
24
|
+
* Fix `NoteElement#title` to be more specific about finding the title (patch)
|
25
|
+
* Adds `data-type="slug"` to `metadata_lement` `children_to_keep` method, updates spec helper `metadata_element` and related spec files(minor)
|
26
|
+
|
27
|
+
## [12.0.0] - 2021-09-21
|
28
|
+
|
29
|
+
* Fixes `BakeStepwise` to skip nested lists (patch)
|
30
|
+
* Adds an optional selector to `RemoveSectionTitles` (minor)
|
31
|
+
* Patches `BakeFreeResponse` to only delete the first h3, not all h3s (patch)
|
32
|
+
* Lets `BakeExample` not count titles in lists as commentary titles (minor)
|
33
|
+
* Renames `BakePageAbstracts` to `BakeLearningObjectives` and adds optional parameter for titles in `v2` (major)
|
34
|
+
* Gets rid of extraneous titles in `BakeAutoTitledNotes` when subtitles are off (minor)
|
35
|
+
* Adds `BakeAutotitledExercise` direction and the option to `bake_unclassified_exercises` within `BakeAutotitledNotes`
|
36
|
+
* Adds optional numbering for `BakeReferences.v1` (minor)
|
37
|
+
* Patches`BakeNumberedNotes.v3` to suppress solutions outside examples when suppress_solutions is true (minor)
|
38
|
+
|
39
|
+
## [11.2.0] - 2021-09-10
|
40
|
+
|
41
|
+
* Adds `BakeAccessibilityFixes` direction for (minor)
|
42
|
+
* Remove deprecation warning from `BakeChapterIntroductions.v1` and adapted to be used like `.v2` (minor)
|
43
|
+
* Small class fix for `BakeFootnotes.v1` (patch)
|
44
|
+
* Fix `BakeNumberedNotes` to find related example better (minor)
|
45
|
+
* Small fix for parameter in `bake_note` definition (minor)
|
46
|
+
* Small fixes to return when no elements are found and not add an empty wrapper in `BakeChapterReferences` and
|
47
|
+
`BakeFreeResponse` (minor)
|
48
|
+
* Adding class `os-timeline-table-container` to numbered tables when required (minor)
|
49
|
+
* Fix `BakeExample` to catch the multiple solutions to one exercise (patch)
|
50
|
+
|
9
51
|
## [11.1.0] - 2021-08-30
|
10
52
|
|
11
53
|
* Update injected questions to synthesize ids during baking (minor)
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openstax_kitchen (
|
4
|
+
openstax_kitchen (12.2.0)
|
5
5
|
activesupport
|
6
6
|
i18n
|
7
7
|
nokogiri
|
@@ -11,7 +11,7 @@ PATH
|
|
11
11
|
GEM
|
12
12
|
remote: https://rubygems.org/
|
13
13
|
specs:
|
14
|
-
activesupport (6.1.4)
|
14
|
+
activesupport (6.1.4.1)
|
15
15
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
16
16
|
i18n (>= 1.6, < 2)
|
17
17
|
minitest (>= 5.1)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kitchen::Directions::BakeAutotitledExercise
|
4
|
+
class V1
|
5
|
+
def bake(exercise:, number:)
|
6
|
+
exercise.add_class('unnumbered') unless number
|
7
|
+
|
8
|
+
# bake problem
|
9
|
+
exercise.problem.wrap_children('div', class: 'os-problem-container')
|
10
|
+
exercise.problem.prepend(child:
|
11
|
+
<<~HTML
|
12
|
+
<h4 class="exercise-title" data-type="title">#{exercise.autogenerated_title}</h4>
|
13
|
+
HTML
|
14
|
+
)
|
15
|
+
return unless exercise.solution
|
16
|
+
|
17
|
+
# bake solution in place
|
18
|
+
exercise.solution.wrap_children('div', class: 'os-solution-container')
|
19
|
+
exercise.solution.prepend(child:
|
20
|
+
<<~HTML
|
21
|
+
<h4 class="solution-title" data-type="title">
|
22
|
+
<span class="os-text">#{I18n.t(:"exercises.solution")}</span>
|
23
|
+
</h4>
|
24
|
+
HTML
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -18,6 +18,8 @@ module Kitchen::Directions::BakeChapterIntroductions
|
|
18
18
|
def bake_as_note(chapter:)
|
19
19
|
chapter_objectives_note = chapter.notes('$.chapter-objectives').first
|
20
20
|
|
21
|
+
return unless chapter_objectives_note.present?
|
22
|
+
|
21
23
|
# trash existing title
|
22
24
|
chapter_objectives_note.titles.first&.trash
|
23
25
|
Kitchen::Directions::BakeAutotitledNotes.v1(
|
@@ -3,54 +3,14 @@
|
|
3
3
|
module Kitchen::Directions::BakeChapterIntroductions
|
4
4
|
class V1
|
5
5
|
def bake(book:)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
title = introduction_page.title.cut
|
16
|
-
title.name = 'h2'
|
17
|
-
Kitchen::Directions::MoveTitleTextIntoSpan.v1(title: title)
|
18
|
-
|
19
|
-
intro_content = introduction_page.search(
|
20
|
-
"> :not([data-type='metadata']):not(.splash):not(.has-splash)"
|
21
|
-
).cut
|
22
|
-
|
23
|
-
chapter_objectives_html = chapter.non_introduction_pages.map do |page|
|
24
|
-
<<~HTML
|
25
|
-
<div class="os-chapter-objective">
|
26
|
-
<a class="os-chapter-objective" href="##{page.title[:id]}">
|
27
|
-
<span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
|
28
|
-
<span class="os-divider"> </span>
|
29
|
-
<span data-type="" itemprop="" class="os-text">#{page.title.children[0].text}</span>
|
30
|
-
</a>
|
31
|
-
</div>
|
32
|
-
HTML
|
33
|
-
end.join('')
|
34
|
-
|
35
|
-
chapter_outline =
|
36
|
-
Kitchen::Directions::BakeChapterIntroductions.bake_chapter_outline(
|
37
|
-
chapter_objectives_html: chapter_objectives_html
|
38
|
-
)
|
39
|
-
|
40
|
-
introduction_page.append(child:
|
41
|
-
<<~HTML
|
42
|
-
<div class="intro-body">
|
43
|
-
#{chapter_outline}
|
44
|
-
<div class="intro-text">
|
45
|
-
#{title.paste}
|
46
|
-
#{intro_content.paste}
|
47
|
-
</div>
|
48
|
-
</div>
|
49
|
-
HTML
|
50
|
-
)
|
51
|
-
end
|
52
|
-
|
53
|
-
Kitchen::Directions::BakeChapterIntroductions.v1_update_selectors(book)
|
6
|
+
Kitchen::Directions::BakeChapterIntroductions.v2(
|
7
|
+
book: book,
|
8
|
+
strategy_options: {
|
9
|
+
strategy: :add_objectives,
|
10
|
+
bake_chapter_outline: true,
|
11
|
+
introduction_order: :v1
|
12
|
+
}
|
13
|
+
)
|
54
14
|
end
|
55
15
|
end
|
56
16
|
end
|
@@ -30,9 +30,9 @@ module Kitchen
|
|
30
30
|
problem.wrap_children(class: 'os-problem-container')
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
exercise.solutions.each do |solution|
|
34
34
|
solution_number = if numbered_solutions
|
35
|
-
"<span class=\"os-number\">#{
|
35
|
+
"<span class=\"os-number\">#{solution.count_in(:example)}</span>"
|
36
36
|
else
|
37
37
|
''
|
38
38
|
end
|
@@ -53,7 +53,7 @@ module Kitchen
|
|
53
53
|
next unless commentary.present?
|
54
54
|
|
55
55
|
commentary_title = commentary.titles.first
|
56
|
-
next unless commentary_title.present?
|
56
|
+
next unless commentary_title.present? && commentary_title.parent['data-type'] != 'list'
|
57
57
|
|
58
58
|
commentary_title.name = 'h4'
|
59
59
|
commentary_title['data-type'] = 'commentary-title'
|
@@ -4,10 +4,11 @@ module Kitchen
|
|
4
4
|
module Directions
|
5
5
|
module BakeFigure
|
6
6
|
def self.v1(figure:, number:, cases: false)
|
7
|
-
return if figure.has_class?('unnumbered') && !figure.has_class?('splash')
|
7
|
+
return if figure.has_class?('unnumbered') && !figure.has_class?('splash') && !figure.caption
|
8
8
|
|
9
9
|
figure.wrap(%(<div class="os-figure#{' has-splash' if figure.has_class?('splash')}">))
|
10
|
-
|
10
|
+
|
11
|
+
if figure.has_class?('unnumbered') && (figure.caption || figure.has_class?('splash'))
|
11
12
|
caption = figure.caption&.cut
|
12
13
|
figure.append(sibling:
|
13
14
|
<<~HTML
|
@@ -28,7 +28,11 @@ module Kitchen::Directions::BakeFootnotes
|
|
28
28
|
anchor.replace_children(with: footnote_number)
|
29
29
|
aside_id = anchor[:href][1..-1]
|
30
30
|
aside_id_to_footnote_number[aside_id] = footnote_number
|
31
|
-
|
31
|
+
if anchor.parent.name == 'p'
|
32
|
+
anchor.parent.add_class('has-noteref')
|
33
|
+
elsif anchor.parent.name == 'em' && anchor.parent.parent.name == 'p'
|
34
|
+
anchor.parent.parent.add_class('has-noteref')
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
container.search('aside').each do |aside|
|
@@ -12,7 +12,7 @@ module Kitchen::Directions::BakeFreeResponse
|
|
12
12
|
free_response_questions = page.free_response
|
13
13
|
next if free_response_questions.none?
|
14
14
|
|
15
|
-
free_response_questions.search('h3')
|
15
|
+
free_response_questions.search('h3')&.first&.trash
|
16
16
|
title = Kitchen::Directions::EocSectionTitleLinkSnippet.v1(page: page)
|
17
17
|
free_response_questions.each do |free_response_question|
|
18
18
|
free_response_question.prepend(child: title)
|
@@ -20,6 +20,8 @@ module Kitchen::Directions::BakeFreeResponse
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
return if @free_response_clipboard.none?
|
24
|
+
|
23
25
|
append_to_element = append_to || chapter
|
24
26
|
@title_tag = append_to ? 'h3' : 'h2'
|
25
27
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kitchen
|
4
|
+
module Directions
|
5
|
+
# Ids should be added before exercises are moved to EOC,
|
6
|
+
# since they're using part of the ancestor page id.
|
7
|
+
#
|
8
|
+
# In some books exercises are numbered after moving.
|
9
|
+
# That's why this step has to be separated from BakeInjectedExerciseQuestion
|
10
|
+
module AddInjectedExerciseId
|
11
|
+
def self.v1(book:)
|
12
|
+
book.pages.injected_questions.each(&:id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
File without changes
|
@@ -2,17 +2,22 @@
|
|
2
2
|
|
3
3
|
module Kitchen
|
4
4
|
module Directions
|
5
|
-
|
6
|
-
module BakePageAbstracts
|
5
|
+
module BakeLearningObjectives
|
7
6
|
def self.v1(chapter:)
|
8
7
|
chapter.abstracts.each do |abstract|
|
9
8
|
abstract.prepend(child: "<h3 data-type='title'>#{I18n.t(:learning_objectives)}</h3>")
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
13
|
-
def self.v2(chapter:)
|
14
|
-
|
15
|
-
|
12
|
+
def self.v2(chapter:, add_title: true)
|
13
|
+
learning_objectives =
|
14
|
+
chapter.abstracts.any? ? chapter.abstracts : chapter.learning_objectives
|
15
|
+
|
16
|
+
learning_objectives.each do |abstract|
|
17
|
+
if add_title
|
18
|
+
abstract.prepend(child: "<h3 data-type='title'>#{I18n.t(:learning_objectives)}</h3>")
|
19
|
+
end
|
20
|
+
|
16
21
|
ul = abstract.first!('ul')
|
17
22
|
ul.add_class('os-abstract')
|
18
23
|
ul.search('li').each_with_index do |li, index|
|
@@ -3,19 +3,24 @@
|
|
3
3
|
module Kitchen
|
4
4
|
module Directions
|
5
5
|
module BakeAutotitledNotes
|
6
|
-
def self.v1(book:, classes:, bake_subtitle: true, cases: false)
|
6
|
+
def self.v1(book:, classes:, bake_subtitle: true, cases: false, bake_exercises: false)
|
7
7
|
book.notes.each do |note|
|
8
8
|
next unless (note.classes & classes).any?
|
9
9
|
|
10
|
-
bake_note(
|
10
|
+
bake_note(
|
11
|
+
note: note, bake_subtitle: bake_subtitle, cases: cases, bake_exercises: bake_exercises)
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
def self.bake_note(note:, bake_subtitle:, cases:
|
15
|
+
def self.bake_note(note:, bake_subtitle:, cases:, bake_exercises:)
|
15
16
|
Kitchen::Directions::BakeIframes.v1(outer_element: note)
|
16
17
|
note.wrap_children(class: 'os-note-body')
|
17
18
|
|
18
|
-
|
19
|
+
if bake_subtitle
|
20
|
+
BakeNoteSubtitle.v1(note: note, cases: cases)
|
21
|
+
else
|
22
|
+
note.title&.trash
|
23
|
+
end
|
19
24
|
|
20
25
|
note.prepend(child:
|
21
26
|
<<~HTML
|
@@ -24,6 +29,33 @@ module Kitchen
|
|
24
29
|
</h3>
|
25
30
|
HTML
|
26
31
|
)
|
32
|
+
|
33
|
+
bake_unclassified_exercises(note: note) if bake_exercises
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.bake_unclassified_exercises(note:)
|
37
|
+
note.exercises.each do |exercise|
|
38
|
+
exercise.problem.wrap_children('div', class: 'os-problem-container')
|
39
|
+
|
40
|
+
unless exercise.has_class?('unnumbered')
|
41
|
+
exercise.problem.prepend(child:
|
42
|
+
<<~HTML
|
43
|
+
<span class="os-title-label">#{I18n.t(:"exercises.exercise")} </span>
|
44
|
+
<span class="os-number">#{exercise.count_in(:note)}</span>
|
45
|
+
HTML
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
next unless exercise.solution
|
50
|
+
|
51
|
+
exercise.solution.wrap_children('div', class: 'os-solution-container')
|
52
|
+
|
53
|
+
exercise.solution.prepend(child:
|
54
|
+
<<~HTML
|
55
|
+
<span class="os-title-label">#{I18n.t(:"exercises.solution")}</span>
|
56
|
+
HTML
|
57
|
+
)
|
58
|
+
end
|
27
59
|
end
|
28
60
|
end
|
29
61
|
end
|
@@ -9,6 +9,9 @@ module Kitchen::Directions
|
|
9
9
|
book.chapters.pages.notes("$.#{klass}").each do |note|
|
10
10
|
note.wrap_children(class: 'os-note-body')
|
11
11
|
previous_example = note.previous
|
12
|
+
until previous_example.nil? || previous_example[:'data-type'] == 'example'
|
13
|
+
previous_example = previous_example.previous
|
14
|
+
end
|
12
15
|
os_number = previous_example&.first('.os-number')&.children&.to_s
|
13
16
|
|
14
17
|
note.prepend(child:
|
@@ -29,6 +32,8 @@ module Kitchen::Directions
|
|
29
32
|
note.injected_questions.each do |question|
|
30
33
|
BakeNumberedNotes.bake_note_injected_question(note: note, question: question)
|
31
34
|
end
|
35
|
+
|
36
|
+
note.search("div[data-type='solution']").each&.trash if suppress_solution
|
32
37
|
end
|
33
38
|
end
|
34
39
|
end
|
@@ -62,6 +62,9 @@ module Kitchen
|
|
62
62
|
elsif table.column_header?
|
63
63
|
custom_table = CustomBody.new(table: table, klass: 'column-header')
|
64
64
|
custom_table.modify_body(has_fake_title: false)
|
65
|
+
elsif table.text_heavy?
|
66
|
+
custom_table = CustomBody.new(table: table, klass: 'text-heavy')
|
67
|
+
custom_table.modify_body(has_fake_title: false)
|
65
68
|
end
|
66
69
|
end
|
67
70
|
end
|
@@ -5,10 +5,11 @@ module Kitchen
|
|
5
5
|
# Bake directions for EOB references
|
6
6
|
#
|
7
7
|
module BakeReferences
|
8
|
-
def self.v1(book:, metadata_source:)
|
8
|
+
def self.v1(book:, metadata_source:, numbered_title: false)
|
9
9
|
V1.new.bake(
|
10
10
|
book: book,
|
11
|
-
metadata_source: metadata_source
|
11
|
+
metadata_source: metadata_source,
|
12
|
+
numbered_title: numbered_title
|
12
13
|
)
|
13
14
|
end
|
14
15
|
|
@@ -4,7 +4,7 @@ module Kitchen::Directions::BakeReferences
|
|
4
4
|
class V1
|
5
5
|
renderable
|
6
6
|
|
7
|
-
def bake(book:, metadata_source:)
|
7
|
+
def bake(book:, metadata_source:, numbered_title:)
|
8
8
|
@metadata = metadata_source.children_to_keep.copy
|
9
9
|
@klass = 'reference'
|
10
10
|
@uuid_prefix = '.'
|
@@ -28,12 +28,17 @@ module Kitchen::Directions::BakeReferences
|
|
28
28
|
end
|
29
29
|
|
30
30
|
chapter_references = chapter.pages.references.cut
|
31
|
-
|
31
|
+
|
32
|
+
chapter_title = if numbered_title
|
33
|
+
chapter.title.search('.os-number, .os-divider, .os-text')
|
34
|
+
else
|
35
|
+
chapter.title.search('.os-text')
|
36
|
+
end
|
32
37
|
|
33
38
|
chapter.append(child:
|
34
39
|
<<~HTML
|
35
40
|
<div class="os-chapter-area">
|
36
|
-
<h2 data-type="document-title">#{
|
41
|
+
<h2 data-type="document-title">#{chapter_title}</h2>
|
37
42
|
#{chapter_references.paste}
|
38
43
|
</div>
|
39
44
|
HTML
|
@@ -9,6 +9,7 @@ module Kitchen
|
|
9
9
|
table.remove_attribute('summary')
|
10
10
|
table.parent.add_class('os-unstyled-container') if table.unstyled?
|
11
11
|
table.parent.add_class('os-column-header-container') if table.column_header?
|
12
|
+
table.parent.add_class('os-top-titled-container') if table.top_titled?
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
@@ -38,7 +38,9 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
|
|
38
38
|
</div>
|
39
39
|
HTML
|
40
40
|
)
|
41
|
-
strategy.bake(
|
41
|
+
strategy.bake(
|
42
|
+
chapter: chapter, append_to: append_to.first("div[data-uuid-key='#{uuid_key}']")
|
43
|
+
)
|
42
44
|
end
|
43
45
|
# rubocop:enable Metrics/ParameterLists
|
44
46
|
end
|
data/lib/kitchen/element_base.rb
CHANGED
@@ -211,6 +211,14 @@ module Kitchen
|
|
211
211
|
self[:id] = value
|
212
212
|
end
|
213
213
|
|
214
|
+
# Returns the element's data-type
|
215
|
+
#
|
216
|
+
# @return [String]
|
217
|
+
#
|
218
|
+
def data_type
|
219
|
+
self[:'data-type']
|
220
|
+
end
|
221
|
+
|
214
222
|
# A way to set values and chain them
|
215
223
|
#
|
216
224
|
# @param property [String, Symbol] the name of the property to set
|
@@ -419,23 +427,6 @@ module Kitchen
|
|
419
427
|
)
|
420
428
|
end
|
421
429
|
|
422
|
-
# Searches for elements handled by a list of enumerator classes. All element that
|
423
|
-
# matches one of those enumerator classes are iterated over.
|
424
|
-
#
|
425
|
-
# @param enumerator_classes [Array<ElementEnumeratorBase>]
|
426
|
-
# @return [TypeCastingElementEnumerator]
|
427
|
-
#
|
428
|
-
def search_with(*enumerator_classes)
|
429
|
-
block_error_if(block_given?)
|
430
|
-
raise 'must supply at least one enumerator class' if enumerator_classes.empty?
|
431
|
-
|
432
|
-
factory = enumerator_classes[0].factory
|
433
|
-
enumerator_classes[1..-1].each do |enumerator_class|
|
434
|
-
factory = factory.or_with(enumerator_class.factory)
|
435
|
-
end
|
436
|
-
factory.build_within(self)
|
437
|
-
end
|
438
|
-
|
439
430
|
# Removes the element from its parent and places it on the specified clipboard
|
440
431
|
#
|
441
432
|
# @param to [Symbol, String, Clipboard, nil] the name of the clipboard (or a Clipboard
|
@@ -762,7 +753,8 @@ module Kitchen
|
|
762
753
|
# Returns a pages enumerator
|
763
754
|
def_delegators :as_enumerator, :pages, :chapters, :terms, :figures, :notes, :tables, :examples,
|
764
755
|
:metadatas, :non_introduction_pages, :units, :titles, :exercises, :references,
|
765
|
-
:composite_pages, :composite_chapters, :solutions, :injected_questions
|
756
|
+
:composite_pages, :composite_chapters, :solutions, :injected_questions,
|
757
|
+
:search_with
|
766
758
|
|
767
759
|
# Returns this element as an enumerator (over only one element, itself)
|
768
760
|
#
|
@@ -327,6 +327,23 @@ module Kitchen
|
|
327
327
|
chain_to(ElementEnumerator, css_or_xpath: css_or_xpath, only: only, except: except)
|
328
328
|
end
|
329
329
|
|
330
|
+
# Searches for elements handled by a list of enumerator classes. All element that
|
331
|
+
# matches one of those enumerator classes are iterated over.
|
332
|
+
#
|
333
|
+
# @param enumerator_classes [Array<ElementEnumeratorBase>]
|
334
|
+
# @return [TypeCastingElementEnumerator]
|
335
|
+
#
|
336
|
+
def search_with(*enumerator_classes)
|
337
|
+
block_error_if(block_given?)
|
338
|
+
raise 'must supply at least one enumerator class' if enumerator_classes.empty?
|
339
|
+
|
340
|
+
factory = enumerator_classes[0].factory
|
341
|
+
enumerator_classes[1..-1].each do |enumerator_class|
|
342
|
+
factory = factory.or_with(enumerator_class.factory)
|
343
|
+
end
|
344
|
+
factory.build_within(self)
|
345
|
+
end
|
346
|
+
|
330
347
|
# Returns an enumerator that iterates through elements within the scope of this enumerator
|
331
348
|
#
|
332
349
|
# @param enumerator_class [ElementEnumeratorBase] the enumerator to use for the iteration
|
@@ -33,7 +33,8 @@ module Kitchen
|
|
33
33
|
title.parent.has_class?('os-caption-container') || \
|
34
34
|
title.parent.has_class?('os-caption') || \
|
35
35
|
title.parent.name == 'caption' || \
|
36
|
-
title.parent
|
36
|
+
title.parent.data_type == 'note' || \
|
37
|
+
title.parent.data_type == 'exercise'
|
37
38
|
end
|
38
39
|
)
|
39
40
|
end
|
@@ -39,6 +39,14 @@ module Kitchen
|
|
39
39
|
first("div[data-type='solution']")
|
40
40
|
end
|
41
41
|
|
42
|
+
# Returns the enumerator for solutions
|
43
|
+
#
|
44
|
+
# @return [ElementEnumerator]
|
45
|
+
#
|
46
|
+
def solutions
|
47
|
+
search("div[data-type='solution']")
|
48
|
+
end
|
49
|
+
|
42
50
|
# Returns whether the exercise has been baked
|
43
51
|
#
|
44
52
|
# @return [Boolean]
|
@@ -46,5 +54,39 @@ module Kitchen
|
|
46
54
|
def baked?
|
47
55
|
search('div.os-problem-container').any?
|
48
56
|
end
|
57
|
+
|
58
|
+
# Returns true if the exercise's title is autogenerated
|
59
|
+
#
|
60
|
+
# @return [Boolean]
|
61
|
+
#
|
62
|
+
def indicates_autogenerated_title?
|
63
|
+
detected_exercise_title_key != 0 && detected_exercise_title_key.present?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get the autogenerated title for this note
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
#
|
70
|
+
def autogenerated_title
|
71
|
+
if indicates_autogenerated_title?
|
72
|
+
I18n.t(:"exercises.#{detected_exercise_title_key}")
|
73
|
+
else
|
74
|
+
"unknown title for exercise with classes #{classes}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def detected_exercise_title_key
|
79
|
+
@detected_exercise_title_key ||= begin
|
80
|
+
return 0 if classes.empty? || !I18n.t('.').key?(:exercises)
|
81
|
+
|
82
|
+
possible_keys = I18n.t(:exercises).keys.map(&:to_s)
|
83
|
+
keys = possible_keys & classes
|
84
|
+
|
85
|
+
raise("too many translation keys: #{keys.join(', ')}") if keys.many?
|
86
|
+
return 0 if keys.empty?
|
87
|
+
|
88
|
+
keys.first
|
89
|
+
end
|
90
|
+
end
|
49
91
|
end
|
50
92
|
end
|
@@ -53,7 +53,7 @@ module Kitchen
|
|
53
53
|
# @return [Boolean]
|
54
54
|
#
|
55
55
|
def figure_to_bake?
|
56
|
-
return false if subfigure? || (has_class?('unnumbered') && !has_class?('splash'))
|
56
|
+
return false if subfigure? || (has_class?('unnumbered') && !has_class?('splash') && !caption)
|
57
57
|
|
58
58
|
true
|
59
59
|
end
|
@@ -27,7 +27,12 @@ module Kitchen
|
|
27
27
|
# @return [ElementEnumerator]
|
28
28
|
#
|
29
29
|
def children_to_keep
|
30
|
-
search(%w(span[data-type='revised']
|
30
|
+
search(%w(span[data-type='revised']
|
31
|
+
span[data-type='slug']
|
32
|
+
div.authors
|
33
|
+
div.publishers
|
34
|
+
div.print-style
|
35
|
+
div.permissions
|
31
36
|
div[data-type='subject']))
|
32
37
|
end
|
33
38
|
end
|
data/lib/kitchen/note_element.rb
CHANGED
@@ -29,16 +29,30 @@ module Kitchen
|
|
29
29
|
#
|
30
30
|
def title
|
31
31
|
block_error_if(block_given?)
|
32
|
-
|
33
|
-
|
32
|
+
# An element with data-type="title" is ambiguous; it is only the note's title if:
|
33
|
+
# 1. it is the note body's first child
|
34
|
+
# 2. it is the first child's first child and the first child is a paragraph
|
35
|
+
first_child = first_note_body_child
|
36
|
+
return unless first_child
|
37
|
+
|
38
|
+
first_grandchild = get_first_grandchild_for_title(first_child)
|
34
39
|
|
35
|
-
if first_child
|
40
|
+
if first_child.data_type == 'title'
|
36
41
|
first_child
|
37
|
-
elsif
|
38
|
-
|
42
|
+
elsif first_grandchild&.data_type == 'title'
|
43
|
+
first_grandchild
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
47
|
+
def first_note_body_child
|
48
|
+
note_body = first('div.os-note-body')
|
49
|
+
note_body ? note_body.element_children[0] : element_children[0]
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_first_grandchild_for_title(first_child)
|
53
|
+
first_child&.element_children&.[](0) if first_child.name == 'p'
|
54
|
+
end
|
55
|
+
|
42
56
|
# Returns true if the note's title is autogenerated
|
43
57
|
#
|
44
58
|
# @return [Boolean]
|
@@ -97,6 +97,14 @@ module Kitchen
|
|
97
97
|
has_class?('column-header')
|
98
98
|
end
|
99
99
|
|
100
|
+
# Returns true if the table is text heavy
|
101
|
+
#
|
102
|
+
# @return [Boolean]
|
103
|
+
#
|
104
|
+
def text_heavy?
|
105
|
+
has_class?('text-heavy')
|
106
|
+
end
|
107
|
+
|
100
108
|
# Returns an element for the table caption, if present
|
101
109
|
#
|
102
110
|
# @return [Element, nil]
|
data/lib/kitchen/version.rb
CHANGED
data/lib/locales/en.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: 12.2.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-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -243,9 +243,12 @@ 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_accessibility_fixes.rb
|
246
247
|
- lib/kitchen/directions/bake_annotation_classes/main.rb
|
247
248
|
- lib/kitchen/directions/bake_annotation_classes/v1.rb
|
248
249
|
- lib/kitchen/directions/bake_appendix.rb
|
250
|
+
- lib/kitchen/directions/bake_autotitled_exercise/main.rb
|
251
|
+
- lib/kitchen/directions/bake_autotitled_exercise/v1.rb
|
249
252
|
- lib/kitchen/directions/bake_chapter_glossary/main.rb
|
250
253
|
- lib/kitchen/directions/bake_chapter_glossary/v1.rb
|
251
254
|
- lib/kitchen/directions/bake_chapter_introductions/bake_chapter_objectives.rb
|
@@ -291,8 +294,10 @@ files:
|
|
291
294
|
- lib/kitchen/directions/bake_index/v1.rb
|
292
295
|
- lib/kitchen/directions/bake_index/v1.xhtml.erb
|
293
296
|
- lib/kitchen/directions/bake_injected_exercise.rb
|
294
|
-
- lib/kitchen/directions/
|
297
|
+
- lib/kitchen/directions/bake_injected_exercise/add_injected_exercise_id.rb
|
298
|
+
- lib/kitchen/directions/bake_injected_exercise/bake_injected_exercise_question.rb
|
295
299
|
- lib/kitchen/directions/bake_inline_lists.rb
|
300
|
+
- lib/kitchen/directions/bake_learning_objectives.rb
|
296
301
|
- lib/kitchen/directions/bake_link_placeholders.rb
|
297
302
|
- lib/kitchen/directions/bake_lists_with_para.rb
|
298
303
|
- lib/kitchen/directions/bake_math_in_paragraph.rb
|
@@ -310,7 +315,6 @@ files:
|
|
310
315
|
- lib/kitchen/directions/bake_numbered_table/main.rb
|
311
316
|
- lib/kitchen/directions/bake_numbered_table/v1.rb
|
312
317
|
- lib/kitchen/directions/bake_numbered_table/v2.rb
|
313
|
-
- lib/kitchen/directions/bake_page_abstracts.rb
|
314
318
|
- lib/kitchen/directions/bake_preface/main.rb
|
315
319
|
- lib/kitchen/directions/bake_preface/v1.rb
|
316
320
|
- lib/kitchen/directions/bake_references/main.rb
|