epuber 0.7.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -2
  3. data/LICENSE.txt +1 -1
  4. data/README.md +4 -3
  5. data/epuber.gemspec +11 -16
  6. data/lib/epuber/book/contributor.rb +10 -7
  7. data/lib/epuber/book/file_request.rb +3 -3
  8. data/lib/epuber/book/target.rb +30 -33
  9. data/lib/epuber/book/toc_item.rb +2 -4
  10. data/lib/epuber/book.rb +21 -21
  11. data/lib/epuber/checker/bookspec_checker.rb +26 -0
  12. data/lib/epuber/checker/text_checker.rb +16 -7
  13. data/lib/epuber/checker.rb +16 -2
  14. data/lib/epuber/checker_transformer_base.rb +3 -6
  15. data/lib/epuber/command/build.rb +40 -25
  16. data/lib/epuber/command/from_file.rb +39 -0
  17. data/lib/epuber/command/init.rb +34 -32
  18. data/lib/epuber/command/server.rb +3 -3
  19. data/lib/epuber/command.rb +18 -20
  20. data/lib/epuber/compiler/compilation_context.rb +10 -8
  21. data/lib/epuber/compiler/file_database.rb +2 -4
  22. data/lib/epuber/compiler/file_finders/abstract.rb +36 -26
  23. data/lib/epuber/compiler/file_finders/imaginary.rb +40 -35
  24. data/lib/epuber/compiler/file_resolver.rb +79 -89
  25. data/lib/epuber/compiler/file_stat.rb +4 -4
  26. data/lib/epuber/compiler/file_types/abstract_file.rb +4 -7
  27. data/lib/epuber/compiler/file_types/bade_file.rb +20 -15
  28. data/lib/epuber/compiler/file_types/coffee_script_file.rb +1 -1
  29. data/lib/epuber/compiler/file_types/css_file.rb +103 -0
  30. data/lib/epuber/compiler/file_types/generated_file.rb +1 -1
  31. data/lib/epuber/compiler/file_types/image_file.rb +4 -2
  32. data/lib/epuber/compiler/file_types/nav_file.rb +0 -1
  33. data/lib/epuber/compiler/file_types/opf_file.rb +0 -1
  34. data/lib/epuber/compiler/file_types/source_file.rb +8 -3
  35. data/lib/epuber/compiler/file_types/stylus_file.rb +4 -3
  36. data/lib/epuber/compiler/file_types/xhtml_file.rb +67 -13
  37. data/lib/epuber/compiler/generator.rb +1 -2
  38. data/lib/epuber/compiler/meta_inf_generator.rb +1 -1
  39. data/lib/epuber/compiler/nav_generator.rb +10 -11
  40. data/lib/epuber/compiler/opf_generator.rb +26 -27
  41. data/lib/epuber/compiler/problem.rb +12 -21
  42. data/lib/epuber/compiler/xhtml_processor.rb +63 -32
  43. data/lib/epuber/compiler.rb +77 -25
  44. data/lib/epuber/config.rb +16 -10
  45. data/lib/epuber/dsl/attribute.rb +17 -18
  46. data/lib/epuber/dsl/attribute_support.rb +7 -7
  47. data/lib/epuber/dsl/object.rb +19 -17
  48. data/lib/epuber/dsl/tree_object.rb +2 -3
  49. data/lib/epuber/epubcheck.rb +15 -0
  50. data/lib/epuber/from_file/bookspec_generator.rb +371 -0
  51. data/lib/epuber/from_file/encryption_handler.rb +146 -0
  52. data/lib/epuber/from_file/from_file_executor.rb +140 -0
  53. data/lib/epuber/from_file/nav_file.rb +163 -0
  54. data/lib/epuber/from_file/opf_file.rb +219 -0
  55. data/lib/epuber/helper.rb +0 -1
  56. data/lib/epuber/lockfile.rb +7 -9
  57. data/lib/epuber/plugin.rb +2 -3
  58. data/lib/epuber/ruby_extensions/match_data.rb +1 -1
  59. data/lib/epuber/ruby_extensions/thread.rb +1 -0
  60. data/lib/epuber/server/base.styl +0 -1
  61. data/lib/epuber/server/basic.styl +1 -30
  62. data/lib/epuber/server/handlers.rb +1 -1
  63. data/lib/epuber/server.rb +81 -80
  64. data/lib/epuber/third_party/bower.rb +5 -5
  65. data/lib/epuber/transformer/book_transformer.rb +108 -0
  66. data/lib/epuber/transformer/text_transformer.rb +4 -2
  67. data/lib/epuber/transformer.rb +4 -2
  68. data/lib/epuber/user_interface.rb +49 -38
  69. data/lib/epuber/vendor/hash_binding.rb +9 -2
  70. data/lib/epuber/vendor/ruby_templater.rb +4 -8
  71. data/lib/epuber/vendor/version.rb +12 -12
  72. data/lib/epuber/version.rb +1 -1
  73. metadata +79 -100
  74. data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Bold.ttf +0 -0
  75. data/lib/epuber/server/fonts/AvenirNext/AvenirNext-BoldItalic.ttf +0 -0
  76. data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Italic.ttf +0 -0
  77. data/lib/epuber/server/fonts/AvenirNext/AvenirNext-Regular.ttf +0 -0
