epuber 0.7.4 → 0.8.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/Gemfile +1 -2
- data/README.md +2 -1
- data/epuber.gemspec +10 -12
- data/lib/epuber/book/contributor.rb +0 -1
- data/lib/epuber/book/file_request.rb +1 -1
- data/lib/epuber/book/target.rb +20 -23
- data/lib/epuber/book/toc_item.rb +2 -4
- data/lib/epuber/book.rb +19 -19
- data/lib/epuber/checker/bookspec_checker.rb +26 -0
- data/lib/epuber/checker/text_checker.rb +2 -1
- data/lib/epuber/checker.rb +16 -2
- data/lib/epuber/checker_transformer_base.rb +2 -5
- data/lib/epuber/command/build.rb +34 -24
- data/lib/epuber/command/init.rb +23 -23
- data/lib/epuber/command/server.rb +2 -2
- data/lib/epuber/command.rb +17 -20
- data/lib/epuber/compiler/compilation_context.rb +10 -8
- data/lib/epuber/compiler/file_database.rb +0 -2
- data/lib/epuber/compiler/file_finders/abstract.rb +33 -23
- data/lib/epuber/compiler/file_finders/imaginary.rb +40 -35
- data/lib/epuber/compiler/file_resolver.rb +77 -88
- data/lib/epuber/compiler/file_stat.rb +4 -4
- data/lib/epuber/compiler/file_types/abstract_file.rb +3 -4
- data/lib/epuber/compiler/file_types/bade_file.rb +12 -7
- data/lib/epuber/compiler/file_types/coffee_script_file.rb +1 -1
- data/lib/epuber/compiler/file_types/generated_file.rb +1 -1
- data/lib/epuber/compiler/file_types/image_file.rb +4 -2
- data/lib/epuber/compiler/file_types/nav_file.rb +0 -1
- data/lib/epuber/compiler/file_types/opf_file.rb +0 -1
- data/lib/epuber/compiler/file_types/source_file.rb +8 -3
- data/lib/epuber/compiler/file_types/xhtml_file.rb +67 -13
- data/lib/epuber/compiler/generator.rb +1 -2
- data/lib/epuber/compiler/meta_inf_generator.rb +1 -1
- data/lib/epuber/compiler/nav_generator.rb +5 -6
- data/lib/epuber/compiler/opf_generator.rb +22 -23
- data/lib/epuber/compiler/problem.rb +12 -21
- data/lib/epuber/compiler/xhtml_processor.rb +61 -31
- data/lib/epuber/compiler.rb +66 -19
- data/lib/epuber/config.rb +13 -7
- data/lib/epuber/dsl/attribute.rb +16 -17
- data/lib/epuber/dsl/attribute_support.rb +3 -3
- data/lib/epuber/dsl/object.rb +17 -15
- data/lib/epuber/dsl/tree_object.rb +2 -3
- data/lib/epuber/epubcheck.rb +15 -0
- data/lib/epuber/helper.rb +0 -1
- data/lib/epuber/lockfile.rb +7 -9
- data/lib/epuber/plugin.rb +1 -2
- data/lib/epuber/ruby_extensions/match_data.rb +1 -1
- data/lib/epuber/ruby_extensions/thread.rb +1 -0
- data/lib/epuber/server/base.styl +0 -1
- data/lib/epuber/server/basic.styl +1 -30
- data/lib/epuber/server/handlers.rb +1 -1
- data/lib/epuber/server.rb +67 -66
- data/lib/epuber/third_party/bower.rb +5 -5
- data/lib/epuber/transformer/text_transformer.rb +4 -2
- data/lib/epuber/transformer.rb +2 -2
- data/lib/epuber/user_interface.rb +49 -38
- data/lib/epuber/vendor/hash_binding.rb +9 -2
- data/lib/epuber/vendor/ruby_templater.rb +1 -5
- data/lib/epuber/vendor/version.rb +10 -10
- data/lib/epuber/version.rb +1 -1
- metadata +67 -69
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Bold.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-BoldItalic.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Italic.ttf +0 -0
- data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Regular.ttf +0 -0
@@ -25,7 +25,7 @@ module Epuber
|
|
25
25
|
class FileResolver
|
26
26
|
class ResolveError < StandardError; end
|
27
27
|
|
28
|
-
PATH_TYPES = [:spine, :manifest, :package, nil]
|
28
|
+
PATH_TYPES = [:spine, :manifest, :package, nil].freeze
|
29
29
|
|
30
30
|
# @return [String] path where should look for source files
|
31
31
|
#
|
@@ -125,24 +125,16 @@ module Epuber
|
|
125
125
|
existing_file = @final_destination_path_to_file[file.final_destination_path]
|
126
126
|
|
127
127
|
# save mapping from file_request to file, file_request can be different, but result file could be the same ...
|
128
|
-
unless file.try(:file_request).nil?
|
129
|
-
@request_to_files[file.file_request] << (existing_file || file)
|
130
|
-
end
|
128
|
+
@request_to_files[file.file_request] << (existing_file || file) unless file.try(:file_request).nil?
|
131
129
|
|
132
130
|
# return existing file if already exists, new file will be thrown away
|
133
131
|
return existing_file unless existing_file.nil?
|
134
132
|
|
135
|
-
if [:spine].include?(type)
|
136
|
-
@spine_files << file
|
137
|
-
end
|
133
|
+
@spine_files << file if [:spine].include?(type)
|
138
134
|
|
139
|
-
if [
|
140
|
-
@manifest_files << file
|
141
|
-
end
|
135
|
+
@manifest_files << file if %i[spine manifest].include?(type)
|
142
136
|
|
143
|
-
if [
|
144
|
-
@package_files << file
|
145
|
-
end
|
137
|
+
@package_files << file if %i[spine manifest package].include?(type)
|
146
138
|
|
147
139
|
@files << file
|
148
140
|
|
@@ -151,13 +143,11 @@ module Epuber
|
|
151
143
|
|
152
144
|
@final_destination_path_to_file[file.final_destination_path] = file
|
153
145
|
|
154
|
-
if file.respond_to?(:source_path) && !file.source_path.nil?
|
155
|
-
@source_path_to_file[file.source_path] = file
|
156
|
-
end
|
146
|
+
@source_path_to_file[file.source_path] = file if file.respond_to?(:source_path) && !file.source_path.nil?
|
157
147
|
|
158
|
-
|
159
|
-
|
160
|
-
|
148
|
+
return unless file.respond_to?(:abs_source_path) && !file.abs_source_path.nil?
|
149
|
+
|
150
|
+
@abs_source_path_to_file[file.abs_source_path] = file
|
161
151
|
end
|
162
152
|
|
163
153
|
# Get instance of file from request instance
|
@@ -184,7 +174,7 @@ module Epuber
|
|
184
174
|
end
|
185
175
|
|
186
176
|
if file_request.only_one
|
187
|
-
files.first
|
177
|
+
files.first # @request_to_files always returns array, see #initialize method
|
188
178
|
else
|
189
179
|
files
|
190
180
|
end
|
@@ -219,99 +209,98 @@ module Epuber
|
|
219
209
|
# @return [Array<String>] list of files that should be deleted in destination directory
|
220
210
|
#
|
221
211
|
def unneeded_files_in_destination
|
222
|
-
requested_paths = files.map
|
223
|
-
file.pkg_destination_path
|
224
|
-
end
|
212
|
+
requested_paths = files.map(&:pkg_destination_path)
|
225
213
|
|
226
214
|
existing_paths = FileFinders::Normal.new(destination_path).find_all('*')
|
227
215
|
|
228
216
|
unnecessary_paths = existing_paths - requested_paths
|
229
217
|
|
230
|
-
unnecessary_paths.
|
231
|
-
|
218
|
+
unnecessary_paths.reject! do |path|
|
219
|
+
::File.directory?(File.join(destination_path, path))
|
232
220
|
end
|
233
221
|
|
234
222
|
unnecessary_paths
|
235
223
|
end
|
236
224
|
|
237
|
-
|
238
225
|
##################################################################################################################
|
239
226
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
# @param file [Epuber::Compiler::AbstractFile]
|
258
|
-
#
|
259
|
-
# @return [nil]
|
260
|
-
#
|
261
|
-
def resolve_destination_path(file)
|
262
|
-
if file.final_destination_path.nil?
|
263
|
-
dest_path = if file.respond_to?(:source_path) && !file.source_path.nil?
|
264
|
-
file.abs_source_path = File.expand_path(file.source_path, source_path)
|
265
|
-
self.class.renamed_file_with_path(file.source_path)
|
266
|
-
elsif !file.destination_path.nil?
|
267
|
-
file.destination_path
|
268
|
-
else
|
269
|
-
raise ResolveError, "What should I do with file that doesn't have source path or destination path? file: #{file.inspect}"
|
270
|
-
end
|
271
|
-
|
272
|
-
file.destination_path = dest_path
|
273
|
-
file.pkg_destination_path = File.join(*self.class.path_comps_for(file.path_type), dest_path)
|
274
|
-
file.final_destination_path = File.join(destination_path, file.pkg_destination_path)
|
227
|
+
class << self
|
228
|
+
# @param [String] path path to some file
|
229
|
+
#
|
230
|
+
# @return [String] path with changed extension
|
231
|
+
#
|
232
|
+
def renamed_file_with_path(path)
|
233
|
+
extname = File.extname(path)
|
234
|
+
new_extname = FileFinders::EXTENSIONS_RENAME[extname]
|
235
|
+
|
236
|
+
if new_extname.nil?
|
237
|
+
path
|
238
|
+
else
|
239
|
+
path.sub(/#{Regexp.escape(extname)}$/, new_extname)
|
240
|
+
end
|
275
241
|
end
|
276
|
-
end
|
277
242
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
243
|
+
# @param [String] extname extension of file
|
244
|
+
#
|
245
|
+
# @return [Class]
|
246
|
+
#
|
247
|
+
def file_class_for(extname)
|
248
|
+
mapping = {
|
249
|
+
'.styl' => FileTypes::StylusFile,
|
285
250
|
|
286
|
-
|
251
|
+
'.coffee' => FileTypes::CoffeeScriptFile,
|
287
252
|
|
288
|
-
|
289
|
-
|
290
|
-
|
253
|
+
'.bade' => FileTypes::BadeFile,
|
254
|
+
'.xhtml' => FileTypes::XHTMLFile,
|
255
|
+
'.html' => FileTypes::XHTMLFile,
|
291
256
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
257
|
+
'.jpg' => FileTypes::ImageFile,
|
258
|
+
'.jpeg' => FileTypes::ImageFile,
|
259
|
+
'.png' => FileTypes::ImageFile,
|
260
|
+
}
|
296
261
|
|
297
|
-
|
298
|
-
|
262
|
+
mapping[extname] || FileTypes::StaticFile
|
263
|
+
end
|
299
264
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
265
|
+
# @param [String] root_path path to root of the package
|
266
|
+
# @param [Symbol] path_type path type of file
|
267
|
+
#
|
268
|
+
# @return [Array<String>] path components
|
269
|
+
#
|
270
|
+
def path_comps_for(root_path, path_type)
|
271
|
+
case path_type
|
307
272
|
when :spine, :manifest
|
308
273
|
Array(root_path) + [Compiler::EPUB_CONTENT_FOLDER]
|
309
274
|
when :package
|
310
275
|
Array(root_path)
|
311
|
-
|
312
|
-
nil
|
276
|
+
end
|
313
277
|
end
|
314
278
|
end
|
279
|
+
|
280
|
+
private
|
281
|
+
|
282
|
+
# @param file [Epuber::Compiler::AbstractFile]
|
283
|
+
#
|
284
|
+
# @return [nil]
|
285
|
+
#
|
286
|
+
def resolve_destination_path(file)
|
287
|
+
return unless file.final_destination_path.nil?
|
288
|
+
|
289
|
+
dest_path = if file.respond_to?(:source_path) && !file.source_path.nil?
|
290
|
+
file.abs_source_path = File.expand_path(file.source_path, source_path)
|
291
|
+
self.class.renamed_file_with_path(file.source_path)
|
292
|
+
elsif !file.destination_path.nil?
|
293
|
+
file.destination_path
|
294
|
+
else
|
295
|
+
raise ResolveError, <<~ERROR
|
296
|
+
What should I do with file that doesn't have source path or destination path? file: #{file.inspect}
|
297
|
+
ERROR
|
298
|
+
end
|
299
|
+
|
300
|
+
file.destination_path = dest_path
|
301
|
+
file.pkg_destination_path = File.join(*self.class.path_comps_for(nil, file.path_type), dest_path)
|
302
|
+
file.final_destination_path = File.join(destination_path, file.pkg_destination_path)
|
303
|
+
end
|
315
304
|
end
|
316
305
|
end
|
317
306
|
end
|
@@ -36,7 +36,7 @@ module Epuber
|
|
36
36
|
@mtime = stat.mtime
|
37
37
|
@ctime = stat.ctime
|
38
38
|
@size = stat.size
|
39
|
-
rescue
|
39
|
+
rescue StandardError
|
40
40
|
# noop
|
41
41
|
end
|
42
42
|
end
|
@@ -66,9 +66,9 @@ module Epuber
|
|
66
66
|
raise AttributeError, "other must be class of #{self.class}" unless other.is_a?(FileStat)
|
67
67
|
|
68
68
|
file_path == other.file_path &&
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
size == other.size &&
|
70
|
+
mtime == other.mtime &&
|
71
|
+
ctime == other.ctime
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
@@ -4,18 +4,18 @@ module Epuber
|
|
4
4
|
class Compiler
|
5
5
|
module FileTypes
|
6
6
|
class AbstractFile
|
7
|
-
|
8
7
|
# @return [String] relative destination path
|
9
8
|
#
|
10
9
|
attr_accessor :destination_path
|
11
10
|
|
12
|
-
# @return [Symbol] group of this file (:text, :image, :font, ...), see
|
11
|
+
# @return [Symbol] group of this file (:text, :image, :font, ...), see
|
12
|
+
# Epuber::Compiler::FileFinder::GROUP_EXTENSIONS
|
13
13
|
#
|
14
14
|
attr_accessor :group
|
15
15
|
|
16
16
|
# @return [Set<Symbol>] list of properties
|
17
17
|
#
|
18
|
-
|
18
|
+
attr_writer :properties
|
19
19
|
|
20
20
|
# @return [Set<Symbol>] list of properties
|
21
21
|
#
|
@@ -23,7 +23,6 @@ module Epuber
|
|
23
23
|
@properties ||= Set.new
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
26
|
# @return [String] final relative destination path from root of the package calculated by FileResolver
|
28
27
|
#
|
29
28
|
attr_accessor :pkg_destination_path
|
@@ -26,10 +26,15 @@ module Epuber
|
|
26
26
|
__file_resolver: file_resolver,
|
27
27
|
__file: self,
|
28
28
|
__toc_item: toc_item,
|
29
|
-
__const: Hash.new
|
29
|
+
__const: Hash.new do |_hash, key|
|
30
|
+
UI.warning("Undefined constant with key `#{key}`", location: caller_locations[0])
|
31
|
+
end.merge!(target.constants),
|
30
32
|
}
|
31
33
|
|
32
|
-
should_load_from_precompiled = up_to_date &&
|
34
|
+
should_load_from_precompiled = up_to_date &&
|
35
|
+
precompiled_exists &&
|
36
|
+
compilation_context.incremental_build? &&
|
37
|
+
!compilation_context.should_write
|
33
38
|
|
34
39
|
precompiled = if should_load_from_precompiled
|
35
40
|
begin
|
@@ -49,7 +54,9 @@ module Epuber
|
|
49
54
|
renderer.render(new_line: '', indent: '')
|
50
55
|
end
|
51
56
|
else
|
52
|
-
|
57
|
+
if compilation_context.incremental_build?
|
58
|
+
UI.print_processing_debug_info('Parsing new version of source file')
|
59
|
+
end
|
53
60
|
|
54
61
|
bade_content = load_source(compilation_context)
|
55
62
|
|
@@ -58,9 +65,7 @@ module Epuber
|
|
58
65
|
.with_locals(variables)
|
59
66
|
|
60
67
|
# turn on optimizations when can
|
61
|
-
if renderer.respond_to?(:optimize=)
|
62
|
-
renderer.optimize = true
|
63
|
-
end
|
68
|
+
renderer.optimize = true if renderer.respond_to?(:optimize=)
|
64
69
|
|
65
70
|
FileUtils.mkdir_p(File.dirname(precompiled_path))
|
66
71
|
renderer.precompiled.write_yaml_to_file(precompiled_path)
|
@@ -82,7 +87,7 @@ module Epuber
|
|
82
87
|
# @return [String]
|
83
88
|
#
|
84
89
|
def precompiled_path
|
85
|
-
File.join(Config.instance.build_cache_path(PRECOMPILED_CACHE_NAME), source_path
|
90
|
+
File.join(Config.instance.build_cache_path(PRECOMPILED_CACHE_NAME), "#{source_path}.precompiled.yml")
|
86
91
|
end
|
87
92
|
|
88
93
|
def pretty_precompiled_path
|
@@ -10,7 +10,7 @@ module Epuber
|
|
10
10
|
class CoffeeScriptFile < SourceFile
|
11
11
|
# @param [Compiler::CompilationContext] compilation_context
|
12
12
|
#
|
13
|
-
def process(
|
13
|
+
def process(_compilation_context)
|
14
14
|
return if destination_file_up_to_date?
|
15
15
|
|
16
16
|
write_compiled(CoffeeScript.compile(File.new(abs_source_path)))
|
@@ -16,14 +16,16 @@ module Epuber
|
|
16
16
|
dest = final_destination_path
|
17
17
|
source = abs_source_path
|
18
18
|
|
19
|
-
img = Magick::Image
|
19
|
+
img = Magick::Image.read(source).first
|
20
20
|
|
21
21
|
resolution = img.columns * img.rows
|
22
22
|
max_resolution = 3_000_000
|
23
23
|
|
24
24
|
if resolution > max_resolution
|
25
25
|
img = img.change_geometry("#{max_resolution}@>") do |width, height, b_img|
|
26
|
-
UI.print_processing_debug_info(
|
26
|
+
UI.print_processing_debug_info(<<~MSG)
|
27
|
+
downscaling from resolution #{b_img.columns}x#{b_img.rows} to #{width}x#{height}
|
28
|
+
MSG
|
27
29
|
b_img.resize!(width, height)
|
28
30
|
end
|
29
31
|
|
@@ -6,7 +6,6 @@ module Epuber
|
|
6
6
|
require_relative 'abstract_file'
|
7
7
|
|
8
8
|
class SourceFile < AbstractFile
|
9
|
-
|
10
9
|
# @return [String] relative source path
|
11
10
|
#
|
12
11
|
attr_reader :source_path
|
@@ -22,6 +21,8 @@ module Epuber
|
|
22
21
|
# @param [String] source_path relative path from project root to source file
|
23
22
|
#
|
24
23
|
def initialize(source_path)
|
24
|
+
super()
|
25
|
+
|
25
26
|
@source_path = source_path
|
26
27
|
end
|
27
28
|
|
@@ -95,7 +96,9 @@ module Epuber
|
|
95
96
|
UI.print_processing_debug_info("Writing compiled version to #{pkg_destination_path}")
|
96
97
|
self.class.write_to_file!(content, final_destination_path)
|
97
98
|
else
|
98
|
-
UI.print_processing_debug_info(
|
99
|
+
UI.print_processing_debug_info(<<~MSG)
|
100
|
+
Not writing to disk ... compiled version at #{pkg_destination_path} is same
|
101
|
+
MSG
|
99
102
|
end
|
100
103
|
end
|
101
104
|
|
@@ -104,7 +107,9 @@ module Epuber
|
|
104
107
|
UI.print_processing_debug_info("Writing processed version to #{pkg_destination_path}")
|
105
108
|
self.class.write_to_file!(content, final_destination_path)
|
106
109
|
else
|
107
|
-
UI.print_processing_debug_info(
|
110
|
+
UI.print_processing_debug_info(<<~MSG)
|
111
|
+
Not writing to disk ... processed version at #{pkg_destination_path} is same
|
112
|
+
MSG
|
108
113
|
end
|
109
114
|
end
|
110
115
|
end
|
@@ -12,6 +12,21 @@ module Epuber
|
|
12
12
|
#
|
13
13
|
attr_accessor :toc_item
|
14
14
|
|
15
|
+
# @return [Array<String>]
|
16
|
+
#
|
17
|
+
attr_accessor :global_ids
|
18
|
+
|
19
|
+
# @return [Array<String>]
|
20
|
+
#
|
21
|
+
attr_accessor :global_links
|
22
|
+
|
23
|
+
def initialize(source_path)
|
24
|
+
super
|
25
|
+
|
26
|
+
self.global_ids = []
|
27
|
+
self.global_links = []
|
28
|
+
end
|
29
|
+
|
15
30
|
# @param [Book::Target] target
|
16
31
|
# @param [FileResolver] file_resolver
|
17
32
|
#
|
@@ -22,8 +37,9 @@ module Epuber
|
|
22
37
|
Array(file_resolver.file_from_request(default_style_request))
|
23
38
|
end.flatten
|
24
39
|
|
40
|
+
dirname = Pathname.new(File.dirname(final_destination_path))
|
25
41
|
default_styles.map do |style|
|
26
|
-
Pathname.new(style.final_destination_path).relative_path_from(
|
42
|
+
Pathname.new(style.final_destination_path).relative_path_from(dirname).to_s
|
27
43
|
end
|
28
44
|
end
|
29
45
|
|
@@ -37,8 +53,9 @@ module Epuber
|
|
37
53
|
Array(file_resolver.file_from_request(default_style_request))
|
38
54
|
end.flatten
|
39
55
|
|
56
|
+
dirname = Pathname.new(File.dirname(final_destination_path))
|
40
57
|
default_scripts.map do |style|
|
41
|
-
Pathname.new(style.final_destination_path).relative_path_from(
|
58
|
+
Pathname.new(style.final_destination_path).relative_path_from(dirname).to_s
|
42
59
|
end
|
43
60
|
end
|
44
61
|
|
@@ -58,10 +75,7 @@ module Epuber
|
|
58
75
|
end
|
59
76
|
end
|
60
77
|
|
61
|
-
|
62
|
-
if compilation_context.should_write
|
63
|
-
self.class.write_to_file(xhtml_content, abs_source_path)
|
64
|
-
end
|
78
|
+
self.class.write_to_file(xhtml_content, abs_source_path) if compilation_context.should_write
|
65
79
|
|
66
80
|
xhtml_content
|
67
81
|
end
|
@@ -88,9 +102,7 @@ module Epuber
|
|
88
102
|
XHTMLProcessor.xml_doc_from_str_with_errors(content, source_path)
|
89
103
|
end
|
90
104
|
|
91
|
-
if compilation_context.release_build && xhtml_doc.errors.count
|
92
|
-
process_nokogiri_errors(errors)
|
93
|
-
end
|
105
|
+
process_nokogiri_errors(errors) if compilation_context.release_build && xhtml_doc.errors.count.positive?
|
94
106
|
|
95
107
|
UI.print_step_processing_time('adding missing elements') do
|
96
108
|
XHTMLProcessor.add_missing_root_elements(xhtml_doc, book.title, target.epub_version)
|
@@ -120,13 +132,13 @@ module Epuber
|
|
120
132
|
XHTMLProcessor.resolve_mathml_namespace(xhtml_doc)
|
121
133
|
|
122
134
|
UI.print_step_processing_time('investigating properties') do
|
123
|
-
|
124
|
-
|
125
|
-
|
135
|
+
properties << :remote_resources if XHTMLProcessor.using_remote_resources?(xhtml_doc)
|
136
|
+
properties << :scripted if XHTMLProcessor.using_javascript?(xhtml_doc)
|
137
|
+
properties << :mathml if XHTMLProcessor.using_mathml?(xhtml_doc)
|
126
138
|
end
|
127
139
|
|
128
140
|
xhtml_string = UI.print_step_processing_time('converting to XHTML') do
|
129
|
-
|
141
|
+
xhtml_doc.to_s
|
130
142
|
end
|
131
143
|
|
132
144
|
# perform transformations
|
@@ -145,6 +157,12 @@ module Epuber
|
|
145
157
|
end
|
146
158
|
end
|
147
159
|
|
160
|
+
if xhtml_string.include?('="$')
|
161
|
+
xhtml_doc = XHTMLProcessor.xml_document_from_string(xhtml_string, final_destination_path)
|
162
|
+
self.global_ids = XHTMLProcessor.find_global_ids(xhtml_doc)
|
163
|
+
self.global_links = XHTMLProcessor.find_global_links(xhtml_doc)
|
164
|
+
end
|
165
|
+
|
148
166
|
xhtml_string
|
149
167
|
end
|
150
168
|
|
@@ -153,6 +171,42 @@ module Epuber
|
|
153
171
|
def process(compilation_context)
|
154
172
|
write_processed(common_process(load_source(compilation_context), compilation_context))
|
155
173
|
end
|
174
|
+
|
175
|
+
# @param [Compiler::CompilationContext] compilation_context
|
176
|
+
# @param [Hash<String, XHTMLFile>] global_ids
|
177
|
+
#
|
178
|
+
def process_global_ids(compilation_context, global_ids)
|
179
|
+
return if self.global_ids.empty? && global_links.empty?
|
180
|
+
|
181
|
+
xhtml_doc = XHTMLProcessor.xml_document_from_string(File.read(final_destination_path), final_destination_path)
|
182
|
+
|
183
|
+
XHTMLProcessor.find_global_ids_nodes(xhtml_doc).each do |node|
|
184
|
+
id = node['id']
|
185
|
+
node['id'] = id[1..-1]
|
186
|
+
end
|
187
|
+
|
188
|
+
XHTMLProcessor.find_global_links_nodes(xhtml_doc).each do |node|
|
189
|
+
href = node['href'][1..-1]
|
190
|
+
|
191
|
+
dest_file = global_ids[href]
|
192
|
+
if dest_file
|
193
|
+
rel_path = Pathname(dest_file.final_destination_path.unicode_normalize)
|
194
|
+
.relative_path_from(Pathname(File.dirname(final_destination_path.unicode_normalize))).to_s
|
195
|
+
|
196
|
+
node['href'] = "#{rel_path}##{href}"
|
197
|
+
else
|
198
|
+
message = "Can't find global id '#{href}' from link in file #{source_path}"
|
199
|
+
location = UserInterface::Location.new(path: final_destination_path, lineno: node.line)
|
200
|
+
if compilation_context.release_build?
|
201
|
+
UI.error!(message, location: location)
|
202
|
+
else
|
203
|
+
UI.warning(message, location: location)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
write_processed(xhtml_doc.to_s)
|
209
|
+
end
|
156
210
|
end
|
157
211
|
end
|
158
212
|
end
|
@@ -12,7 +12,6 @@ module Nokogiri
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
15
|
module Epuber
|
17
16
|
class Compiler
|
18
17
|
class Generator
|
@@ -55,7 +54,7 @@ module Epuber
|
|
55
54
|
builder = Nokogiri::XML::Builder.new(encoding: 'utf-8') do |xml|
|
56
55
|
@xml = xml
|
57
56
|
|
58
|
-
block
|
57
|
+
block&.call(xml)
|
59
58
|
|
60
59
|
@xml = nil
|
61
60
|
end
|
@@ -15,7 +15,7 @@ module Epuber
|
|
15
15
|
generate_xml do |xml|
|
16
16
|
xml.container(version: 1.0, xmlns: 'urn:oasis:names:tc:opendocument:xmlns:container') do
|
17
17
|
xml.rootfiles do
|
18
|
-
@file_resolver.package_files.select { |file| file.
|
18
|
+
@file_resolver.package_files.select { |file| file.is_a?(FileTypes::OPFFile) }.each do |file|
|
19
19
|
path = file.pkg_destination_path
|
20
20
|
xml.rootfile('full-path' => path, 'media-type' => MIME::Types.of(path).first.content_type)
|
21
21
|
end
|
@@ -9,7 +9,6 @@ module Epuber
|
|
9
9
|
require_relative 'generator'
|
10
10
|
|
11
11
|
class NavGenerator < Generator
|
12
|
-
|
13
12
|
NCX_NAMESPACES = {
|
14
13
|
'xmlns' => 'http://www.daisy.org/z3986/2005/ncx/',
|
15
14
|
}.freeze
|
@@ -26,10 +25,10 @@ module Epuber
|
|
26
25
|
|
27
26
|
# resource page http://www.idpf.org/epub/301/spec/epub-contentdocs.html#sec-xhtml-nav-def-types-landmarks
|
28
27
|
LANDMARKS_MAP = {
|
29
|
-
landmark_cover:
|
30
|
-
landmark_start_page: { type: %w
|
31
|
-
landmark_copyright:
|
32
|
-
landmark_toc:
|
28
|
+
landmark_cover: { type: 'cover', text: 'Cover page' },
|
29
|
+
landmark_start_page: { type: %w[bodymatter ibooks:reader-start-page], text: 'Start Reading' },
|
30
|
+
landmark_copyright: { type: 'copyright-page', text: 'Copyright page' },
|
31
|
+
landmark_toc: { type: 'toc', text: 'Table of contents' },
|
33
32
|
}.freeze
|
34
33
|
|
35
34
|
# Generates XML for toc document, the structure differs depend on epub_version
|
@@ -121,7 +120,7 @@ module Epuber
|
|
121
120
|
end
|
122
121
|
end
|
123
122
|
|
124
|
-
if @target.epub_version >= 3 && toc_items.length
|
123
|
+
if @target.epub_version >= 3 && toc_items.length.positive? && contains_item_with_title(toc_items)
|
125
124
|
@xml.ol do
|
126
125
|
iterate_lambda.call
|
127
126
|
end
|