epuber 0.9.4 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/epuber.gemspec +1 -1
- 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 +77 -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 +8 -5
@@ -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
|