openstax_kitchen 4.1.1 → 8.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/.github/workflows/changelog.yml +24 -0
- data/.github/workflows/rubocop.yml +28 -0
- data/CHANGELOG.md +62 -0
- data/Gemfile.lock +16 -7
- data/docker/rubocop +24 -0
- data/lib/kitchen/composite_page_element.rb +20 -3
- data/lib/kitchen/directions/bake_appendix.rb +3 -1
- data/lib/kitchen/directions/bake_chapter_glossary/v1.rb +23 -5
- data/lib/kitchen/directions/bake_chapter_introductions.rb +22 -15
- data/lib/kitchen/directions/bake_chapter_introductions/chapter_introduction.xhtml.erb +0 -0
- data/lib/kitchen/directions/bake_chapter_references/main.rb +1 -2
- data/lib/kitchen/directions/bake_chapter_references/v1.rb +26 -12
- data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +2 -2
- data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +2 -1
- data/lib/kitchen/directions/bake_chapter_solutions/main.rb +11 -0
- data/lib/kitchen/directions/bake_chapter_solutions/v1.rb +37 -0
- data/lib/kitchen/directions/bake_chapter_summary.rb +13 -6
- data/lib/kitchen/directions/bake_example.rb +11 -2
- data/lib/kitchen/directions/bake_figure.rb +13 -0
- data/lib/kitchen/directions/bake_first_elements.rb +7 -1
- data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
- data/lib/kitchen/directions/bake_footnotes/v1.rb +11 -8
- data/lib/kitchen/directions/bake_further_research.rb +2 -0
- data/lib/kitchen/directions/bake_index/v1.rb +3 -14
- data/lib/kitchen/directions/bake_inline_lists.rb +22 -0
- data/lib/kitchen/directions/bake_notes/bake_numbered_notes/main.rb +43 -0
- data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v1.rb +37 -0
- data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v2.rb +25 -0
- data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v3.rb +32 -0
- data/lib/kitchen/directions/bake_numbered_exercise/main.rb +3 -2
- data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +10 -1
- data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +29 -0
- data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -0
- data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -24
- data/lib/kitchen/directions/bake_numbered_table/v2.rb +31 -0
- data/lib/kitchen/directions/bake_preface/main.rb +2 -2
- data/lib/kitchen/directions/bake_preface/v1.rb +3 -2
- data/lib/kitchen/directions/bake_references/main.rb +7 -0
- data/lib/kitchen/directions/bake_references/v2.rb +35 -0
- data/lib/kitchen/directions/bake_toc.rb +3 -1
- data/lib/kitchen/directions/book_answer_key_container/eob_answer_key_outer_container.xhtml.erb +9 -0
- data/lib/kitchen/directions/book_answer_key_container/main.rb +2 -2
- data/lib/kitchen/directions/book_answer_key_container/v1.rb +4 -3
- data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +3 -3
- data/lib/kitchen/directions/chapter_review_container/main.rb +2 -2
- data/lib/kitchen/directions/chapter_review_container/v1.rb +4 -2
- data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +13 -0
- data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +10 -0
- data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +49 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +6 -2
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +27 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +84 -0
- data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +11 -7
- data/lib/kitchen/document.rb +17 -42
- data/lib/kitchen/element_base.rb +31 -7
- data/lib/kitchen/i18n_string.rb +16 -0
- data/lib/kitchen/id_tracker.rb +68 -0
- data/lib/kitchen/oven.rb +3 -1
- data/lib/kitchen/page_element.rb +2 -3
- data/lib/kitchen/patches/array.rb +15 -0
- data/lib/kitchen/patches/i18n.rb +34 -0
- data/lib/kitchen/patches/integer.rb +24 -0
- data/lib/kitchen/patches/nokogiri.rb +7 -0
- data/lib/kitchen/version.rb +1 -1
- data/lib/locales/en.yml +2 -1
- data/lib/locales/es.yml +33 -0
- data/lib/locales/pl.yml +3 -1
- data/lib/openstax_kitchen.rb +2 -5
- data/openstax_kitchen.gemspec +1 -0
- metadata +40 -7
- data/.github/config.yml +0 -14
- data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +0 -51
- data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +0 -9
- data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +0 -19
- data/lib/kitchen/transliterations.rb +0 -21
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kitchen::Directions::MoveSolutionsToAnswerKey
|
4
|
+
module Strategies
|
5
|
+
class Default
|
6
|
+
def bake(chapter:, append_to:)
|
7
|
+
bake_section(chapter: chapter, append_to: append_to)
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def bake_section(chapter:, append_to:)
|
13
|
+
@selectors.each do |selector|
|
14
|
+
chapter.search("#{selector} div[data-type='solution']").each do |solution|
|
15
|
+
append_to.add_child(solution.cut.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method helps to obtain more strategy-specific params through
|
21
|
+
# "strategy_options: {blah1: 1, blah2: 2}"
|
22
|
+
def initialize(strategy_options)
|
23
|
+
@selectors = strategy_options[:selectors] || (raise 'missing selectors for strategy')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kitchen::Directions::MoveSolutionsToAnswerKey
|
4
|
+
module Strategies
|
5
|
+
class Precalculus
|
6
|
+
def bake(chapter:, append_to:)
|
7
|
+
try_note_solutions(chapter: chapter, append_to: append_to)
|
8
|
+
|
9
|
+
# Bake section exercises
|
10
|
+
chapter.non_introduction_pages.each do |page|
|
11
|
+
number = "#{chapter.count_in(:book)}.#{page.count_in(:chapter)}"
|
12
|
+
bake_section(chapter: page, append_to: append_to, klass: 'section-exercises',
|
13
|
+
number: number)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Bake other types of exercises
|
17
|
+
classes = %w[review-exercises practice-test]
|
18
|
+
classes.each do |klass|
|
19
|
+
bake_section(chapter: chapter, append_to: append_to, klass: klass)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def bake_section(chapter:, append_to:, klass:, number: nil)
|
26
|
+
section_solutions_set = Kitchen::Clipboard.new
|
27
|
+
chapter.search(".#{klass}").each do |section|
|
28
|
+
section.search('[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
|
+
def try_note_solutions(chapter:, append_to:)
|
45
|
+
append_to.add_child(
|
46
|
+
<<~HTML
|
47
|
+
<div class="os-module-reset-solution-area os-try-solution-area">
|
48
|
+
<h3 data-type="title">
|
49
|
+
<span class="os-title-label">#{I18n.t(:"notes.try")}</span>
|
50
|
+
</h3>
|
51
|
+
</div>
|
52
|
+
HTML
|
53
|
+
)
|
54
|
+
chapter.non_introduction_pages.each do |page|
|
55
|
+
solutions = Kitchen::Clipboard.new
|
56
|
+
page.notes('$.try').each do |note|
|
57
|
+
note.exercises.each do |exercise|
|
58
|
+
solution = exercise.solution
|
59
|
+
solution&.cut(to: solutions) #if solution
|
60
|
+
end
|
61
|
+
end
|
62
|
+
next if solutions.items.empty?
|
63
|
+
|
64
|
+
title_snippet = Kitchen::Directions::EocSectionTitleLinkSnippet.v2(page: page)
|
65
|
+
|
66
|
+
append_solution_area(title: title_snippet, solutions: solutions,
|
67
|
+
append_to: append_to.search('.os-try-solution-area').first)
|
68
|
+
end
|
69
|
+
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
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -2,22 +2,26 @@
|
|
2
2
|
|
3
3
|
module Kitchen::Directions::MoveSolutionsToAnswerKey
|
4
4
|
class V1
|
5
|
-
def bake(chapter:, metadata_source:, strategy:, append_to:)
|
5
|
+
def bake(chapter:, metadata_source:, strategy:, append_to:, strategy_options: {}, solutions_plural: true)
|
6
6
|
strategy =
|
7
7
|
case strategy
|
8
8
|
when :calculus
|
9
|
-
Strategies::Calculus
|
9
|
+
Strategies::Calculus.new
|
10
10
|
when :uphysics
|
11
|
-
Strategies::UPhysics
|
12
|
-
when :
|
13
|
-
Strategies::
|
11
|
+
Strategies::UPhysics.new
|
12
|
+
when :precalculus
|
13
|
+
Strategies::Precalculus.new
|
14
|
+
when :default
|
15
|
+
Strategies::Default.new(strategy_options)
|
14
16
|
else
|
15
17
|
raise 'No such strategy'
|
16
18
|
end
|
17
19
|
|
20
|
+
solutions_or_solution = solutions_plural ? 'solutions' : 'solution'
|
18
21
|
append_to.append(child:
|
19
22
|
<<~HTML
|
20
|
-
<div class="os-eob os-
|
23
|
+
<div class="os-eob os-#{solutions_or_solution}-container" data-type="composite-page" \
|
24
|
+
data-uuid-key=".#{solutions_or_solution}#{chapter.count_in(:book)}">
|
21
25
|
<h2 data-type="document-title">
|
22
26
|
<span class="os-text">#{I18n.t(:chapter)} #{chapter.count_in(:book)}</span>
|
23
27
|
</h2>
|
@@ -28,7 +32,7 @@ module Kitchen::Directions::MoveSolutionsToAnswerKey
|
|
28
32
|
</div>
|
29
33
|
HTML
|
30
34
|
)
|
31
|
-
strategy.
|
35
|
+
strategy.bake(chapter: chapter, append_to: append_to.last_element)
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
data/lib/kitchen/document.rb
CHANGED
@@ -13,6 +13,8 @@ module Kitchen
|
|
13
13
|
attr_accessor :location
|
14
14
|
# @return [Config] the configuration used in this document
|
15
15
|
attr_reader :config
|
16
|
+
# @return [IdTracker] the counter for duplicate IDs
|
17
|
+
attr_reader :id_tracker
|
16
18
|
|
17
19
|
# @!method selectors
|
18
20
|
# The document's selectors
|
@@ -34,7 +36,10 @@ module Kitchen
|
|
34
36
|
# @!method to_html
|
35
37
|
# @see https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#to_html-instance_method Nokogiri::XML::Node#to_html
|
36
38
|
# @return [String] the document as an HTML string
|
37
|
-
|
39
|
+
# @!method encoding
|
40
|
+
# @see https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Document#encoding-instance_method Nokogiri::XML::Document#encoding
|
41
|
+
# @return [String] the document as an HTML string
|
42
|
+
def_delegators :@nokogiri_document, :to_xhtml, :to_s, :to_xml, :to_html, :encoding
|
38
43
|
|
39
44
|
# Return a new instance of Document
|
40
45
|
#
|
@@ -44,8 +49,7 @@ module Kitchen
|
|
44
49
|
@nokogiri_document = nokogiri_document
|
45
50
|
@location = nil
|
46
51
|
@config = config || Config.new
|
47
|
-
@
|
48
|
-
@id_copy_suffix = '_copy_'
|
52
|
+
@id_tracker = IdTracker.new
|
49
53
|
|
50
54
|
# Nokogiri by default only recognizes the namespaces on the root node. Add all others.
|
51
55
|
raw&.add_all_namespaces! if @config.enable_all_namespaces
|
@@ -148,38 +152,6 @@ module Kitchen
|
|
148
152
|
end
|
149
153
|
end
|
150
154
|
|
151
|
-
# Keeps track that an element with the given ID has been copied. When such
|
152
|
-
# elements are pasted, this information is used to give those elements unique
|
153
|
-
# IDs that don't duplicate the original element.
|
154
|
-
#
|
155
|
-
# @param id [String] the ID
|
156
|
-
#
|
157
|
-
def record_id_copied(id)
|
158
|
-
return if id.blank?
|
159
|
-
|
160
|
-
@next_paste_count_for_id[id] ||= 1
|
161
|
-
end
|
162
|
-
|
163
|
-
# Returns a unique ID given the ID of an element that was copied and is about
|
164
|
-
# to be pasted
|
165
|
-
#
|
166
|
-
# @param original_id [String]
|
167
|
-
#
|
168
|
-
def modified_id_to_paste(original_id)
|
169
|
-
return nil if original_id.nil?
|
170
|
-
return '' if original_id.blank?
|
171
|
-
|
172
|
-
count = next_count_for_pasted_id(original_id)
|
173
|
-
|
174
|
-
# A count of 0 means the element was cut and this is the first paste, do not
|
175
|
-
# modify the ID; otherwise, use the uniquified ID.
|
176
|
-
if count.zero?
|
177
|
-
original_id
|
178
|
-
else
|
179
|
-
"#{original_id}#{@id_copy_suffix}#{count}"
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
155
|
# Returns the underlying Nokogiri Document object
|
184
156
|
#
|
185
157
|
# @return [Nokogiri::XML::Document]
|
@@ -188,16 +160,19 @@ module Kitchen
|
|
188
160
|
@nokogiri_document
|
189
161
|
end
|
190
162
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
163
|
+
# Returns the locale for this document, default to `:en` if no locale detected
|
164
|
+
#
|
165
|
+
# @return [Symbol]
|
166
|
+
#
|
167
|
+
def locale
|
168
|
+
raw.root['lang']&.to_sym || begin
|
169
|
+
warn 'No `lang` attribute on this document so cannot detect its locale; defaulting to `:en`'
|
170
|
+
:en
|
198
171
|
end
|
199
172
|
end
|
200
173
|
|
174
|
+
protected
|
175
|
+
|
201
176
|
attr_reader :nokogiri_document
|
202
177
|
|
203
178
|
end
|
data/lib/kitchen/element_base.rb
CHANGED
@@ -101,6 +101,8 @@ module Kitchen
|
|
101
101
|
# @return [Clipboard]
|
102
102
|
def_delegators :document, :pantry, :clipboard
|
103
103
|
|
104
|
+
def_delegators :document, :id_tracker
|
105
|
+
|
104
106
|
# Creates a new instance
|
105
107
|
#
|
106
108
|
# @param node [Nokogiri::XML::Node] the wrapped element
|
@@ -441,6 +443,11 @@ module Kitchen
|
|
441
443
|
def cut(to: nil)
|
442
444
|
block_error_if(block_given?)
|
443
445
|
|
446
|
+
raw.traverse do |node|
|
447
|
+
next if node.text? || node.document?
|
448
|
+
|
449
|
+
id_tracker.record_id_cut(node[:id])
|
450
|
+
end
|
444
451
|
node.remove
|
445
452
|
get_clipboard(to).add(self) if to.present?
|
446
453
|
self
|
@@ -461,7 +468,7 @@ module Kitchen
|
|
461
468
|
the_copy.raw.traverse do |node|
|
462
469
|
next if node.text? || node.document?
|
463
470
|
|
464
|
-
|
471
|
+
id_tracker.record_id_copied(node[:id])
|
465
472
|
end
|
466
473
|
get_clipboard(to).add(the_copy) if to.present?
|
467
474
|
the_copy
|
@@ -472,20 +479,22 @@ module Kitchen
|
|
472
479
|
def paste
|
473
480
|
# See `clone` method for a note about namespaces
|
474
481
|
block_error_if(block_given?)
|
475
|
-
|
476
482
|
temp_copy = clone
|
477
483
|
temp_copy.raw.traverse do |node|
|
478
484
|
next if node.text? || node.document?
|
479
485
|
|
480
|
-
|
486
|
+
if node[:id].present?
|
487
|
+
id_tracker.record_id_pasted(node[:id])
|
488
|
+
node[:id] = id_tracker.modified_id_to_paste(node[:id])
|
489
|
+
end
|
481
490
|
end
|
482
491
|
temp_copy.to_s
|
483
492
|
end
|
484
493
|
|
485
494
|
# Copy the element's id
|
486
495
|
def copied_id
|
487
|
-
|
488
|
-
|
496
|
+
id_tracker.record_id_copied(id)
|
497
|
+
id_tracker.modified_id_to_paste(id)
|
489
498
|
end
|
490
499
|
|
491
500
|
# Delete the element
|
@@ -499,6 +508,21 @@ module Kitchen
|
|
499
508
|
Element.new(node: raw.parent, document: document, short_type: "parent(#{short_type})")
|
500
509
|
end
|
501
510
|
|
511
|
+
# returns previous element
|
512
|
+
# skips double indentations that the nokigiri sometimes picks up
|
513
|
+
# nil if there's no previous sibling
|
514
|
+
#
|
515
|
+
def previous
|
516
|
+
prev = raw.previous
|
517
|
+
return prev if prev.nil?
|
518
|
+
|
519
|
+
Element.new(
|
520
|
+
node: prev,
|
521
|
+
document: document,
|
522
|
+
short_type: "previous(#{short_type})"
|
523
|
+
)
|
524
|
+
end
|
525
|
+
|
502
526
|
# TODO: make it clear if all of these methods take Element, Node, or String
|
503
527
|
|
504
528
|
# If child argument given, prepends it before the element's current children.
|
@@ -578,9 +602,9 @@ module Kitchen
|
|
578
602
|
attributes.each do |k, v|
|
579
603
|
new_node[k.to_s.gsub(/([^_])_([^_])/, '\1-\2').gsub('__', '_')] = v
|
580
604
|
end
|
581
|
-
new_node.children = children
|
605
|
+
new_node.children = children
|
582
606
|
yield Element.new(node: new_node, document: document, short_type: nil) if block_given?
|
583
|
-
end
|
607
|
+
end
|
584
608
|
|
585
609
|
self
|
586
610
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kitchen
|
4
|
+
# Compare one string with another
|
5
|
+
#
|
6
|
+
# Returns 0 if first string equals second,
|
7
|
+
# 1 if first string is greater than the second
|
8
|
+
# and -1 if first string is less than the second.
|
9
|
+
#
|
10
|
+
class I18nString < String
|
11
|
+
|
12
|
+
def <=>(other)
|
13
|
+
I18n.sort_strings(self, other)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kitchen
|
4
|
+
# A class to track and modify duplicate IDs in a document
|
5
|
+
#
|
6
|
+
class IdTracker
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@id_data = Hash.new { |hash, key| hash[key] = { count: 0, last_pasted: false } }
|
10
|
+
@id_copy_suffix = '_copy_'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Keeps track that an element with the given ID has been copied. When such
|
14
|
+
# elements are pasted, this information is used to give those elements unique
|
15
|
+
# IDs that don't duplicate the original element.
|
16
|
+
#
|
17
|
+
# @param id [String] the ID
|
18
|
+
#
|
19
|
+
def record_id_copied(id)
|
20
|
+
return if id.blank?
|
21
|
+
|
22
|
+
@id_data[id][:count] += 1
|
23
|
+
@id_data[id][:last_pasted] = false
|
24
|
+
end
|
25
|
+
|
26
|
+
# Keeps track that an element with the given ID has been cut.
|
27
|
+
#
|
28
|
+
# @param id [String]
|
29
|
+
#
|
30
|
+
def record_id_cut(id)
|
31
|
+
return if id.blank?
|
32
|
+
|
33
|
+
@id_data[id][:count] -= 1 if @id_data[id][:count].positive?
|
34
|
+
@id_data[id][:last_pasted] = false
|
35
|
+
end
|
36
|
+
|
37
|
+
# Keeps track that an element with the given ID has been pasted.
|
38
|
+
#
|
39
|
+
# @param id [String]
|
40
|
+
#
|
41
|
+
def record_id_pasted(id)
|
42
|
+
return if id.blank?
|
43
|
+
|
44
|
+
@id_data[id][:count] += 1 if @id_data[id][:last_pasted]
|
45
|
+
@id_data[id][:last_pasted] = true
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns a unique ID given the ID of an element that was copied and is about
|
49
|
+
# to be pasted
|
50
|
+
#
|
51
|
+
# @param original_id [String]
|
52
|
+
# @return [String]
|
53
|
+
#
|
54
|
+
def modified_id_to_paste(original_id)
|
55
|
+
return nil if original_id.nil?
|
56
|
+
return '' if original_id.blank?
|
57
|
+
|
58
|
+
count = @id_data[original_id][:count]
|
59
|
+
# A count of 0 means the element was cut and this is the first paste, do not
|
60
|
+
# modify the ID; otherwise, use the uniquified ID.
|
61
|
+
if count.zero?
|
62
|
+
original_id
|
63
|
+
else
|
64
|
+
"#{original_id}#{@id_copy_suffix}#{count}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/kitchen/oven.rb
CHANGED
@@ -28,6 +28,8 @@ module Kitchen
|
|
28
28
|
config: config
|
29
29
|
)
|
30
30
|
|
31
|
+
I18n.locale = doc.locale
|
32
|
+
|
31
33
|
[recipes].flatten.each do |recipe|
|
32
34
|
recipe.document = doc
|
33
35
|
recipe.bake
|
@@ -35,7 +37,7 @@ module Kitchen
|
|
35
37
|
profile.baked!
|
36
38
|
|
37
39
|
File.open(output_file, 'w') do |f|
|
38
|
-
f.write doc.to_xhtml(indent: 2)
|
40
|
+
f.write doc.to_xhtml(indent: 2, encoding: doc.encoding || 'utf-8')
|
39
41
|
end
|
40
42
|
profile.written!
|
41
43
|
|
data/lib/kitchen/page_element.rb
CHANGED
@@ -88,11 +88,10 @@ module Kitchen
|
|
88
88
|
|
89
89
|
# Returns the summary element.
|
90
90
|
#
|
91
|
-
# @
|
92
|
-
# @return [Element]
|
91
|
+
# @return [Element, nil] the summary or nil if no summary found
|
93
92
|
#
|
94
93
|
def summary
|
95
|
-
first
|
94
|
+
first(selectors.page_summary)
|
96
95
|
end
|
97
96
|
|
98
97
|
# Returns the exercises element.
|