@@ -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("Not writing to disk ... compiled version at #{pkg_destination_path} is same")
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("Not writing to disk ... processed version at #{pkg_destination_path} is same")
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
@@ -5,9 +5,9 @@ require 'epuber-stylus'
5
5
  module Epuber
6
6
  class Compiler
7
7
  module FileTypes
8
- require_relative 'source_file'
8
+ require_relative 'css_file'
9
9
 
10
- class StylusFile < SourceFile
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
- write_compiled(Stylus.compile(File.new(abs_source_path)))
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
@@ -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(Pathname.new(File.dirname(final_destination_path))).to_s
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(Pathname.new(File.dirname(final_destination_path))).to_s
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 > 0
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
- self.properties << :remote_resources if XHTMLProcessor.using_remote_resources?(xhtml_doc)
124
- self.properties << :scripted if XHTMLProcessor.using_javascript?(xhtml_doc)
125
- self.properties << :mathml if XHTMLProcessor.using_mathml?(xhtml_doc)
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
- xhtml_doc.to_s
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.call(xml) unless block.nil?
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.kind_of?(FileTypes::OPFFile) }.each do |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: { type: 'cover', text: 'Cover page' },
30
- landmark_start_page: { type: %w(bodymatter ibooks:reader-start-page), text: 'Start Reading' },
31
- landmark_copyright: { type: 'copyright-page', text: 'Copyright page' },
32
- landmark_toc: { type: 'toc', text: 'Table of contents' },
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
@@ -95,7 +94,7 @@ module Epuber
95
94
  @xml.ncx(nav_namespaces, version: '2005-1') do
96
95
  # head
97
96
  @xml.head do
98
- @xml.meta(name: 'dtb:uid', content: (@target.identifier || "urn:isbn:#{@target.isbn}"))
97
+ @xml.meta(name: 'dtb:uid', content: @target.identifier || "urn:isbn:#{@target.isbn}")
99
98
  end
100
99
 
101
100
  # title
@@ -112,7 +111,7 @@ module Epuber
112
111
  end
113
112
  end
114
113
 
115
- # @param toc_items [Array<Epuber::Book::TocItem>]
114
+ # @param [Array<Epuber::Book::TocItem>] toc_items
116
115
  #
117
116
  def visit_toc_items(toc_items)
118
117
  iterate_lambda = lambda do
@@ -121,7 +120,7 @@ module Epuber
121
120
  end
122
121
  end
123
122
 
124
- if @target.epub_version >= 3 && toc_items.length > 0 && contains_item_with_title(toc_items)
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
@@ -134,7 +133,7 @@ module Epuber
134
133
  toc_items.any? { |a| a.title || contains_item_with_title(a.sub_items) }
135
134
  end
136
135
 
137
- # @param toc_item [Epuber::Book::TocItem]
136
+ # @param [Epuber::Book::TocItem] toc_item
138
137
  #
139
138
  def visit_toc_item(toc_item)
140
139
  result_file_path = pretty_path_for_toc_item(toc_item)
@@ -166,7 +165,7 @@ module Epuber
166
165
 
167
166
  # --------------- landmarks -----------------------------
168
167
 
169
- # @param toc_items [Array<Epuber::Book::TocItem>]
168
+ # @param [Array<Epuber::Book::TocItem>] toc_items
170
169
  #
171
170
  def landmarks_visit_toc_items(toc_items)
172
171
  toc_items.each do |child_item|
@@ -174,7 +173,7 @@ module Epuber
174
173
  end
175
174
  end
176
175
 
177
- # @param toc_item [Epuber::Book::TocItem]
176
+ # @param [Epuber::Book::TocItem] toc_item
178
177
  #
