epuber 0.9.4 → 0.10.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/lib/epuber/checker/text_checker.rb +1 -2
- data/lib/epuber/checker.rb +3 -7
- data/lib/epuber/command/build.rb +43 -7
- data/lib/epuber/command/init.rb +5 -5
- data/lib/epuber/command/server.rb +1 -1
- data/lib/epuber/command.rb +24 -19
- data/lib/epuber/compiler/compilation_context.rb +8 -4
- data/lib/epuber/compiler/file_resolver.rb +1 -1
- data/lib/epuber/compiler/file_types/source_file.rb +2 -2
- data/lib/epuber/compiler/file_types/xhtml_file.rb +7 -15
- data/lib/epuber/compiler/xhtml_processor.rb +2 -2
- data/lib/epuber/compiler.rb +13 -10
- data/lib/epuber/config.rb +35 -14
- data/lib/epuber/epubcheck.rb +82 -2
- data/lib/epuber/from_file/from_file_executor.rb +9 -9
- data/lib/epuber/plugin.rb +1 -1
- data/lib/epuber/server.rb +5 -5
- data/lib/epuber/transformer/book_transformer.rb +30 -12
- data/lib/epuber/user_interface.rb +13 -218
- data/lib/epuber/utils/location.rb +14 -0
- data/lib/epuber/utils/logger/abstract_logger.rb +214 -0
- data/lib/epuber/utils/logger/console_logger.rb +122 -0
- data/lib/epuber/version.rb +1 -1
- metadata +5 -2
@@ -21,7 +21,7 @@ module Epuber
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def run
|
24
|
-
UI.
|
24
|
+
UI.info "📖 Loading EPUB file #{@filepath}"
|
25
25
|
|
26
26
|
Zip::File.open(@filepath) do |zip_file|
|
27
27
|
@zip_file = zip_file
|
@@ -29,22 +29,22 @@ module Epuber
|
|
29
29
|
validate_mimetype
|
30
30
|
|
31
31
|
@opf_path = content_opf_path
|
32
|
-
UI.
|
32
|
+
UI.info " Parsing OPF file at #{@opf_path}"
|
33
33
|
@opf = OpfFile.new(zip_file.read(@opf_path))
|
34
34
|
|
35
35
|
if zip_file.find_entry(ENCRYPTION_PATH)
|
36
|
-
UI.
|
36
|
+
UI.info ' Parsing encryption.xml file'
|
37
37
|
@encryption_handler = EncryptionHandler.new(zip_file.read(ENCRYPTION_PATH), @opf)
|
38
38
|
end
|
39
39
|
|
40
|
-
UI.
|
40
|
+
UI.info ' Generating bookspec file'
|
41
41
|
basename = File.basename(@filepath, File.extname(@filepath))
|
42
42
|
File.write("#{basename}.bookspec", generate_bookspec)
|
43
43
|
|
44
44
|
export_files
|
45
45
|
|
46
|
-
UI.
|
47
|
-
UI.
|
46
|
+
UI.info '' # empty line
|
47
|
+
UI.info <<~TEXT.rstrip.ansi.green
|
48
48
|
🎉 Project initialized.
|
49
49
|
Please review generated #{basename}.bookspec file and start using Epuber.
|
50
50
|
|
@@ -112,13 +112,13 @@ module Epuber
|
|
112
112
|
extension = File.extname(item.href).downcase
|
113
113
|
if text_file_extensions.include?(extension) &&
|
114
114
|
@opf.spine_items.none? { |spine_item| spine_item.idref == item.id }
|
115
|
-
UI.
|
115
|
+
UI.info " Skipping #{item.href} (not in spine)"
|
116
116
|
next
|
117
117
|
end
|
118
118
|
|
119
119
|
# ignore ncx file
|
120
120
|
if item.media_type == 'application/x-dtbncx+xml'
|
121
|
-
UI.
|
121
|
+
UI.info " Skipping #{item.href} (ncx file)"
|
122
122
|
next
|
123
123
|
end
|
124
124
|
|
@@ -127,7 +127,7 @@ module Epuber
|
|
127
127
|
.join(item.href)
|
128
128
|
.to_s
|
129
129
|
|
130
|
-
UI.
|
130
|
+
UI.info " Exporting #{item.href} (from #{full_path})"
|
131
131
|
|
132
132
|
contents = @zip_file.read(full_path)
|
133
133
|
contents = @encryption_handler.process_file(full_path, contents) if @encryption_handler
|
data/lib/epuber/plugin.rb
CHANGED
data/lib/epuber/server.rb
CHANGED
@@ -116,7 +116,7 @@ module Epuber
|
|
116
116
|
|
117
117
|
super() do |server|
|
118
118
|
$stderr = old_stderr
|
119
|
-
UI.
|
119
|
+
UI.info "Started development server on #{server.host}:#{server.port}"
|
120
120
|
|
121
121
|
host = if server.host == '0.0.0.0'
|
122
122
|
'localhost'
|
@@ -187,13 +187,13 @@ module Epuber
|
|
187
187
|
def self._log(level, message)
|
188
188
|
case level
|
189
189
|
when :ui
|
190
|
-
UI.
|
190
|
+
UI.info message
|
191
191
|
when :info
|
192
|
-
UI.
|
192
|
+
UI.info "INFO: #{message}" if verbose
|
193
193
|
when :get
|
194
|
-
UI.
|
194
|
+
UI.info " GET: #{message}" if verbose
|
195
195
|
when :ws
|
196
|
-
UI.
|
196
|
+
UI.info " WS: #{message}" if verbose
|
197
197
|
else
|
198
198
|
raise "Unknown log level #{level}"
|
199
199
|
end
|
@@ -29,21 +29,27 @@ module Epuber
|
|
29
29
|
# Find file in source or destination paths
|
30
30
|
#
|
31
31
|
# @param [String] pattern
|
32
|
+
# @param [String] context_path path to directory that is used as context for finding
|
33
|
+
# @param [Array<Symbol>, Symbol] groups
|
32
34
|
# @param [Thread::Backtrace::Location] location
|
33
35
|
#
|
34
36
|
# @return [Epuber::Compiler::FileTypes::AbstractFile, nil]
|
35
37
|
#
|
36
|
-
def find_file(pattern, location: caller_locations.first)
|
38
|
+
def find_file(pattern, context_path: nil, groups: nil, location: caller_locations.first)
|
37
39
|
return pattern if pattern.is_a?(Compiler::FileTypes::AbstractFile)
|
38
40
|
|
39
41
|
UI.error!("Pattern for finding file can't be nil", location: location) if pattern.nil?
|
40
42
|
|
41
43
|
begin
|
42
|
-
path = @compilation_context.file_resolver.source_finder.find_file(pattern
|
44
|
+
path = @compilation_context.file_resolver.source_finder.find_file(pattern, context_path: context_path,
|
45
|
+
groups: groups)
|
46
|
+
path = File.join(context_path, path) if context_path
|
43
47
|
@compilation_context.file_resolver.file_with_source_path(path)
|
44
48
|
rescue Compiler::FileFinders::FileNotFoundError
|
45
49
|
begin
|
46
|
-
path = @compilation_context.file_resolver.dest_finder.find_file(pattern
|
50
|
+
path = @compilation_context.file_resolver.dest_finder.find_file(pattern, context_path: context_path,
|
51
|
+
groups: groups)
|
52
|
+
path = File.join(context_path, path) if context_path
|
47
53
|
@compilation_context.file_resolver.file_with_destination_path(path)
|
48
54
|
rescue Compiler::FileFinders::FileNotFoundError
|
49
55
|
nil
|
@@ -54,27 +60,35 @@ module Epuber
|
|
54
60
|
# Find files destination paths
|
55
61
|
#
|
56
62
|
# @param [String] pattern
|
63
|
+
# @param [String] context_path path to directory that is used as context for finding
|
64
|
+
# @param [Array<Symbol>, Symbol] groups
|
57
65
|
# @param [Thread::Backtrace::Location] location
|
58
66
|
#
|
59
67
|
# @return [Array<Epuber::Compiler::FileTypes::AbstractFile>]
|
60
68
|
#
|
61
|
-
def find_destination_files(pattern, location: caller_locations.first)
|
69
|
+
def find_destination_files(pattern, context_path: nil, groups: nil, location: caller_locations.first)
|
62
70
|
UI.error!("Pattern for finding file can't be nil", location: location) if pattern.nil?
|
63
71
|
|
64
|
-
paths = @compilation_context.file_resolver.dest_finder.find_files(pattern
|
72
|
+
paths = @compilation_context.file_resolver.dest_finder.find_files(pattern, context_path: context_path,
|
73
|
+
groups: groups)
|
65
74
|
paths.map { |path| @compilation_context.file_resolver.file_with_destination_path(path) }
|
66
75
|
end
|
67
76
|
|
68
77
|
# Find file and raise exception if not found
|
69
78
|
#
|
70
79
|
# @param [String] pattern
|
80
|
+
# @param [String] context_path path to directory that is used as context for finding
|
81
|
+
# @param [Array<Symbol>, Symbol] groups
|
71
82
|
# @param [Thread::Backtrace::Location] location
|
72
83
|
#
|
73
84
|
# @return [Epuber::Compiler::FileTypes::AbstractFile]
|
74
85
|
#
|
75
|
-
def get_file(pattern, location: caller_locations.first)
|
76
|
-
file = find_file(pattern, location: location)
|
77
|
-
|
86
|
+
def get_file(pattern, context_path: nil, groups: nil, location: caller_locations.first)
|
87
|
+
file = find_file(pattern, context_path: context_path, groups: groups, location: location)
|
88
|
+
unless file
|
89
|
+
UI.error!("File with pattern #{pattern} not found (context path: #{context_path || 'nil'})",
|
90
|
+
location: location)
|
91
|
+
end
|
78
92
|
|
79
93
|
file
|
80
94
|
end
|
@@ -82,12 +96,14 @@ module Epuber
|
|
82
96
|
# Read file from destination path (raises exception if not found)
|
83
97
|
#
|
84
98
|
# @param [String] pattern
|
99
|
+
# @param [String] context_path path to directory that is used as context for finding
|
100
|
+
# @param [Array<Symbol>, Symbol] groups
|
85
101
|
# @param [Thread::Backtrace::Location] location
|
86
102
|
#
|
87
103
|
# @return [String]
|
88
104
|
#
|
89
|
-
def read_destination_file(pattern, location: caller_locations.first)
|
90
|
-
file = get_file(pattern, location: location)
|
105
|
+
def read_destination_file(pattern, context_path: nil, groups: nil, location: caller_locations.first)
|
106
|
+
file = get_file(pattern, context_path: context_path, groups: groups, location: location)
|
91
107
|
File.read(file.final_destination_path)
|
92
108
|
end
|
93
109
|
|
@@ -95,12 +111,14 @@ module Epuber
|
|
95
111
|
#
|
96
112
|
# @param [String] pattern
|
97
113
|
# @param [String] content
|
114
|
+
# @param [String] context_path path to directory that is used as context for finding
|
115
|
+
# @param [Array<Symbol>, Symbol] groups
|
98
116
|
# @param [Thread::Backtrace::Location] location
|
99
117
|
#
|
100
118
|
# @return [void]
|
101
119
|
#
|
102
|
-
def write_destination_file(pattern, content, location: caller_locations.first)
|
103
|
-
file = get_file(pattern, location: location)
|
120
|
+
def write_destination_file(pattern, content, context_path: nil, groups: nil, location: caller_locations.first)
|
121
|
+
file = get_file(pattern, context_path: context_path, groups: groups, location: location)
|
104
122
|
Compiler::FileTypes::AbstractFile.write_to_file(content, file.final_destination_path)
|
105
123
|
end
|
106
124
|
end
|
@@ -1,235 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'nokogiri'
|
3
|
+
require 'delegate'
|
5
4
|
|
6
|
-
require_relative '
|
7
|
-
require_relative 'command'
|
5
|
+
require_relative 'utils/logger/console_logger'
|
8
6
|
|
9
7
|
module Epuber
|
10
|
-
class UserInterface
|
11
|
-
|
12
|
-
|
13
|
-
class << self
|
14
|
-
# @return [Epuber::Command]
|
15
|
-
#
|
16
|
-
attr_accessor :current_command
|
17
|
-
end
|
18
|
-
|
19
|
-
# Fatal error, prints message and exit with return code 1
|
20
|
-
#
|
21
|
-
# @param [Exception, String] message message of the error
|
22
|
-
# @param [Thread::Backtrace::Location] location location of the error
|
23
|
-
#
|
24
|
-
def self.error!(message, location: nil)
|
25
|
-
error(message, location: location)
|
26
|
-
exit(1)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Fatal error, prints message and exit with return code 1
|
30
|
-
#
|
31
|
-
# @param [String] message message of the error
|
32
|
-
# @param [Thread::Backtrace::Location] location location of the error
|
33
|
-
# @param [Bool] backtrace output backtrace locations, nil == automatic, true == always and false == never
|
34
|
-
#
|
35
|
-
def self.error(message, location: nil)
|
36
|
-
_clear_processing_line_for_new_output do
|
37
|
-
$stdout.puts(_format_message(:error, message, location: location))
|
38
|
-
if current_command&.verbose?
|
39
|
-
_print_backtrace(location.try(:backtrace_locations) || message.try(:backtrace_locations) || caller_locations,
|
40
|
-
location: location)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# @param [String] message message of the error
|
46
|
-
# @param [Thread::Backtrace::Location] location location of the error
|
47
|
-
#
|
48
|
-
def self.warning(message, location: nil)
|
49
|
-
_clear_processing_line_for_new_output do
|
50
|
-
$stdout.puts(_format_message(:warning, message, location: location))
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# @param [#to_s] problem some problem, object just have to know to convert self into string with method #to_s
|
55
|
-
#
|
56
|
-
def self.print_processing_problem(problem)
|
57
|
-
_clear_processing_line_for_new_output do
|
58
|
-
$stdout.puts(problem.to_s.ansi.send(_color_from_level(:warning)))
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# @param [String] info_text
|
63
|
-
#
|
64
|
-
def self.print_processing_debug_info(info_text)
|
65
|
-
return unless current_command&.verbose?
|
66
|
-
|
67
|
-
_clear_processing_line_for_new_output do
|
68
|
-
message = if @current_file.nil?
|
69
|
-
"▸ #{info_text}"
|
70
|
-
else
|
71
|
-
"▸ #{@current_file.source_path}: #{info_text}"
|
72
|
-
end
|
73
|
-
|
74
|
-
$stdout.puts(message.ansi.send(_color_from_level(:debug)))
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# @param [Compiler::FileTypes::AbstractFile] file
|
79
|
-
#
|
80
|
-
# @return nil
|
81
|
-
#
|
82
|
-
def self.print_processing_file(file, index, count)
|
83
|
-
remove_processing_file_line
|
84
|
-
|
85
|
-
@current_file = file
|
86
|
-
|
87
|
-
@last_processing_file_line = "▸ Processing #{file.source_path} (#{index + 1} of #{count})"
|
88
|
-
$stdout.print(@last_processing_file_line)
|
89
|
-
end
|
90
|
-
|
91
|
-
def self.remove_processing_file_line
|
92
|
-
last_line = @last_processing_file_line
|
93
|
-
|
94
|
-
unless @last_processing_file_line.nil?
|
95
|
-
$stdout.print("\033[2K") # remove line, but without moving cursor
|
96
|
-
$stdout.print("\r") # go to beginning of line
|
97
|
-
@last_processing_file_line = nil
|
98
|
-
end
|
99
|
-
|
100
|
-
last_line
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.processing_files_done
|
104
|
-
remove_processing_file_line
|
105
|
-
|
106
|
-
@current_file = nil
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.puts(message)
|
110
|
-
_clear_processing_line_for_new_output do
|
111
|
-
$stdout.puts(message)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# @param [Compiler::FileTypes::AbstractFile] file
|
116
|
-
# @param [String] step_name
|
117
|
-
# @param [Fixnum] time
|
8
|
+
class UserInterface < Delegator
|
9
|
+
# @return [Logger::AbstractLogger]
|
118
10
|
#
|
119
|
-
|
120
|
-
return yield if !current_command || !current_command.debug_steps_times
|
121
|
-
|
122
|
-
remove_processing_file_line
|
11
|
+
attr_reader :logger
|
123
12
|
|
124
|
-
|
125
|
-
|
126
|
-
returned_value = yield
|
13
|
+
def initialize
|
14
|
+
super(nil)
|
127
15
|
|
128
|
-
|
129
|
-
end
|
130
|
-
|
131
|
-
info_text = "Step #{step_name} took #{time * 1000} ms"
|
132
|
-
message = if @current_file.nil?
|
133
|
-
"▸ #{info_text}"
|
134
|
-
else
|
135
|
-
"▸ #{@current_file.source_path}: #{info_text}"
|
136
|
-
end
|
137
|
-
|
138
|
-
$stdout.puts(_format_message(:debug, message))
|
139
|
-
|
140
|
-
returned_value
|
16
|
+
@logger = Logger::ConsoleLogger.new
|
141
17
|
end
|
142
18
|
|
143
|
-
def
|
144
|
-
|
145
|
-
|
146
|
-
yield
|
147
|
-
|
148
|
-
@last_processing_file_line = last_line
|
149
|
-
$stdout.print(last_line)
|
150
|
-
end
|
151
|
-
|
152
|
-
# @param [Symbol] level color of the output
|
153
|
-
#
|
154
|
-
# @return [Symbol] color
|
155
|
-
#
|
156
|
-
def self._color_from_level(level)
|
157
|
-
case level
|
158
|
-
when :error then :red
|
159
|
-
when :warning then :yellow
|
160
|
-
when :normal then :white
|
161
|
-
when :debug then :blue
|
162
|
-
else
|
163
|
-
raise "Unknown output level #{level}"
|
164
|
-
end
|
19
|
+
def __getobj__
|
20
|
+
@logger
|
165
21
|
end
|
166
22
|
|
167
|
-
|
168
|
-
|
169
|
-
# @return [Location]
|
170
|
-
#
|
171
|
-
def self._location_from_obj(obj)
|
172
|
-
case obj
|
173
|
-
when ::Thread::Backtrace::Location
|
174
|
-
Location.new(path: obj.path, lineno: obj.lineno)
|
175
|
-
when ::Nokogiri::XML::Node
|
176
|
-
Location.new(path: obj.document.file_path, lineno: obj.line)
|
177
|
-
when Location
|
178
|
-
obj
|
179
|
-
when Epuber::Compiler::FileTypes::AbstractFile
|
180
|
-
Location.new(path: obj.source_path)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
# @param [Symbol] level color of the output
|
185
|
-
# @param [String] message message of the error
|
186
|
-
# @param [Thread::Backtrace::Location] location location of the error
|
187
|
-
#
|
188
|
-
# @return [String] formatted message
|
189
|
-
#
|
190
|
-
def self._format_message(level, message, location: nil)
|
191
|
-
location = _location_from_obj(location)
|
192
|
-
|
193
|
-
comps = []
|
194
|
-
comps << message.to_s
|
195
|
-
message_already_formatted =
|
196
|
-
message.is_a?(Epuber::Compiler::Problem) || message.is_a?(Epuber::Checker::TextChecker::MatchProblem)
|
197
|
-
|
198
|
-
if !location.nil? && !message_already_formatted
|
199
|
-
path = location.path
|
200
|
-
|
201
|
-
# calculate relative path when path is absolute and in project
|
202
|
-
path = path[Config.instance.project_path.size + 1..-1] if path.start_with?(Config.instance.project_path)
|
203
|
-
|
204
|
-
line_parts = [
|
205
|
-
" (in file #{path}",
|
206
|
-
]
|
207
|
-
line_parts << "line #{location.lineno}" if location.lineno
|
208
|
-
line_parts << "column #{location.column}" if location.column
|
209
|
-
|
210
|
-
comps << "#{line_parts.join(' ')})"
|
211
|
-
end
|
212
|
-
|
213
|
-
comps.join("\n").ansi.send(_color_from_level(level))
|
214
|
-
end
|
215
|
-
|
216
|
-
# @param [Array<Thread::Backtrace::Location>] locations locations of the error (only for verbose output)
|
217
|
-
# @param [Thread::Backtrace::Location] location location of the error
|
218
|
-
#
|
219
|
-
# @return [String] formatted message
|
220
|
-
#
|
221
|
-
def self._format_backtrace(locations, location: nil)
|
222
|
-
index = locations.index(location) || 0
|
223
|
-
locations[index, locations.size].map(&:to_s)
|
224
|
-
end
|
225
|
-
|
226
|
-
# @param [Thread::Backtrace::Location] location location of the error
|
227
|
-
#
|
228
|
-
def self._print_backtrace(locations, location: nil)
|
229
|
-
$stdout.puts(_format_backtrace(locations, location: location)) if current_command.verbose?
|
23
|
+
def __setobj__(obj)
|
24
|
+
@logger = obj
|
230
25
|
end
|
231
26
|
end
|
232
27
|
|
233
28
|
# shortcut
|
234
|
-
UI = UserInterface
|
29
|
+
UI = UserInterface.new
|
235
30
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Epuber
|
4
|
+
Location = Struct.new(:path, :lineno, :column, keyword_init: true) do
|
5
|
+
# !@attribute [r] path
|
6
|
+
# @return [String] path to file
|
7
|
+
|
8
|
+
# !@attribute [r] lineno
|
9
|
+
# @return [Integer, nil] line number
|
10
|
+
|
11
|
+
# !@attribute [r] column
|
12
|
+
# @return [Integer, nil] column number
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object/try'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
require_relative '../location'
|
7
|
+
|
8
|
+
module Epuber
|
9
|
+
module Logger
|
10
|
+
class AbstractLogger
|
11
|
+
LEVELS = %i[
|
12
|
+
error
|
13
|
+
warning
|
14
|
+
info
|
15
|
+
debug
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
# @return [Boolean]
|
19
|
+
#
|
20
|
+
attr_accessor :verbose
|
21
|
+
|
22
|
+
# @return [Boolean]
|
23
|
+
#
|
24
|
+
attr_accessor :debug_steps_times
|
25
|
+
|
26
|
+
# @param [Hash] opts
|
27
|
+
# @option opts [Boolean] :verbose (false)
|
28
|
+
# @option opts [Boolean] :debug_steps_times (false)
|
29
|
+
#
|
30
|
+
def initialize(opts = {})
|
31
|
+
@verbose = opts.fetch(:verbose, false)
|
32
|
+
@debug_steps_times = opts.fetch(:debug_steps_times, false)
|
33
|
+
|
34
|
+
@current_file = nil
|
35
|
+
@sticky_message = nil
|
36
|
+
@error_was_logged = false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Report error message
|
40
|
+
#
|
41
|
+
# @param [String, #to_s] message
|
42
|
+
# @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
|
43
|
+
# @param [Boolean] stick if true, the error message will be sticked to the previous one
|
44
|
+
#
|
45
|
+
def error!(message, location: nil, backtrace: caller_locations)
|
46
|
+
_common_log(:error, message, location: location, backtrace: backtrace)
|
47
|
+
exit(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Report error message
|
51
|
+
#
|
52
|
+
# @param [String, #to_s] message
|
53
|
+
# @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
|
54
|
+
# @param [Boolean] stick if true, the error message will be sticked to the previous one
|
55
|
+
#
|
56
|
+
def error(message, sticky: false, location: nil, backtrace: caller_locations)
|
57
|
+
_common_log(:error, message, sticky: sticky, location: location, backtrace: backtrace)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Report warning message
|
61
|
+
#
|
62
|
+
# @param [String, #to_s] message
|
63
|
+
# @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
|
64
|
+
#
|
65
|
+
def warning(message, sticky: false, location: nil, backtrace: caller_locations)
|
66
|
+
_common_log(:warning, message, sticky: sticky, location: location, backtrace: backtrace)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Report info message
|
70
|
+
#
|
71
|
+
# @param [String, #to_s] message
|
72
|
+
# @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
|
73
|
+
#
|
74
|
+
def info(message, sticky: false, location: nil, backtrace: caller_locations)
|
75
|
+
_common_log(:info, message, sticky: sticky, location: location, backtrace: backtrace)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Report debug message
|
79
|
+
#
|
80
|
+
# @param [String, #to_s] message
|
81
|
+
# @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
|
82
|
+
#
|
83
|
+
def debug(message, sticky: false, location: nil, backtrace: caller_locations)
|
84
|
+
return unless @verbose
|
85
|
+
|
86
|
+
_common_log(:debug, message, sticky: sticky, location: location, backtrace: backtrace)
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param [Epuber::Compiler::FileTypes::AbstractFile] file
|
90
|
+
# @param [Fixnum] index
|
91
|
+
# @param [Fixnum] count
|
92
|
+
#
|
93
|
+
def start_processing_file(file, index, count)
|
94
|
+
@current_file = file
|
95
|
+
|
96
|
+
_common_log(:debug, "▸ Processing #{file.source_path} (#{index + 1} of #{count})", sticky: true)
|
97
|
+
end
|
98
|
+
|
99
|
+
def end_processing
|
100
|
+
_remove_sticky_message
|
101
|
+
@current_file = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
# @param [String] info_text
|
105
|
+
#
|
106
|
+
def print_processing_debug_info(info_text)
|
107
|
+
return unless @verbose
|
108
|
+
|
109
|
+
message = if @current_file.nil?
|
110
|
+
"▸ #{info_text}"
|
111
|
+
else
|
112
|
+
"▸ #{@current_file.source_path}: #{info_text}"
|
113
|
+
end
|
114
|
+
_log(:debug, message)
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param [String] step_name
|
118
|
+
# @param [Fixnum] time
|
119
|
+
#
|
120
|
+
def print_step_processing_time(step_name, time = nil)
|
121
|
+
return yield unless @debug_steps_times
|
122
|
+
|
123
|
+
if block_given?
|
124
|
+
start = Time.now
|
125
|
+
returned_value = yield
|
126
|
+
|
127
|
+
time = Time.now - start
|
128
|
+
end
|
129
|
+
|
130
|
+
info_text = "Step #{step_name} took #{(time * 1000).round(2)} ms"
|
131
|
+
message = if @current_file.nil?
|
132
|
+
"▸ #{info_text}"
|
133
|
+
else
|
134
|
+
"▸ #{@current_file.source_path}: #{info_text}"
|
135
|
+
end
|
136
|
+
|
137
|
+
_log(:debug, message)
|
138
|
+
|
139
|
+
returned_value
|
140
|
+
end
|
141
|
+
|
142
|
+
# Return true if there was any error logged
|
143
|
+
#
|
144
|
+
# @return [Boolean]
|
145
|
+
def error?
|
146
|
+
@error_was_logged
|
147
|
+
end
|
148
|
+
|
149
|
+
protected
|
150
|
+
|
151
|
+
# Point of implementation for concrete logger
|
152
|
+
#
|
153
|
+
# @param [Symbol] level
|
154
|
+
# @param [String] message
|
155
|
+
# @param [Epuber::Location, nil] location
|
156
|
+
# @param [Array<Thread::Backtrace::Location>, nil] backtrace
|
157
|
+
# @param [Boolean] sticky if true, the message will be sticky (will be always as the last message)
|
158
|
+
#
|
159
|
+
def _log(level, message, location: nil, backtrace: nil, remove_last: false) # rubocop:disable Lint/UnusedMethodArgument
|
160
|
+
raise 'Not implemented, this is abstract class'
|
161
|
+
end
|
162
|
+
|
163
|
+
# Remove last line of the output (if it was sticky)
|
164
|
+
#
|
165
|
+
# @return [String, nil] last line
|
166
|
+
#
|
167
|
+
def _remove_sticky_message; end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
# Core logging method
|
172
|
+
#
|
173
|
+
# @param level [Symbol]
|
174
|
+
# @param message [String]
|
175
|
+
# @param location [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node,
|
176
|
+
# Epuber::Compiler::FileTypes::AbstractFile, nil]
|
177
|
+
# @param sticky [Boolean] if true, the message will be sticky (will be always as the last message)
|
178
|
+
#
|
179
|
+
def _common_log(level, message, sticky: false, location: nil, backtrace: nil)
|
180
|
+
raise ArgumentError, "Unknown log level #{level}" unless LEVELS.include?(level)
|
181
|
+
|
182
|
+
@error_was_logged = true if level == :error
|
183
|
+
|
184
|
+
location = _location_from_obj(location)
|
185
|
+
|
186
|
+
if @verbose && level == :error
|
187
|
+
backtrace = location.try(:backtrace_locations) ||
|
188
|
+
message.try(:backtrace_locations) ||
|
189
|
+
backtrace ||
|
190
|
+
caller_locations
|
191
|
+
end
|
192
|
+
|
193
|
+
_log(level, message, location: location, backtrace: backtrace, sticky: sticky)
|
194
|
+
end
|
195
|
+
|
196
|
+
# @param [Thread::Backtrace::Location, Nokogiri::XML::Node] obj
|
197
|
+
#
|
198
|
+
# @return [Location]
|
199
|
+
#
|
200
|
+
def _location_from_obj(obj)
|
201
|
+
case obj
|
202
|
+
when ::Thread::Backtrace::Location
|
203
|
+
Location.new(path: obj.path, lineno: obj.lineno)
|
204
|
+
when ::Nokogiri::XML::Node
|
205
|
+
Location.new(path: obj.document.file_path, lineno: obj.line)
|
206
|
+
when Location
|
207
|
+
obj
|
208
|
+
when Epuber::Compiler::FileTypes::AbstractFile
|
209
|
+
Location.new(path: obj.source_path)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|