epuber 0.8.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/epuber.gemspec +3 -6
- data/lib/epuber/book/contributor.rb +10 -6
- data/lib/epuber/book/file_request.rb +2 -2
- data/lib/epuber/book/target.rb +10 -10
- data/lib/epuber/book.rb +2 -2
- data/lib/epuber/checker/text_checker.rb +14 -6
- data/lib/epuber/checker_transformer_base.rb +1 -1
- data/lib/epuber/command/build.rb +6 -1
- data/lib/epuber/command/from_file.rb +39 -0
- data/lib/epuber/command/init.rb +11 -9
- data/lib/epuber/command/server.rb +1 -1
- data/lib/epuber/command.rb +1 -0
- data/lib/epuber/compiler/file_database.rb +2 -2
- data/lib/epuber/compiler/file_finders/abstract.rb +3 -3
- data/lib/epuber/compiler/file_resolver.rb +3 -2
- data/lib/epuber/compiler/file_types/abstract_file.rb +1 -3
- data/lib/epuber/compiler/file_types/bade_file.rb +9 -9
- data/lib/epuber/compiler/file_types/css_file.rb +84 -0
- data/lib/epuber/compiler/file_types/source_file.rb +31 -0
- data/lib/epuber/compiler/file_types/stylus_file.rb +4 -3
- data/lib/epuber/compiler/nav_generator.rb +5 -5
- data/lib/epuber/compiler/opf_generator.rb +4 -4
- data/lib/epuber/compiler/xhtml_processor.rb +7 -25
- data/lib/epuber/compiler.rb +12 -7
- data/lib/epuber/config.rb +3 -3
- data/lib/epuber/dsl/attribute.rb +1 -1
- data/lib/epuber/dsl/attribute_support.rb +4 -4
- data/lib/epuber/dsl/object.rb +2 -2
- data/lib/epuber/from_file/bookspec_generator.rb +371 -0
- data/lib/epuber/from_file/encryption_handler.rb +146 -0
- data/lib/epuber/from_file/from_file_executor.rb +140 -0
- data/lib/epuber/from_file/nav_file.rb +163 -0
- data/lib/epuber/from_file/opf_file.rb +219 -0
- data/lib/epuber/plugin.rb +1 -1
- data/lib/epuber/server.rb +17 -17
- data/lib/epuber/transformer/book_transformer.rb +108 -0
- data/lib/epuber/transformer.rb +2 -0
- data/lib/epuber/user_interface.rb +2 -2
- data/lib/epuber/vendor/ruby_templater.rb +3 -3
- data/lib/epuber/vendor/version.rb +3 -3
- data/lib/epuber/version.rb +1 -1
- metadata +40 -59
@@ -5,9 +5,9 @@ require 'epuber-stylus'
|
|
5
5
|
module Epuber
|
6
6
|
class Compiler
|
7
7
|
module FileTypes
|
8
|
-
require_relative '
|
8
|
+
require_relative 'css_file'
|
9
9
|
|
10
|
-
class StylusFile <
|
10
|
+
class StylusFile < CSSFile
|
11
11
|
# @param [Compiler::CompilationContext] compilation_context
|
12
12
|
#
|
13
13
|
def process(compilation_context)
|
@@ -19,7 +19,8 @@ module Epuber
|
|
19
19
|
Stylus.define('__book_title', compilation_context.book.title)
|
20
20
|
Stylus.define('__const', compilation_context.target.constants)
|
21
21
|
|
22
|
-
|
22
|
+
css = Stylus.compile(File.new(abs_source_path))
|
23
|
+
write_compiled(process_css(css, compilation_context))
|
23
24
|
|
24
25
|
update_metadata!
|
25
26
|
end
|
@@ -94,7 +94,7 @@ module Epuber
|
|
94
94
|
@xml.ncx(nav_namespaces, version: '2005-1') do
|
95
95
|
# head
|
96
96
|
@xml.head do
|
97
|
-
@xml.meta(name: 'dtb:uid', content:
|
97
|
+
@xml.meta(name: 'dtb:uid', content: @target.identifier || "urn:isbn:#{@target.isbn}")
|
98
98
|
end
|
99
99
|
|
100
100
|
# title
|
@@ -111,7 +111,7 @@ module Epuber
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
# @param
|
114
|
+
# @param [Array<Epuber::Book::TocItem>] toc_items
|
115
115
|
#
|
116
116
|
def visit_toc_items(toc_items)
|
117
117
|
iterate_lambda = lambda do
|
@@ -133,7 +133,7 @@ module Epuber
|
|
133
133
|
toc_items.any? { |a| a.title || contains_item_with_title(a.sub_items) }
|
134
134
|
end
|
135
135
|
|
136
|
-
# @param
|
136
|
+
# @param [Epuber::Book::TocItem] toc_item
|
137
137
|
#
|
138
138
|
def visit_toc_item(toc_item)
|
139
139
|
result_file_path = pretty_path_for_toc_item(toc_item)
|
@@ -165,7 +165,7 @@ module Epuber
|
|
165
165
|
|
166
166
|
# --------------- landmarks -----------------------------
|
167
167
|
|
168
|
-
# @param
|
168
|
+
# @param [Array<Epuber::Book::TocItem>] toc_items
|
169
169
|
#
|
170
170
|
def landmarks_visit_toc_items(toc_items)
|
171
171
|
toc_items.each do |child_item|
|
@@ -173,7 +173,7 @@ module Epuber
|
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|
176
|
-
# @param
|
176
|
+
# @param [Epuber::Book::TocItem] toc_item
|
177
177
|
#
|
178
178
|
def landmarks_visit_toc_item(toc_item)
|
179
179
|
landmarks = toc_item.landmarks
|
@@ -217,7 +217,7 @@ module Epuber
|
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
|
-
# @param
|
220
|
+
# @param [Array<Epuber::Book::TocItem>] toc_items
|
221
221
|
#
|
222
222
|
# @return nil
|
223
223
|
#
|
@@ -227,7 +227,7 @@ module Epuber
|
|
227
227
|
end
|
228
228
|
end
|
229
229
|
|
230
|
-
# @param
|
230
|
+
# @param [Epuber::Book::TocItem] toc_item
|
231
231
|
#
|
232
232
|
# @return nil
|
233
233
|
#
|
@@ -251,7 +251,7 @@ module Epuber
|
|
251
251
|
|
252
252
|
# Creates id from file path
|
253
253
|
#
|
254
|
-
# @param
|
254
|
+
# @param [String] path
|
255
255
|
#
|
256
256
|
# @return [String]
|
257
257
|
#
|
@@ -263,7 +263,7 @@ module Epuber
|
|
263
263
|
|
264
264
|
# Creates proper mime-type for file
|
265
265
|
#
|
266
|
-
# @param
|
266
|
+
# @param [Epuber::Compiler::FileTypes::AbstractFile | String] file
|
267
267
|
#
|
268
268
|
# @return [String]
|
269
269
|
#
|
@@ -50,7 +50,8 @@ module Epuber
|
|
50
50
|
|
51
51
|
parse_options = Nokogiri::XML::ParseOptions::DEFAULT_XML |
|
52
52
|
Nokogiri::XML::ParseOptions::NOERROR | # to silence any errors or warnings printing into console
|
53
|
-
Nokogiri::XML::ParseOptions::NOWARNING
|
53
|
+
Nokogiri::XML::ParseOptions::NOWARNING |
|
54
|
+
Nokogiri::XML::ParseOptions::NOENT
|
54
55
|
|
55
56
|
doc = Nokogiri::XML("#{before}<root>#{text}</root>", file_path, nil, parse_options)
|
56
57
|
text_for_errors = before + text
|
@@ -341,34 +342,15 @@ module Epuber
|
|
341
342
|
end
|
342
343
|
|
343
344
|
def self.resolve_resources_in(node_css_query, attribute_name, resource_group, xhtml_doc, file_path, file_resolver)
|
344
|
-
dirname = File.dirname(file_path)
|
345
|
-
|
346
345
|
xhtml_doc.css(node_css_query).each do |img|
|
347
346
|
path = img[attribute_name]
|
348
347
|
next if path.nil?
|
349
348
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
pkg_abs_path = File.expand_path(new_path, dirname).unicode_normalize
|
356
|
-
pkg_new_path = Pathname.new(pkg_abs_path).relative_path_from(Pathname.new(file_resolver.source_path)).to_s
|
357
|
-
|
358
|
-
file_class = FileResolver.file_class_for(File.extname(new_path))
|
359
|
-
file = file_class.new(pkg_new_path)
|
360
|
-
file.path_type = :manifest
|
361
|
-
file_resolver.add_file(file)
|
362
|
-
|
363
|
-
new_path = FileResolver.renamed_file_with_path(new_path)
|
364
|
-
rescue UnparseableLinkError, FileFinders::FileNotFoundError, FileFinders::MultipleFilesFoundError => e
|
365
|
-
UI.warning(e.to_s, location: img)
|
366
|
-
|
367
|
-
next
|
368
|
-
end
|
369
|
-
end
|
370
|
-
|
371
|
-
img[attribute_name] = new_path
|
349
|
+
new_path = Compiler::FileTypes::SourceFile.resolve_relative_file(file_path,
|
350
|
+
path,
|
351
|
+
file_resolver,
|
352
|
+
group: resource_group)
|
353
|
+
img[attribute_name] = new_path if new_path
|
372
354
|
end
|
373
355
|
end
|
374
356
|
|
data/lib/epuber/compiler.rb
CHANGED
@@ -39,8 +39,8 @@ module Epuber
|
|
39
39
|
#
|
40
40
|
attr_reader :compilation_context
|
41
41
|
|
42
|
-
# @param
|
43
|
-
# @param
|
42
|
+
# @param [Epuber::Book::Book] book
|
43
|
+
# @param [Epuber::Book::Target] target
|
44
44
|
#
|
45
45
|
def initialize(book, target)
|
46
46
|
@book = book
|
@@ -50,7 +50,7 @@ module Epuber
|
|
50
50
|
|
51
51
|
# Compile target to build folder
|
52
52
|
#
|
53
|
-
# @param
|
53
|
+
# @param [String] build_folder path to folder, where will be stored all compiled files
|
54
54
|
# @param [Bool] check should run non-release checkers
|
55
55
|
# @param [Bool] write should perform transformations of source files and write them back
|
56
56
|
# @param [Bool] release this is release build
|
@@ -88,6 +88,11 @@ module Epuber
|
|
88
88
|
|
89
89
|
process_all_target_files
|
90
90
|
generate_other_files
|
91
|
+
|
92
|
+
compilation_context.perform_plugin_things(Transformer, :after_all_text_files) do |transformer|
|
93
|
+
transformer.call(@book, compilation_context)
|
94
|
+
end
|
95
|
+
|
91
96
|
process_global_ids
|
92
97
|
|
93
98
|
# build folder cleanup
|
@@ -109,7 +114,7 @@ module Epuber
|
|
109
114
|
|
110
115
|
# Archives current target files to epub
|
111
116
|
#
|
112
|
-
# @param
|
117
|
+
# @param [String] path path to created archive
|
113
118
|
#
|
114
119
|
# @return [String] path
|
115
120
|
#
|
@@ -285,7 +290,7 @@ module Epuber
|
|
285
290
|
UI.processing_files_done
|
286
291
|
end
|
287
292
|
|
288
|
-
# @param
|
293
|
+
# @param [Epuber::Book::TocItem] toc_item
|
289
294
|
#
|
290
295
|
def parse_toc_item(toc_item)
|
291
296
|
unless toc_item.file_request.nil?
|
@@ -310,7 +315,7 @@ module Epuber
|
|
310
315
|
|
311
316
|
# Validates duplicity of global ids in all files + returns map of global ids to files
|
312
317
|
#
|
313
|
-
# @param
|
318
|
+
# @param [Array<FileTypes::XHTMLFile>] xhtml_files
|
314
319
|
# @return [Hash<String, FileTypes::XHTMLFile>]
|
315
320
|
#
|
316
321
|
def validate_global_ids(xhtml_files)
|
@@ -333,7 +338,7 @@ module Epuber
|
|
333
338
|
map
|
334
339
|
end
|
335
340
|
|
336
|
-
# @param
|
341
|
+
# @param [String] cmd
|
337
342
|
#
|
338
343
|
# @return [void]
|
339
344
|
#
|
data/lib/epuber/config.rb
CHANGED
@@ -14,7 +14,7 @@ module Epuber
|
|
14
14
|
@project_path ||= Dir.pwd.unicode_normalize
|
15
15
|
end
|
16
16
|
|
17
|
-
# @param
|
17
|
+
# @param [String] of_file absolute path to file
|
18
18
|
#
|
19
19
|
# @return [String] relative path to file from root of project
|
20
20
|
#
|
@@ -84,7 +84,7 @@ module Epuber
|
|
84
84
|
bookspec_lockfile.write_to_file
|
85
85
|
end
|
86
86
|
|
87
|
-
# @param
|
87
|
+
# @param [Epuber::Book::Target] target
|
88
88
|
#
|
89
89
|
# @return [String]
|
90
90
|
#
|
@@ -92,7 +92,7 @@ module Epuber
|
|
92
92
|
File.join(working_path, 'build', target.name.to_s)
|
93
93
|
end
|
94
94
|
|
95
|
-
# @param
|
95
|
+
# @param [Epuber::Book::Target] target
|
96
96
|
#
|
97
97
|
# @return [String]
|
98
98
|
#
|
data/lib/epuber/dsl/attribute.rb
CHANGED
@@ -9,8 +9,8 @@ module Epuber
|
|
9
9
|
# attribute :name
|
10
10
|
# attribute :title, required: true, inherited: true
|
11
11
|
#
|
12
|
-
# @param
|
13
|
-
# @param
|
12
|
+
# @param [Symbol] name attribute name
|
13
|
+
# @param [Hash] options
|
14
14
|
#
|
15
15
|
# @see Attribute
|
16
16
|
#
|
@@ -44,8 +44,8 @@ module Epuber
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
# @param
|
48
|
-
# @param
|
47
|
+
# @param [Symbol] name
|
48
|
+
# @param [Epuber::DSL::Attribute] attr
|
49
49
|
#
|
50
50
|
# @return nil
|
51
51
|
#
|
data/lib/epuber/dsl/object.rb
CHANGED
@@ -58,7 +58,7 @@ module Epuber
|
|
58
58
|
|
59
59
|
# Creates new instance by parsing ruby code from file
|
60
60
|
#
|
61
|
-
# @param
|
61
|
+
# @param [String] file_path
|
62
62
|
#
|
63
63
|
# @return [Self]
|
64
64
|
#
|
@@ -68,7 +68,7 @@ module Epuber
|
|
68
68
|
|
69
69
|
# Creates new instance by parsing ruby code from string
|
70
70
|
#
|
71
|
-
# @param
|
71
|
+
# @param [String] string
|
72
72
|
#
|
73
73
|
# @return [Self]
|
74
74
|
#
|
@@ -0,0 +1,371 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Epuber
|
6
|
+
class BookspecGenerator
|
7
|
+
class TocItem
|
8
|
+
# @return [String]
|
9
|
+
#
|
10
|
+
attr_accessor :href
|
11
|
+
|
12
|
+
# @return [String, nil]
|
13
|
+
#
|
14
|
+
attr_accessor :title
|
15
|
+
|
16
|
+
# @return [Array<TocItem>]
|
17
|
+
#
|
18
|
+
attr_accessor :children
|
19
|
+
|
20
|
+
# @return [Array<Symbol>]
|
21
|
+
#
|
22
|
+
attr_accessor :landmarks
|
23
|
+
|
24
|
+
def initialize(href, title = nil, landmarks = [], children = [])
|
25
|
+
@href = href
|
26
|
+
@title = title
|
27
|
+
@landmarks = landmarks
|
28
|
+
@children = children
|
29
|
+
end
|
30
|
+
|
31
|
+
def attribs
|
32
|
+
[href.inspect, title&.inspect, *landmarks.map(&:inspect)].compact.join(', ')
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(other)
|
36
|
+
other.is_a?(TocItem) &&
|
37
|
+
href == other.href &&
|
38
|
+
title == other.title &&
|
39
|
+
landmarks == other.landmarks &&
|
40
|
+
children == other.children
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s(level = 0)
|
44
|
+
indent = ' ' * level
|
45
|
+
children_str = children.map { |c| c.to_s(level + 2) }.join("\n")
|
46
|
+
%(#{indent}#{href.inspect} #{title.inspect} #{landmarks.inspect}\n#{children_str})
|
47
|
+
end
|
48
|
+
|
49
|
+
def inspect
|
50
|
+
%(#<#{self.class.name} #{self}>)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param [Epuber::OpfFile] opf
|
55
|
+
# @param [Epuber::NavFile, nil] nav
|
56
|
+
#
|
57
|
+
def initialize(opf, nav)
|
58
|
+
@opf = opf
|
59
|
+
@nav = nav
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [String]
|
63
|
+
#
|
64
|
+
def generate_bookspec
|
65
|
+
@indent = 0
|
66
|
+
@bookspec = []
|
67
|
+
|
68
|
+
add_code('Epuber::Book.new do |book|', after: 'end') do
|
69
|
+
generate_titles
|
70
|
+
generate_authors
|
71
|
+
add_empty_line
|
72
|
+
generate_id
|
73
|
+
generate_language
|
74
|
+
generate_published
|
75
|
+
generate_publisher
|
76
|
+
add_empty_line
|
77
|
+
generate_cover
|
78
|
+
add_empty_line
|
79
|
+
generate_toc
|
80
|
+
end
|
81
|
+
add_empty_line
|
82
|
+
|
83
|
+
@bookspec.join("\n")
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [void]
|
87
|
+
#
|
88
|
+
def generate_titles
|
89
|
+
titles = @opf.metadata.css('title')
|
90
|
+
titles.each do |title|
|
91
|
+
is_main = titles.count == 1
|
92
|
+
|
93
|
+
id = title['id']
|
94
|
+
is_main = @opf.find_refines(id, 'title-type') == 'main' if id && !is_main
|
95
|
+
|
96
|
+
add_comment('alternate title found from original EPUB file (Epuber supports only one title)') unless is_main
|
97
|
+
add_setting_property(:title, title.text.inspect, commented: !is_main)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [void]
|
102
|
+
#
|
103
|
+
def generate_authors
|
104
|
+
authors = @opf.metadata.css('creator')
|
105
|
+
if authors.empty?
|
106
|
+
add_setting_property(:author, nil)
|
107
|
+
elsif authors.count == 1
|
108
|
+
add_setting_property(:author, format_author(authors.first))
|
109
|
+
else
|
110
|
+
add_setting_property(:authors, authors.map { |auth| format_author(auth) })
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return [String]
|
115
|
+
#
|
116
|
+
def format_author(author_node)
|
117
|
+
name = author_node.text.strip
|
118
|
+
id = author_node['id']
|
119
|
+
|
120
|
+
if id
|
121
|
+
role = @opf.find_refines(id, 'role')
|
122
|
+
file_as = @opf.find_refines(id, 'file-as')
|
123
|
+
end
|
124
|
+
|
125
|
+
role ||= author_node['opf:role']
|
126
|
+
file_as ||= author_node['opf:file-as']
|
127
|
+
|
128
|
+
role_is_default = role.nil? || role == 'aut'
|
129
|
+
file_as_is_default = file_as.nil? || contributor_file_as_eq?(Book::Contributor.from_obj(name).file_as, file_as)
|
130
|
+
|
131
|
+
if role_is_default && file_as_is_default
|
132
|
+
name.inspect
|
133
|
+
elsif role_is_default && !file_as_is_default
|
134
|
+
%({ pretty_name: #{name.inspect}, file_as: #{file_as.inspect} })
|
135
|
+
elsif !role_is_default && file_as_is_default
|
136
|
+
%({ name: #{name.inspect}, role: #{role.inspect} })
|
137
|
+
else
|
138
|
+
%({ pretty_name: #{name.inspect}, file_as: #{file_as.inspect}, role: #{role.inspect} })
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [void]
|
143
|
+
#
|
144
|
+
def generate_id
|
145
|
+
nodes = @opf.metadata.css('identifier')
|
146
|
+
|
147
|
+
nodes.each do |id_node|
|
148
|
+
value = id_node.text.strip
|
149
|
+
|
150
|
+
is_main = @opf.package['unique-identifier'] == id_node['id']
|
151
|
+
is_isbn = value.start_with?('urn:isbn:')
|
152
|
+
value = value.sub(/^urn:isbn:/, '').strip if is_isbn
|
153
|
+
key = is_isbn ? :isbn : :identifier
|
154
|
+
|
155
|
+
if is_main
|
156
|
+
add_setting_property(key, value.inspect)
|
157
|
+
else
|
158
|
+
add_comment('alternate identifier found from original EPUB file (Epuber supports only one identifier)')
|
159
|
+
add_setting_property(key, value.inspect, commented: true)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# @return [void]
|
165
|
+
#
|
166
|
+
def generate_language
|
167
|
+
language = @opf.metadata.at_css('language')
|
168
|
+
add_setting_property(:language, language.text.strip.inspect) if language
|
169
|
+
end
|
170
|
+
|
171
|
+
# @return [void]
|
172
|
+
#
|
173
|
+
def generate_published
|
174
|
+
published = @opf.metadata.at_css('date')
|
175
|
+
add_setting_property(:published, published.text.strip.inspect) if published
|
176
|
+
end
|
177
|
+
|
178
|
+
# @return [void]
|
179
|
+
#
|
180
|
+
def generate_publisher
|
181
|
+
publisher = @opf.metadata.at_css('publisher')
|
182
|
+
add_setting_property(:publisher, publisher.text.strip.inspect) if publisher
|
183
|
+
end
|
184
|
+
|
185
|
+
# @return [void]
|
186
|
+
#
|
187
|
+
def generate_cover
|
188
|
+
cover_property = Compiler::OPFGenerator::PROPERTIES_MAP[:cover_image]
|
189
|
+
|
190
|
+
cover_id = @opf.manifest_items.find { |_, item| item.properties&.include?(cover_property) }&.last&.id
|
191
|
+
cover_id ||= @opf.metadata.at_css('meta[name="cover"]')&.[]('content')
|
192
|
+
cover = @opf.manifest_file_by_id(cover_id) if cover_id
|
193
|
+
return unless cover
|
194
|
+
|
195
|
+
href = cover.href.sub(/#{Regexp.escape(File.extname(cover.href))}$/, '')
|
196
|
+
add_setting_property(:cover_image, href.inspect)
|
197
|
+
end
|
198
|
+
|
199
|
+
# @return [void]
|
200
|
+
#
|
201
|
+
def generate_toc
|
202
|
+
items = calculate_toc_items
|
203
|
+
|
204
|
+
render_toc_item = lambda do |item|
|
205
|
+
if item.children.empty?
|
206
|
+
add_code(%(toc.file #{item.attribs}))
|
207
|
+
else
|
208
|
+
add_code(%(toc.file #{item.attribs} do), after: 'end') do
|
209
|
+
item.children.each do |child|
|
210
|
+
render_toc_item.call(child)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
add_code('book.toc do |toc, target|', after: 'end') do
|
217
|
+
items.each do |toc_item|
|
218
|
+
render_toc_item.call(toc_item)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
# Add code to final file. When block is given, it will be indented.
|
226
|
+
#
|
227
|
+
# @param [String] code code to print into final file
|
228
|
+
# @param [Boolean] commented should be code commented?
|
229
|
+
# @param [String, nil] after code to print after this code
|
230
|
+
#
|
231
|
+
# @return [void]
|
232
|
+
#
|
233
|
+
def add_code(code, commented: false, after: nil)
|
234
|
+
indent_str = ' ' * @indent
|
235
|
+
comment_prefix = commented ? '# ' : ''
|
236
|
+
|
237
|
+
@bookspec << %(#{indent_str}#{comment_prefix}#{code})
|
238
|
+
|
239
|
+
if block_given?
|
240
|
+
increase_indent
|
241
|
+
yield
|
242
|
+
decrease_indent
|
243
|
+
end
|
244
|
+
|
245
|
+
add_code(after, commented: commented) if after
|
246
|
+
end
|
247
|
+
|
248
|
+
def add_setting_property(name, value, commented: false)
|
249
|
+
if value.is_a?(Array)
|
250
|
+
add_code(%(book.#{name} = [), commented: commented, after: ']') do
|
251
|
+
value.each do |v|
|
252
|
+
add_code(%(#{v},), commented: commented)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
else
|
256
|
+
add_code(%(book.#{name} = #{value}), commented: commented)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def add_comment(text)
|
261
|
+
add_code(text, commented: true)
|
262
|
+
end
|
263
|
+
|
264
|
+
def add_empty_line
|
265
|
+
return if @bookspec.last == ''
|
266
|
+
|
267
|
+
@bookspec << ''
|
268
|
+
end
|
269
|
+
|
270
|
+
def increase_indent
|
271
|
+
@indent += 2
|
272
|
+
end
|
273
|
+
|
274
|
+
def decrease_indent
|
275
|
+
@indent -= 2
|
276
|
+
@indent = 0 if @indent.negative?
|
277
|
+
end
|
278
|
+
|
279
|
+
# Compares two contributors by file_as, it will return true if file_as is same even when case is different
|
280
|
+
#
|
281
|
+
# @param [String] file_as_a
|
282
|
+
# @param [String] file_as_b
|
283
|
+
#
|
284
|
+
# @return [Boolean]
|
285
|
+
#
|
286
|
+
def contributor_file_as_eq?(file_as_a, file_as_b)
|
287
|
+
file_as_a == file_as_b || file_as_a.mb_chars.downcase == file_as_b.mb_chars.downcase
|
288
|
+
end
|
289
|
+
|
290
|
+
# @param [String] href
|
291
|
+
#
|
292
|
+
# @return [Array<Symbol>]
|
293
|
+
#
|
294
|
+
def landmark_for_href(href)
|
295
|
+
landmarks = @nav&.landmarks
|
296
|
+
landmark_map = NavFile::LANDMARKS_MAP unless landmarks.nil?
|
297
|
+
|
298
|
+
if landmarks.nil?
|
299
|
+
landmarks = @opf.guide_items
|
300
|
+
landmark_map = OpfFile::LANDMARKS_MAP
|
301
|
+
end
|
302
|
+
|
303
|
+
found = landmarks.select { |l| l.href == href }
|
304
|
+
.map(&:type)
|
305
|
+
.compact
|
306
|
+
.map { |t| landmark_map[t] }
|
307
|
+
.compact
|
308
|
+
|
309
|
+
return found unless found.empty?
|
310
|
+
|
311
|
+
# try to find by href without fragment
|
312
|
+
if href.include?('#')
|
313
|
+
href = href.split('#').first
|
314
|
+
return landmark_for_href(href)
|
315
|
+
end
|
316
|
+
|
317
|
+
[]
|
318
|
+
end
|
319
|
+
|
320
|
+
# @return [Array<Epuber::BookspecGenerator::TocItem>]
|
321
|
+
#
|
322
|
+
def calculate_toc_items
|
323
|
+
spine_items = @opf.spine_items
|
324
|
+
idrefs = spine_items.map(&:idref)
|
325
|
+
landmarks = Set.new
|
326
|
+
|
327
|
+
# @param [ManifestItem, nil] manifest_item
|
328
|
+
# @param [NavItem, nil] toc_item
|
329
|
+
#
|
330
|
+
# @return [Array<Epuber::BookspecGenerator::TocItem>]
|
331
|
+
#
|
332
|
+
render_toc_item = lambda do |manifest_item, toc_item|
|
333
|
+
# ignore this item when it was already rendered
|
334
|
+
next nil if manifest_item && !idrefs.include?(manifest_item.id)
|
335
|
+
|
336
|
+
manifest_item ||= @opf.manifest_file_by_href(toc_item.href)
|
337
|
+
|
338
|
+
href = toc_item&.href || manifest_item.href
|
339
|
+
toc_item ||= @nav&.find_by_href(href) || @nav&.find_by_href(href, ignore_fragment: true)
|
340
|
+
href = toc_item&.href || manifest_item.href
|
341
|
+
|
342
|
+
href_output = href.sub(/\.x?html$/, '')
|
343
|
+
.sub(/\.x?html#/, '#')
|
344
|
+
|
345
|
+
landmarks_for_this = landmark_for_href(href)
|
346
|
+
unless landmarks_for_this.empty?
|
347
|
+
diff = Set.new(landmarks_for_this) - landmarks
|
348
|
+
landmarks += diff
|
349
|
+
|
350
|
+
landmarks_for_this = diff.to_a
|
351
|
+
end
|
352
|
+
|
353
|
+
item = TocItem.new(href_output, toc_item&.title, landmarks_for_this)
|
354
|
+
item.children = toc_item&.children&.map do |child|
|
355
|
+
render_toc_item.call(nil, child)
|
356
|
+
end || []
|
357
|
+
|
358
|
+
idrefs.delete(manifest_item.id) if manifest_item
|
359
|
+
|
360
|
+
item
|
361
|
+
end
|
362
|
+
|
363
|
+
spine_items.map do |itemref|
|
364
|
+
idref = itemref.idref
|
365
|
+
next unless idref
|
366
|
+
|
367
|
+
render_toc_item.call(@opf.manifest_file_by_id(idref), nil)
|
368
|
+
end.compact
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|