179
178
  def landmarks_visit_toc_item(toc_item)
180
179
  landmarks = toc_item.landmarks
@@ -11,20 +11,19 @@ require_relative '../book/toc_item'
11
11
  module Epuber
12
12
  class Compiler
13
13
  class OPFGenerator < Generator
14
-
15
14
  EPUB2_NAMESPACES = {
16
- 'xmlns' => 'http://www.idpf.org/2007/opf',
17
- 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
15
+ 'xmlns' => 'http://www.idpf.org/2007/opf',
16
+ 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
18
17
  'xmlns:opf' => 'http://www.idpf.org/2007/opf',
19
18
  }.freeze
20
19
 
21
20
  EPUB3_NAMESPACES = {
22
- 'prefix' => 'rendition: http://www.idpf.org/vocab/rendition/',
21
+ 'prefix' => 'rendition: http://www.idpf.org/vocab/rendition/',
23
22
  'xmlns:epub' => 'http://www.idpf.org/2007/ops',
24
23
  }.freeze
25
24
 
26
25
  IBOOKS_NAMESPACES = {
27
- 'prefix' => 'rendition: http://www.idpf.org/vocab/rendition/# ibooks: http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/',
26
+ 'prefix' => 'rendition: http://www.idpf.org/vocab/rendition/# ibooks: http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/',
28
27
  'xmlns:ibooks' => 'http://apple.com/ibooks/html-extensions',
29
28
  }.freeze
30
29
 
@@ -32,32 +31,32 @@ module Epuber
32
31
  LANDMARKS_MAP = {
33
32
 
34
33
  # my favorite
35
- landmark_cover: 'cover',
34
+ landmark_cover: 'cover',
36
35
  landmark_start_page: 'text',
37
- landmark_copyright: 'copyright-page',
38
- landmark_toc: 'toc',
36
+ landmark_copyright: 'copyright-page',
37
+ landmark_toc: 'toc',
39
38
 
40
39
  # others
41
- landmark_title: 'title-page',
42
- landmark_index: 'index',
43
- landmark_glossary: 'glossary',
44
- landmark_acknowledgements: 'acknowledgements',
45
- landmark_bibliography: 'bibliography',
46
- landmark_colophon: 'colophon',
47
- landmark_dedication: 'dedication',
48
- landmark_epigraph: 'epigraph',
49
- landmark_foreword: 'foreword',
40
+ landmark_title: 'title-page',
41
+ landmark_index: 'index',
42
+ landmark_glossary: 'glossary',
43
+ landmark_acknowledgements: 'acknowledgements',
44
+ landmark_bibliography: 'bibliography',
45
+ landmark_colophon: 'colophon',
46
+ landmark_dedication: 'dedication',
47
+ landmark_epigraph: 'epigraph',
48
+ landmark_foreword: 'foreword',
50
49
  landmark_list_of_illustrations: 'loi',
51
- landmark_list_of_tables: 'lot',
52
- landmark_notes: 'notes',
53
- landmark_preface: 'preface',
50
+ landmark_list_of_tables: 'lot',
51
+ landmark_notes: 'notes',
52
+ landmark_preface: 'preface',
54
53
 
55
54
  }.freeze
56
55
 
57
56
  PROPERTIES_MAP = {
58
57
  cover_image: 'cover-image',
59
- navigation: 'nav',
60
- scripted: 'scripted',
58
+ navigation: 'nav',
59
+ scripted: 'scripted',
61
60
  remote_resources: 'remote-resources',
62
61
  mathml: 'mathml',
63
62
  }.freeze
@@ -164,7 +163,7 @@ module Epuber
164
163
  attrs['media-type'] = mime_type_for(file)
165
164
 
166
165
  properties = file.properties
167
- if properties.length > 0 && @target.epub_version >= 3
166
+ if properties.length.positive? && @target.epub_version >= 3
168
167
  pretty_properties = properties.to_a.map { |property| PROPERTIES_MAP[property] }.join(' ')
169
168
  attrs['properties'] = pretty_properties
170
169
  end
@@ -218,7 +217,7 @@ module Epuber
218
217
  end
219
218
  end
220
219
 
221
- # @param toc_items [Array<Epuber::Book::TocItem>]
220
+ # @param [Array<Epuber::Book::TocItem>] toc_items
222
221
  #
223
222
  # @return nil
224
223
  #
@@ -228,7 +227,7 @@ module Epuber
228
227
  end
