openstax_kitchen 1.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 +7 -0
- data/.devcontainer/devcontainer.json +19 -0
- data/.github/workflows/tests.yml +36 -0
- data/.gitignore +20 -0
- data/.rspec +3 -0
- data/.solargraph.yml +15 -0
- data/CHANGELOG.md +11 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Dockerfile +19 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +674 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/normalize +79 -0
- data/bin/setup +8 -0
- data/books/chemistry2e/bake.rb +133 -0
- data/codecov.yaml +27 -0
- data/docker-compose.yml +12 -0
- data/docker/bash +1 -0
- data/docker/entrypoint +9 -0
- data/lib/kitchen.rb +57 -0
- data/lib/kitchen/ancestor.rb +30 -0
- data/lib/kitchen/book_document.rb +18 -0
- data/lib/kitchen/book_element.rb +24 -0
- data/lib/kitchen/book_element_enumerator.rb +5 -0
- data/lib/kitchen/book_recipe.rb +25 -0
- data/lib/kitchen/chapter_element.rb +35 -0
- data/lib/kitchen/chapter_element_enumerator.rb +13 -0
- data/lib/kitchen/clipboard.rb +37 -0
- data/lib/kitchen/composite_chapter_element.rb +23 -0
- data/lib/kitchen/composite_page_element.rb +27 -0
- data/lib/kitchen/composite_page_element_enumerator.rb +13 -0
- data/lib/kitchen/config.rb +20 -0
- data/lib/kitchen/counter.rb +34 -0
- data/lib/kitchen/debug/print_recipe_error.rb +80 -0
- data/lib/kitchen/directions/bake_appendix.rb +26 -0
- data/lib/kitchen/directions/bake_chapter_glossary.rb +34 -0
- data/lib/kitchen/directions/bake_chapter_introductions.rb +58 -0
- data/lib/kitchen/directions/bake_chapter_key_equations.rb +30 -0
- data/lib/kitchen/directions/bake_chapter_summary.rb +52 -0
- data/lib/kitchen/directions/bake_composite_pages.rb +13 -0
- data/lib/kitchen/directions/bake_example.rb +31 -0
- data/lib/kitchen/directions/bake_exercises.rb +164 -0
- data/lib/kitchen/directions/bake_figure.rb +25 -0
- data/lib/kitchen/directions/bake_footnotes/main.rb +11 -0
- data/lib/kitchen/directions/bake_footnotes/v1.rb +38 -0
- data/lib/kitchen/directions/bake_index/main.rb +11 -0
- data/lib/kitchen/directions/bake_index/v1.rb +138 -0
- data/lib/kitchen/directions/bake_index/v1.xhtml.erb +28 -0
- data/lib/kitchen/directions/bake_math_in_paragraph.rb +13 -0
- data/lib/kitchen/directions/bake_notes.rb +58 -0
- data/lib/kitchen/directions/bake_numbered_table/main.rb +11 -0
- data/lib/kitchen/directions/bake_numbered_table/v1.rb +47 -0
- data/lib/kitchen/directions/bake_stepwise.rb +27 -0
- data/lib/kitchen/directions/bake_toc.rb +103 -0
- data/lib/kitchen/directions/bake_unnumbered_tables.rb +14 -0
- data/lib/kitchen/directions/move_title_text_into_span.rb +15 -0
- data/lib/kitchen/document.rb +142 -0
- data/lib/kitchen/element.rb +15 -0
- data/lib/kitchen/element_base.rb +444 -0
- data/lib/kitchen/element_enumerator.rb +12 -0
- data/lib/kitchen/element_enumerator_base.rb +101 -0
- data/lib/kitchen/element_enumerator_factory.rb +111 -0
- data/lib/kitchen/element_factory.rb +32 -0
- data/lib/kitchen/errors.rb +4 -0
- data/lib/kitchen/example_element.rb +20 -0
- data/lib/kitchen/example_element_enumerator.rb +13 -0
- data/lib/kitchen/figure_element.rb +20 -0
- data/lib/kitchen/figure_element_enumerator.rb +13 -0
- data/lib/kitchen/mixins/block_error_if.rb +19 -0
- data/lib/kitchen/note_element.rb +43 -0
- data/lib/kitchen/note_element_enumerator.rb +13 -0
- data/lib/kitchen/oven.rb +61 -0
- data/lib/kitchen/page_element.rb +51 -0
- data/lib/kitchen/page_element_enumerator.rb +13 -0
- data/lib/kitchen/pantry.rb +35 -0
- data/lib/kitchen/patches/nokogiri.rb +31 -0
- data/lib/kitchen/patches/renderable.rb +31 -0
- data/lib/kitchen/patches/string.rb +5 -0
- data/lib/kitchen/recipe.rb +78 -0
- data/lib/kitchen/search_history.rb +33 -0
- data/lib/kitchen/selectors/base.rb +8 -0
- data/lib/kitchen/selectors/standard_1.rb +12 -0
- data/lib/kitchen/table_element.rb +36 -0
- data/lib/kitchen/table_element_enumerator.rb +13 -0
- data/lib/kitchen/term_element.rb +16 -0
- data/lib/kitchen/term_element_enumerator.rb +13 -0
- data/lib/kitchen/transliterations.rb +19 -0
- data/lib/kitchen/type_casting_element_enumerator.rb +23 -0
- data/lib/kitchen/utils.rb +19 -0
- data/lib/kitchen/version.rb +3 -0
- data/lib/locales/en.yml +21 -0
- data/lib/notes.md +9 -0
- data/openstax_kitchen.gemspec +39 -0
- data/tutorials/00/expected_baked.html +3 -0
- data/tutorials/00/raw.html +3 -0
- data/tutorials/00/solution_1.rb +7 -0
- data/tutorials/00/solution_2.rb +6 -0
- data/tutorials/01/expected_baked.html +66 -0
- data/tutorials/01/raw.html +62 -0
- data/tutorials/01/solution_1.rb +16 -0
- data/tutorials/01/solution_2.rb +24 -0
- data/tutorials/02/expected_baked.html +207 -0
- data/tutorials/02/raw.html +201 -0
- data/tutorials/02/solution_1.rb +29 -0
- data/tutorials/03/expected_baked.html +33 -0
- data/tutorials/03/raw.html +31 -0
- data/tutorials/03/solution_1.rb +16 -0
- data/tutorials/03/solution_2.rb +15 -0
- data/tutorials/04/expected_baked.html +36 -0
- data/tutorials/04/raw.html +36 -0
- data/tutorials/04/solution_1.rb +20 -0
- data/tutorials/04/solution_2.rb +25 -0
- data/tutorials/05/expected_baked.html +11 -0
- data/tutorials/05/raw.html +11 -0
- data/tutorials/05/solution_1.rb +9 -0
- data/tutorials/check_it +64 -0
- data/tutorials/setup_my_recipes +30 -0
- metadata +278 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class ChapterElement < ElementBase
|
|
3
|
+
|
|
4
|
+
def initialize(node:, document: nil)
|
|
5
|
+
super(node: node,
|
|
6
|
+
document: document,
|
|
7
|
+
enumerator_class: ChapterElementEnumerator,
|
|
8
|
+
short_type: :chapter)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def title
|
|
12
|
+
# Get the title in the immediate children, not the one in the metadata. Could use
|
|
13
|
+
# CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
|
|
14
|
+
# but xpath is shorter
|
|
15
|
+
first!("./*[@data-type = 'document-title']")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def introduction_page
|
|
19
|
+
pages('.introduction').first
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def glossaries
|
|
23
|
+
search("div[data-type='glossary']")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def key_equations
|
|
27
|
+
search("section.key-equations")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.is_the_element_class_for?(node)
|
|
31
|
+
node['data-type'] == "chapter"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class ChapterElementEnumerator < ElementEnumeratorBase
|
|
3
|
+
|
|
4
|
+
def self.factory
|
|
5
|
+
ElementEnumeratorFactory.new(
|
|
6
|
+
default_css_or_xpath: "div[data-type='chapter']", # TODO element.document.selectors.chapter
|
|
7
|
+
sub_element_class: ChapterElement,
|
|
8
|
+
enumerator_class: self
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
# A place to store lists of things during recipe work. Essentially a
|
|
3
|
+
# slightly fancy array.
|
|
4
|
+
#
|
|
5
|
+
class Clipboard
|
|
6
|
+
include Enumerable
|
|
7
|
+
|
|
8
|
+
attr_reader :items
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
clear
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def add(item)
|
|
15
|
+
@items.push(item)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def clear
|
|
19
|
+
@items = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def paste
|
|
23
|
+
@items.map(&:paste).join("")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def each(&block)
|
|
27
|
+
@items.each do |item|
|
|
28
|
+
block.call(item)
|
|
29
|
+
end
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def sort_by!(&block)
|
|
34
|
+
@items.sort_by!(&block)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class CompositeChapterElement < ElementBase
|
|
3
|
+
|
|
4
|
+
def initialize(node:, document: nil)
|
|
5
|
+
super(node: node,
|
|
6
|
+
document: document,
|
|
7
|
+
enumerator_class: ElementEnumerator,
|
|
8
|
+
short_type: :composite_chapter)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def title
|
|
12
|
+
# Get the title in the immediate children, not the one in the metadata. Could use
|
|
13
|
+
# CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
|
|
14
|
+
# but xpath is shorter
|
|
15
|
+
first!("./*[@data-type = 'document-title']")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.is_the_element_class_for?(node)
|
|
19
|
+
node['data-type'] == "composite-chapter"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class CompositePageElement < ElementBase
|
|
3
|
+
|
|
4
|
+
def initialize(node:, document: nil)
|
|
5
|
+
super(node: node,
|
|
6
|
+
document: document,
|
|
7
|
+
enumerator_class: CompositePageElementEnumerator,
|
|
8
|
+
short_type: :composite_page)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def title
|
|
12
|
+
# Get the title in the immediate children, not the one in the metadata. Could use
|
|
13
|
+
# CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
|
|
14
|
+
# but xpath is shorter
|
|
15
|
+
first!("./*[@data-type = 'document-title']")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.is_the_element_class_for?(node)
|
|
19
|
+
node['data-type'] == "composite-page"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def is_index?
|
|
23
|
+
has_class?("os-index-container")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class CompositePageElementEnumerator < ElementEnumeratorBase
|
|
3
|
+
|
|
4
|
+
def self.factory
|
|
5
|
+
ElementEnumeratorFactory.new(
|
|
6
|
+
default_css_or_xpath: "div[data-type='composite-page']",
|
|
7
|
+
sub_element_class: CompositePageElement,
|
|
8
|
+
enumerator_class: self
|
|
9
|
+
)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class Config
|
|
3
|
+
|
|
4
|
+
attr_reader :selectors
|
|
5
|
+
|
|
6
|
+
def self.new_from_file(file)
|
|
7
|
+
raise "NYI"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.new_default
|
|
11
|
+
new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(hash: {}, selectors: nil)
|
|
15
|
+
@selectors = selectors || Kitchen::Selectors::Standard1.new
|
|
16
|
+
@hash = hash
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
class Counter # hehe
|
|
3
|
+
|
|
4
|
+
def initialize
|
|
5
|
+
reset
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Increase the value of the counter
|
|
9
|
+
#
|
|
10
|
+
# @param by [Integer] the amount to increase by
|
|
11
|
+
#
|
|
12
|
+
def increment(by: 1)
|
|
13
|
+
@value += by
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# (see #increment)
|
|
17
|
+
alias_method :inc, :increment
|
|
18
|
+
|
|
19
|
+
# Returns the value of the counter
|
|
20
|
+
#
|
|
21
|
+
# @return [Integer]
|
|
22
|
+
def get
|
|
23
|
+
@value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Reset the value of the counter
|
|
27
|
+
#
|
|
28
|
+
# @param to [Integer] the value to reset to
|
|
29
|
+
def reset(to: 0)
|
|
30
|
+
@value = to
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'rainbow'
|
|
2
|
+
|
|
3
|
+
module Kitchen
|
|
4
|
+
module Debug
|
|
5
|
+
|
|
6
|
+
CONTEXT_LINES = 2
|
|
7
|
+
|
|
8
|
+
def self.print_recipe_error(error:, source_location:, document:)
|
|
9
|
+
error_location = error.backtrace.detect do |entry|
|
|
10
|
+
entry.start_with?(source_location) || entry.match?(/kitchen\/lib\/kitchen\/directions/)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
error_filename, error_line_number = error_location.match(/(.*):(\d+):/)[1..2]
|
|
14
|
+
error_line_number = error_line_number.to_i
|
|
15
|
+
|
|
16
|
+
puts "The recipe has an error: " + Rainbow(error.message).bright
|
|
17
|
+
puts "at or near the following #{Rainbow('highlighted').red} line"
|
|
18
|
+
puts "\n"
|
|
19
|
+
puts "-----+ #{Rainbow(error_filename).bright} -----"
|
|
20
|
+
|
|
21
|
+
line_numbers_before = (error_line_number-CONTEXT_LINES..error_line_number-1)
|
|
22
|
+
line_numbers_after = (error_line_number+1..error_line_number+CONTEXT_LINES)
|
|
23
|
+
|
|
24
|
+
File.readlines(error_filename).each.with_index do |line, line_index|
|
|
25
|
+
line_number = line_index + 1
|
|
26
|
+
|
|
27
|
+
if line_numbers_before.include?(line_number) ||
|
|
28
|
+
line_numbers_after.include?(line_number)
|
|
29
|
+
print_file_line(line_number, line)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if line_number == error_line_number
|
|
33
|
+
print_file_line(line_number, Rainbow(line.chomp).red)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
puts "\n"
|
|
38
|
+
|
|
39
|
+
print_specific_help_line(error)
|
|
40
|
+
|
|
41
|
+
current_node = document.location&.raw
|
|
42
|
+
|
|
43
|
+
if current_node
|
|
44
|
+
puts "Encountered on line #{Rainbow(current_node.line).red} in the input document on element:"
|
|
45
|
+
puts current_node.dup.tap{|node| node.inner_html="..." if node.inner_html != ""}.to_s
|
|
46
|
+
puts "\n"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if ENV['VERBOSE']
|
|
50
|
+
puts "Full backtrace:\n"
|
|
51
|
+
puts error.backtrace.map{|line| Rainbow(line).blue}
|
|
52
|
+
else
|
|
53
|
+
puts "Full backtrace suppressed (enable by setting the VERBOSE environment variable to something)"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
protected
|
|
58
|
+
|
|
59
|
+
def self.print_file_line(line_number, line)
|
|
60
|
+
puts "#{"%5s" % line_number}| #{line}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.print_specific_help_line(error)
|
|
64
|
+
# No specific help lines at the moment, an example is shown for the future
|
|
65
|
+
|
|
66
|
+
# help_line = case error.message
|
|
67
|
+
# when /some string in error/
|
|
68
|
+
# "`foo` needs to be called on a Bar object"
|
|
69
|
+
# else
|
|
70
|
+
# nil
|
|
71
|
+
# end
|
|
72
|
+
|
|
73
|
+
# if !help_line.nil?
|
|
74
|
+
# puts help_line
|
|
75
|
+
# puts "\n"
|
|
76
|
+
# end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
module Directions
|
|
3
|
+
module BakeAppendix
|
|
4
|
+
|
|
5
|
+
def self.v1(page:, number:)
|
|
6
|
+
title = page.title
|
|
7
|
+
title.name = "h1"
|
|
8
|
+
title.replace_children(with:
|
|
9
|
+
<<~HTML
|
|
10
|
+
<span class="os-part-text">#{I18n.t(:appendix)} </span>
|
|
11
|
+
<span class="os-number">#{number}</span>
|
|
12
|
+
<span class="os-divider"> </span>
|
|
13
|
+
<span data-type="" itemprop="" class="os-text">#{title.children}</span>
|
|
14
|
+
HTML
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Make a section with data-depth of X have a header level of X+1
|
|
18
|
+
page.search("section").each do |section|
|
|
19
|
+
title = section.first!("[data-type='title']")
|
|
20
|
+
title.name = "h#{section['data-depth'].to_i + 1}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
module Directions
|
|
3
|
+
module BakeChapterGlossary
|
|
4
|
+
|
|
5
|
+
def self.v1(chapter:, metadata_source:)
|
|
6
|
+
metadata_elements = metadata_source.search(%w(.authors .publishers .print-style
|
|
7
|
+
.permissions [data-type='subject'])).copy
|
|
8
|
+
|
|
9
|
+
definitions = chapter.glossaries.search("dl").cut
|
|
10
|
+
definitions.sort_by! do |definition|
|
|
11
|
+
[definition.first("dt").text.downcase, definition.first("dd").text.downcase]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
chapter.glossaries.trash
|
|
15
|
+
|
|
16
|
+
chapter.append(child:
|
|
17
|
+
<<~HTML
|
|
18
|
+
<div class="os-eoc os-glossary-container" data-type="composite-page" data-uuid-key="glossary">
|
|
19
|
+
<h2 data-type="document-title">
|
|
20
|
+
<span class="os-text">#{I18n.t(:eoc_key_terms_title)}</span>
|
|
21
|
+
</h2>
|
|
22
|
+
<div data-type="metadata" style="display: none;">
|
|
23
|
+
<h1 data-type="document-title" itemprop="name">#{I18n.t(:eoc_key_terms_title)}</h1>
|
|
24
|
+
#{metadata_elements.paste}
|
|
25
|
+
</div>
|
|
26
|
+
#{definitions.paste}
|
|
27
|
+
</div>
|
|
28
|
+
HTML
|
|
29
|
+
) unless definitions.none?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
module Directions
|
|
3
|
+
module BakeChapterIntroductions
|
|
4
|
+
|
|
5
|
+
def self.v1(book:)
|
|
6
|
+
book.chapters.each do |chapter|
|
|
7
|
+
outline_items_html = chapter.pages.map do |page|
|
|
8
|
+
next if page.is_introduction?
|
|
9
|
+
|
|
10
|
+
<<~HTML
|
|
11
|
+
<div class="os-chapter-objective">
|
|
12
|
+
<a class="os-chapter-objective" href="##{page.title[:id]}">
|
|
13
|
+
<span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)-1}</span>
|
|
14
|
+
<span class="os-divider"> </span>
|
|
15
|
+
<span data-type="" itemprop="" class="os-text">#{page.title.children[0].text}</span>
|
|
16
|
+
</a>
|
|
17
|
+
</div>
|
|
18
|
+
HTML
|
|
19
|
+
end.join("")
|
|
20
|
+
|
|
21
|
+
introduction_page = chapter.introduction_page
|
|
22
|
+
|
|
23
|
+
introduction_page.search("div[data-type='description']").trash
|
|
24
|
+
introduction_page.search("div[data-type='abstract']").trash
|
|
25
|
+
|
|
26
|
+
title = introduction_page.title.cut
|
|
27
|
+
title.name = "h2"
|
|
28
|
+
MoveTitleTextIntoSpan.v1(title: title)
|
|
29
|
+
|
|
30
|
+
intro_content = introduction_page.search("> :not([data-type='metadata']):not(figure)").cut
|
|
31
|
+
|
|
32
|
+
introduction_page.append(child:
|
|
33
|
+
<<~HTML
|
|
34
|
+
<div class="intro-body">
|
|
35
|
+
<div class="os-chapter-outline">
|
|
36
|
+
<h3 class="os-title">Chapter Outline</h3>
|
|
37
|
+
#{outline_items_html}
|
|
38
|
+
</div>
|
|
39
|
+
<div class="intro-text">
|
|
40
|
+
#{title.paste}
|
|
41
|
+
#{intro_content.paste}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
HTML
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
v1_update_selectors(book)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.v1_update_selectors(something_with_selectors)
|
|
52
|
+
something_with_selectors.selectors.title_in_introduction_page =
|
|
53
|
+
".intro-text > [data-type='document-title']"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Kitchen
|
|
2
|
+
module Directions
|
|
3
|
+
module BakeChapterKeyEquations
|
|
4
|
+
|
|
5
|
+
def self.v1(chapter:, metadata_source:)
|
|
6
|
+
metadata_elements = metadata_source.search(%w(.authors .publishers .print-style
|
|
7
|
+
.permissions [data-type='subject'])).copy
|
|
8
|
+
|
|
9
|
+
chapter.key_equations.search("h3").trash
|
|
10
|
+
key_equations = chapter.key_equations.cut
|
|
11
|
+
|
|
12
|
+
chapter.append(child:
|
|
13
|
+
<<~HTML
|
|
14
|
+
<div class="os-eoc os-key-equations-container" data-type="composite-page" data-uuid-key=".key-equations">
|
|
15
|
+
<h2 data-type="document-title">
|
|
16
|
+
<span class="os-text">#{I18n.t(:eoc_key_equations)}</span>
|
|
17
|
+
</h2>
|
|
18
|
+
<div data-type="metadata" style="display: none;">
|
|
19
|
+
<h1 data-type="document-title" itemprop="name">#{I18n.t(:eoc_key_equations)}</h1>
|
|
20
|
+
#{metadata_elements.paste}
|
|
21
|
+
</div>
|
|
22
|
+
#{key_equations.paste}
|
|
23
|
+
</div>
|
|
24
|
+
HTML
|
|
25
|
+
) unless key_equations.none?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|