229
228
  end
230
229
 
231
- # @param toc_item [Epuber::Book::TocItem]
230
+ # @param [Epuber::Book::TocItem] toc_item
232
231
  #
233
232
  # @return nil
234
233
  #
@@ -252,7 +251,7 @@ module Epuber
252
251
 
253
252
  # Creates id from file path
254
253
  #
255
- # @param path [String]
254
+ # @param [String] path
256
255
  #
257
256
  # @return [String]
258
257
  #
@@ -264,7 +263,7 @@ module Epuber
264
263
 
265
264
  # Creates proper mime-type for file
266
265
  #
267
- # @param file [Epuber::Compiler::FileTypes::AbstractFile | String]
266
+ # @param [Epuber::Compiler::FileTypes::AbstractFile | String] file
268
267
  #
269
268
  # @return [String]
270
269
  #
@@ -4,9 +4,7 @@ module Epuber
4
4
  class Compiler
5
5
  class Problem
6
6
  class Location
7
- attr_reader :line
8
- attr_reader :column
9
- attr_reader :length
7
+ attr_reader :line, :column, :length
10
8
 
11
9
  def initialize(line, column, length = nil)
12
10
  @line = line
@@ -15,20 +13,14 @@ module Epuber
15
13
  end
16
14
  end
17
15
 
18
- attr_reader :level
19
- attr_reader :message
20
- attr_reader :source
21
- attr_reader :location
22
- attr_reader :file_path
16
+ attr_reader :level, :message, :source, :location, :file_path
23
17
 
24
18
  def initialize(level, message, source, location: nil, line: nil, column: nil, length: nil, file_path: nil)
25
19
  @level = level
26
20
  @message = message
27
21
  @source = source
28
22
  @location = location
29
- if @location.nil? && line && column
30
- @location = Location.new(line, column, length)
31
- end
23
+ @location = Location.new(line, column, length) if @location.nil? && line && column
32
24
 
33
25
  @file_path = file_path
34
26
  end
@@ -40,7 +32,7 @@ module Epuber
40
32
  # @return [String]
41
33
  #
42
34
  def self.caret_symbol(indent)
43
- ' ' * indent + '^'
35
+ "#{' ' * indent}^"
44
36
  end
45
37
 
46
38
  # Formats caret symbols for indent and length
@@ -53,7 +45,7 @@ module Epuber
53
45
  def self.caret_symbols(indent, length)
54
46
  start_sign = caret_symbol(indent)
55
47
  end_sign = if length > 1
56
- caret_symbol(length-2)
48
+ caret_symbol(length - 2)
57
49
  else
58
50
  ''
59
51
  end
@@ -74,10 +66,11 @@ module Epuber
74
66
  lines = text.split("\n")
75
67
 
76
68
  line = lines[line_index] || ''
77
- matched_text = line[column_index ... column_index + location.length] || ''
69
+ matched_text = line[column_index...column_index + location.length] || ''
78
70
 
79
- pre = (lines[0 ... line_index] + [line[0 ... column_index]]).join("\n")
80
- post = ([line[column_index + location.length .. line.length]] + (lines[location.line .. lines.count] || [])).join("\n")
71
+ pre = (lines[0...line_index] + [line[0...column_index]]).join("\n")
72
+ post = ([line[column_index + location.length..line.length]] + (lines[location.line..lines.count] || []))
73
+ .join("\n")
81
74
 
82
75
  [pre, matched_text, post]
83
76
  end
@@ -89,9 +82,7 @@ module Epuber
89
82
  post_line = post.split("\n").first || ''
90
83
 
91
84
  pre = match_pre_line = pre_line
92
- if remove_tabs(match_pre_line).length > 100
93
- pre = "#{match_pre_line.first(20)}...#{match_pre_line.last(30)}"
94
- end
85
+ pre = "#{match_pre_line.first(20)}...#{match_pre_line.last(30)}" if remove_tabs(match_pre_line).length > 100
95
86
 
96
87
  pre = remove_tabs(pre)
97
88
 
@@ -114,8 +105,8 @@ module Epuber
114
105
 
115
106
  [
116
107
  "#{@file_path}:#{line} column: #{column} --- #{@message}",
117
- ' ' + pre + colored_match_text + post,
118
- ' ' + pointers,
108
+ " #{pre}#{colored_match_text}#{post}",
109
+ " #{pointers}",
119
110
  ].join("\n")
120
111
  end
121
112
  end