fb2rb 0.1.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1f9023970c90759eb32f56a5bbef46864bb5b6bbe74801b63d74b215bc20741
4
- data.tar.gz: a44854f8a96a67c36a3bc7e3f66a24209de49d211508f267ccf6fe7f1fcf1651
3
+ metadata.gz: 3232aa66bba2be36e9f72b67c198a6b2e1b8e13d2cb51746264b44daaab9c60e
4
+ data.tar.gz: 00c679822965363b7ffade747f1898f9d5a687c408cab6240afa8ac150108593
5
5
  SHA512:
6
- metadata.gz: '062709548a3e5d5fd83ec9b85709f5beb5018d5d5b490dcc6f81af71c09d7e9a7d0c5bcd7b14fb1cff55491cda656987b55518f11c299f222918eba58d406ec4'
7
- data.tar.gz: 45c0b3159351d8636695df9ec95a55b62ba7810af3b8320ed1210ea0895fd53a6cf35433bb803878133597f4f839c242efa9731004521c953475d0d56c1a8b13
6
+ metadata.gz: 7684b0249c15f2ca45fd209df32b6dae4f52192d0aa2cf17fff9c63c83666bbec7c1c7aafc5c4055e87a13f2967113056a81d94c5bc490448897a61f73695255
7
+ data.tar.gz: 9e93f45e0567bac65cdf97b9c18d2912b869d5a605d228e1bf667e58739a915a092d5623b6b385fe844817e337457444bca74580ebdb9bcd5720dcaef6af304a
@@ -6,3 +6,8 @@ updates:
6
6
  directory: "/"
7
7
  schedule:
8
8
  interval: "daily"
9
+
10
+ - package-ecosystem: "github-actions"
11
+ directory: "/"
12
+ schedule:
13
+ interval: "daily"
@@ -13,12 +13,6 @@ jobs:
13
13
  with:
14
14
  ruby-version: 2.7
15
15
  - name: Publish to RubyGems.org
16
- run: |
17
- mkdir -p $HOME/.gem
18
- touch $HOME/.gem/credentials
19
- chmod 0600 $HOME/.gem/credentials
20
- printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
21
- gem build *.gemspec
22
- gem push *.gem
23
- env:
24
- RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
16
+ uses: dawidd6/action-publish-gem@v1
17
+ with:
18
+ api_key: ${{ secrets.RUBYGEMS_API_KEY }}
@@ -7,9 +7,32 @@
7
7
  This document provides a high-level view of the changes to the {project-name} by release.
8
8
  For a detailed view of what has changed, refer to the {uri-project}/commits/master[commit history] on GitHub.
9
9
 
10
+ == 0.5.0 (2020-12-07) - @slonopotamus
11
+
12
+ * return `nil` from `FB2rb::Book.read_compressed` for empty ZIP files
13
+ * **breaking change**: switch to named parameters instead of optional
14
+
15
+ == 0.4.0 (2020-11-24) - @slonopotamus
16
+
17
+ * add `Book::add_stylesheet` method
18
+
19
+ == 0.3.0 (2020-07-27) - @slonopotamus
20
+
21
+ * Support reading/writing uncompressed FB2. https://github.com/slonopotamus/fb2rb/issues/5[#5]
22
+
23
+ == 0.2.1 (2020-07-24) - @slonopotamus
24
+
25
+ * Fix field annotation on `FB2rb::TitleInfo::date`
26
+
27
+ == 0.2.0 (2020-07-24) - @slonopotamus
28
+
29
+ * Add support for reproducible builds
30
+ * Remove broken `FB2rb::Book.to_ios`.
31
+ Use `FB2rb::Book.write` instead.
32
+
10
33
  == 0.1.1 (2020-07-23) - @slonopotamus
11
34
 
12
- * Annonate field types
35
+ * Annotate field types
13
36
  * Fix serialization of `<publisher>` in `<document-info>`
14
37
 
15
38
  == 0.1.0 (2020-07-23) - @slonopotamus
@@ -37,6 +37,8 @@ $ gem install fb2rb
37
37
 
38
38
  == Usage
39
39
 
40
+ You can create FB2 book in memory and write it to file:
41
+
40
42
  [source,ruby]
41
43
  ----
42
44
  require 'fb2rb'
@@ -47,7 +49,23 @@ book.description.title_info.book_title = 'Book title'
47
49
  body = FB2rb::Body.new(nil, '<p>Book text</p>')
48
50
  book.bodies << body
49
51
 
50
- book.write('/path/to/book.fb2.zip')
52
+ book.write_compressed('/path/to/book.fb2.zip')
53
+ # or
54
+ book.write_uncompressed('/path/to/book.fb2')
55
+ ----
56
+
57
+ Also, you can read existing FB2 file:
58
+
59
+ [source,ruby]
60
+ ----
61
+ require 'fb2rb'
62
+
63
+ book = FB2rb::Book.read_compressed('/path/to/book.fb2.zip')
64
+ # or
65
+ book = FB2rb::Book.read_uncompressed('/path/to/book.fb2')
66
+
67
+ puts book.description.title_info.book_title
68
+ puts book.bodies[0].content
51
69
  ----
52
70
 
53
71
  == Development
@@ -22,7 +22,8 @@ Gem::Specification.new do |s|
22
22
  s.add_runtime_dependency 'rubyzip', '~> 2.3.0'
23
23
 
24
24
  s.add_development_dependency 'rake', '~> 13.0.0'
25
- s.add_development_dependency 'rspec', '~> 3.9.0'
26
- s.add_development_dependency 'rubocop', '~> 0.88.0'
27
- s.add_development_dependency 'rubocop-rspec', '~> 1.42.0'
25
+ s.add_development_dependency 'rspec', '~> 3.10.0'
26
+ s.add_development_dependency 'rubocop', '~> 1.5.0'
27
+ s.add_development_dependency 'rubocop-rake', '~> 0.5.0'
28
+ s.add_development_dependency 'rubocop-rspec', '~> 2.0.0'
28
29
  end
@@ -12,7 +12,7 @@ module FB2rb
12
12
  XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink'
13
13
 
14
14
  # Holds data of a single FB2 file
15
- class Book
15
+ class Book # rubocop:disable Metrics/ClassLength
16
16
  # @return [Array<FB2rb::Stylesheet>]
17
17
  attr_accessor(:stylesheets)
18
18
  # @return [FB2rb::Description]
@@ -22,47 +22,73 @@ module FB2rb
22
22
  # @return [Array<FB2fb::Binary>]
23
23
  attr_accessor(:binaries)
24
24
 
25
- def initialize(description = Description.new, bodies = [], binaries = [], stylesheets = [])
25
+ def initialize(description: Description.new, bodies: [], binaries: [], stylesheets: [])
26
26
  @binaries = binaries
27
27
  @bodies = bodies
28
28
  @description = description
29
29
  @stylesheets = stylesheets
30
30
  end
31
31
 
32
- # Reads existing FB2 file from an IO object, and creates new Book object.
33
- # @return [FB2rb::Book]
34
- def self.read(filename_or_io)
35
- Zip::InputStream.open(filename_or_io) do |zis|
36
- while (entry = zis.get_next_entry)
37
- next if entry.directory?
32
+ class << self
33
+ # Reads existing compressed FB2 file from an IO object, and creates new Book object.
34
+ # @return [FB2rb::Book, nil]
35
+ def read_compressed(filename_or_io)
36
+ Zip::InputStream.open(filename_or_io) do |zis|
37
+ while (entry = zis.get_next_entry)
38
+ next if entry.directory?
38
39
 
39
- xml = Nokogiri::XML::Document.parse(zis)
40
- fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
41
- xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
42
- return parse(xml, fb2_prefix, xlink_prefix)
40
+ xml = Nokogiri::XML::Document.parse(zis)
41
+ fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
42
+ xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
43
+ return parse(xml, fb2_prefix, xlink_prefix)
44
+ end
43
45
  end
46
+ nil
44
47
  end
45
- end
46
48
 
47
- def self.ns_prefix(namespace, namespaces)
48
- prefix = namespaces.key(namespace)
49
- prefix.nil? ? nil : prefix.sub(/^xmlns:/, '')
50
- end
49
+ # Reads existing uncompressed FB2 file from an IO object, and creates new Book object.
50
+ # @return [FB2rb::Book]
51
+ def read_uncompressed(filename_or_io)
52
+ xml = read_xml(filename_or_io)
53
+ fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
54
+ xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
55
+ parse(xml, fb2_prefix, xlink_prefix)
56
+ end
51
57
 
52
- # @return [FB2rb::Book]
53
- def self.parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/MethodLength
54
- Book.new(
55
- Description.parse(xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:description"), fb2_prefix, xlink_prefix),
56
- xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:body").map do |node|
57
- Body.parse(node)
58
- end,
59
- xml.xpath("#{fb2_prefix}:FictionBook/#{fb2_prefix}:binary").map do |node|
60
- Binary.parse(node)
61
- end,
62
- xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:stylesheet").map do |node|
63
- Stylesheet.parse(node)
58
+ def ns_prefix(namespace, namespaces)
59
+ prefix = namespaces.key(namespace)
60
+ prefix.nil? ? nil : prefix.sub(/^xmlns:/, '')
61
+ end
62
+
63
+ private
64
+
65
+ # @return [FB2rb::Book]
66
+ def parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/MethodLength
67
+ Book.new(
68
+ description: Description.parse(
69
+ xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:description"), fb2_prefix, xlink_prefix
70
+ ),
71
+ bodies: xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:body").map do |node|
72
+ Body.parse(node)
73
+ end,
74
+ binaries: xml.xpath("#{fb2_prefix}:FictionBook/#{fb2_prefix}:binary").map do |node|
75
+ Binary.parse(node)
76
+ end,
77
+ stylesheets: xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:stylesheet").map do |node|
78
+ Stylesheet.parse(node)
79
+ end
80
+ )
81
+ end
82
+
83
+ def read_xml(filename_or_io)
84
+ if filename_or_io.respond_to? :read
85
+ Nokogiri::XML::Document.parse(filename_or_io)
86
+ else
87
+ File.open(filename_or_io, 'rb') do |io|
88
+ return Nokogiri::XML::Document.parse(io)
89
+ end
64
90
  end
65
- )
91
+ end
66
92
  end
67
93
 
68
94
  def to_xml(xml) # rubocop:disable Metrics/MethodLength
@@ -81,26 +107,28 @@ module FB2rb
81
107
  end
82
108
  end
83
109
 
84
- def add_binary(name, filename_or_io, content_type = nil)
110
+ def add_binary(id, filename_or_io, content_type = nil)
85
111
  if filename_or_io.respond_to?(:read)
86
- add_binary_io name, filename_or_io, content_type
112
+ add_binary_io id, filename_or_io, content_type
87
113
  else
88
114
  File.open(filename_or_io, 'r') do |io|
89
- add_binary_io name, io, content_type
115
+ add_binary_io id, io, content_type
90
116
  end
91
117
  end
92
118
  end
93
119
 
94
- # Serializes and returns FB2 as StringIO.
95
- # @return [StringIO]
96
- def to_ios
97
- Zip::OutputStream.write_buffer do |io|
98
- write_to_stream(io)
120
+ def add_stylesheet(content_type, filename_or_io)
121
+ if filename_or_io.respond_to?(:read)
122
+ add_stylesheet_io(content_type, filename_or_io)
123
+ else
124
+ File.open(filename_or_io, 'r') do |io|
125
+ add_stylesheet_io(content_type, io)
126
+ end
99
127
  end
100
128
  end
101
129
 
102
- # Writes FB2 to file or IO object. If file exists, it will be overwritten.
103
- def write(filename_or_io)
130
+ # Writes compressed FB2 to file or IO object. If file exists, it will be overwritten.
131
+ def write_compressed(filename_or_io = StringIO.new)
104
132
  if filename_or_io.respond_to?(:write)
105
133
  Zip::OutputStream.write_buffer(filename_or_io) do |zos|
106
134
  write_to_zip(zos)
@@ -112,28 +140,48 @@ module FB2rb
112
140
  end
113
141
  end
114
142
 
143
+ # Writes FB2 (uncompressed) to file or IO object specified by the argument.
144
+ def write_uncompressed(filename_or_io = StringIO.new) # rubocop:disable Metrics/MethodLength
145
+ data = (Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
146
+ to_xml(xml)
147
+ end).to_xml
148
+
149
+ if filename_or_io.respond_to?(:write)
150
+ filename_or_io.write(data)
151
+ else
152
+ File.open(filename_or_io, 'wb') do |io|
153
+ io.write(data)
154
+ end
155
+ end
156
+ filename_or_io
157
+ end
158
+
115
159
  private
116
160
 
117
161
  def write_to_zip(zos)
162
+ mod_time = Zip::DOSTime.now
163
+ unless (tm = description.document_info.date.value).nil?
164
+ mod_time = Zip::DOSTime.gm(tm.year, tm.month, tm.day)
165
+ end
166
+
118
167
  # TODO: entry name
119
- zos.put_next_entry('book.fb2')
120
- write_to_stream(zos)
168
+ mimetype_entry = Zip::Entry.new(nil, 'book.fb2', nil, nil, nil, nil, nil, nil, mod_time)
169
+ zos.put_next_entry(mimetype_entry, nil, nil, Zip::Entry::DEFLATED)
170
+ write_uncompressed(zos)
121
171
  end
122
172
 
123
- def add_binary_io(name, io, content_type = nil)
173
+ def add_binary_io(id, io, content_type = nil)
124
174
  io.binmode
125
175
  content = io.read
126
- @binaries << Binary.new(name, content, content_type)
176
+ @binaries << Binary.new(id: id, content: content, content_type: content_type)
127
177
  self
128
178
  end
129
179
 
130
- # Writes FB2 (uncompressed) to stream specified by the argument.
131
- def write_to_stream(io)
132
- builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
133
- to_xml(xml)
134
- end
135
- xml = builder.to_xml
136
- io.write(xml)
180
+ def add_stylesheet_io(content_type, io)
181
+ io.binmode
182
+ content = io.read
183
+ @stylesheets << Stylesheet.new(content_type: content_type, content: content)
184
+ self
137
185
  end
138
186
  end
139
187
 
@@ -149,13 +197,14 @@ module FB2rb
149
197
  attr_accessor(:publish_info)
150
198
  # @return [Array<FB2rb::CustomInfo>]
151
199
  attr_accessor(:custom_infos)
200
+
152
201
  # TODO: <output>
153
202
 
154
- def initialize(title_info = TitleInfo.new,
155
- document_info = DocumentInfo.new,
156
- publish_info = nil,
157
- src_title_info = nil,
158
- custom_infos = [])
203
+ def initialize(title_info: TitleInfo.new,
204
+ document_info: DocumentInfo.new,
205
+ publish_info: nil,
206
+ src_title_info: nil,
207
+ custom_infos: [])
159
208
  @title_info = title_info
160
209
  @document_info = document_info
161
210
  @publish_info = publish_info
@@ -168,11 +217,11 @@ module FB2rb
168
217
  publish_info_xml = xml.at("./#{fb2_prefix}:publish-info")
169
218
  src_title_info_xml = xml.at("./#{fb2_prefix}:src-title-info")
170
219
  Description.new(
171
- TitleInfo.parse(xml.at("./#{fb2_prefix}:title-info"), fb2_prefix, xlink_prefix),
172
- DocumentInfo.parse(xml.at("./#{fb2_prefix}:document-info"), fb2_prefix),
173
- publish_info_xml.nil? ? nil : PublishInfo.parse(publish_info_xml, fb2_prefix),
174
- src_title_info_xml.nil? ? nil : TitleInfo.parse(src_title_info_xml, fb2_prefix, xlink_prefix),
175
- xml.xpath("./#{fb2_prefix}:custom-info").map do |node|
220
+ title_info: TitleInfo.parse(xml.at("./#{fb2_prefix}:title-info"), fb2_prefix, xlink_prefix),
221
+ document_info: DocumentInfo.parse(xml.at("./#{fb2_prefix}:document-info"), fb2_prefix),
222
+ publish_info: publish_info_xml.nil? ? nil : PublishInfo.parse(publish_info_xml, fb2_prefix),
223
+ src_title_info: src_title_info_xml.nil? ? nil : TitleInfo.parse(src_title_info_xml, fb2_prefix, xlink_prefix),
224
+ custom_infos: xml.xpath("./#{fb2_prefix}:custom-info").map do |node|
176
225
  CustomInfo.parse(node)
177
226
  end
178
227
  )
@@ -194,47 +243,47 @@ module FB2rb
194
243
  # Holds <stylesheet> data
195
244
  class Stylesheet
196
245
  # @return [String]
197
- attr_accessor(:type)
246
+ attr_accessor(:content_type)
198
247
  # @return [String, nil]
199
248
  attr_accessor(:content)
200
249
 
201
- def initialize(type = '', content = nil)
202
- @type = type
250
+ def initialize(content_type: '', content: nil)
251
+ @content_type = content_type
203
252
  @content = content
204
253
  end
205
254
 
206
255
  def self.parse(xml)
207
- Stylesheet.new(xml['type'], xml.text)
256
+ Stylesheet.new(content_type: xml['type'], content: xml.text)
208
257
  end
209
258
 
210
259
  def to_xml(xml)
211
260
  return if @content.nil?
212
261
 
213
- xml.send('stylesheet', @content, 'type' => @type)
262
+ xml.send('stylesheet', @content, 'type' => @content_type)
214
263
  end
215
264
  end
216
265
 
217
266
  # Holds <custom-info> data
218
267
  class CustomInfo
219
268
  # @return [String]
220
- attr_accessor(:info_type)
269
+ attr_accessor(:type)
221
270
  # @return [String, nil]
222
271
  attr_accessor(:content)
223
272
 
224
- def initialize(info_type = '', content = nil)
225
- @info_type = info_type
273
+ def initialize(type: '', content: nil)
274
+ @type = type
226
275
  @content = content
227
276
  end
228
277
 
229
278
  # @return [FB2rb::CustomInfo]
230
279
  def self.parse(xml)
231
- CustomInfo.new(xml['info-type'], xml.text)
280
+ CustomInfo.new(type: xml['info-type'], content: xml.text)
232
281
  end
233
282
 
234
283
  def to_xml(xml)
235
284
  return if @content.nil?
236
285
 
237
- xml.send('custom-info', @content, 'info-type' => @info_type)
286
+ xml.send('custom-info', @content, 'info-type' => @type)
238
287
  end
239
288
  end
240
289
 
@@ -253,12 +302,12 @@ module FB2rb
253
302
  # @return [Array<FB2RB::Sequence>]
254
303
  attr_accessor(:sequences)
255
304
 
256
- def initialize(book_name = nil, # rubocop:disable Metrics/ParameterLists
257
- publisher = nil,
258
- city = nil,
259
- year = nil,
260
- isbn = nil,
261
- sequences = [])
305
+ def initialize(book_name: nil, # rubocop:disable Metrics/ParameterLists
306
+ publisher: nil,
307
+ city: nil,
308
+ year: nil,
309
+ isbn: nil,
310
+ sequences: [])
262
311
  @book_name = book_name
263
312
  @publisher = publisher
264
313
  @city = city
@@ -270,12 +319,12 @@ module FB2rb
270
319
  # @return [FB2RB::PublishInfo]
271
320
  def self.parse(xml, fb2_prefix)
272
321
  PublishInfo.new(
273
- xml.at("./#{fb2_prefix}:book-name/text()")&.text,
274
- xml.at("./#{fb2_prefix}:publisher/text()")&.text,
275
- xml.at("./#{fb2_prefix}:city/text()")&.text,
276
- xml.at("./#{fb2_prefix}:year/text()")&.text,
277
- xml.at("./#{fb2_prefix}:isbn/text()")&.text,
278
- xml.xpath("./#{fb2_prefix}:sequence").map do |node|
322
+ book_name: xml.at("./#{fb2_prefix}:book-name/text()")&.text,
323
+ publisher: xml.at("./#{fb2_prefix}:publisher/text()")&.text,
324
+ city: xml.at("./#{fb2_prefix}:city/text()")&.text,
325
+ year: xml.at("./#{fb2_prefix}:year/text()")&.text,
326
+ isbn: xml.at("./#{fb2_prefix}:isbn/text()")&.text,
327
+ sequences: xml.xpath("./#{fb2_prefix}:sequence").map do |node|
279
328
  Sequence.parse(node)
280
329
  end
281
330
  )
@@ -316,15 +365,15 @@ module FB2rb
316
365
  # @return [Array<String>]
317
366
  attr_accessor(:publishers)
318
367
 
319
- def initialize(authors = [], # rubocop:disable Metrics/ParameterLists
320
- program_used = nil,
321
- date = FB2Date.new,
322
- src_urls = [],
323
- src_ocr = nil,
324
- id = '',
325
- version = '',
326
- history = nil,
327
- publishers = [])
368
+ def initialize(authors: [], # rubocop:disable Metrics/ParameterLists
369
+ program_used: nil,
370
+ date: FB2Date.new,
371
+ src_urls: [],
372
+ src_ocr: nil,
373
+ id: '',
374
+ version: '',
375
+ history: nil,
376
+ publishers: [])
328
377
  @authors = authors
329
378
  @program_used = program_used
330
379
  @date = date
@@ -337,20 +386,20 @@ module FB2rb
337
386
  end
338
387
 
339
388
  # @return [FB2rb::DocumentInfo]
340
- def self.parse(xml, fb2_prefix) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
389
+ def self.parse(xml, fb2_prefix) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
341
390
  date = xml.at("./#{fb2_prefix}:date")
342
391
  DocumentInfo.new(
343
- xml.xpath("./#{fb2_prefix}:author").map do |node|
392
+ authors: xml.xpath("./#{fb2_prefix}:author").map do |node|
344
393
  Author.parse(node, fb2_prefix)
345
394
  end,
346
- xml.at("./#{fb2_prefix}:program-used")&.text,
347
- date.nil? ? FB2Date.new : FB2Date.parse(date),
348
- xml.xpath("./#{fb2_prefix}:src-url").map(&:text),
349
- xml.at("./#{fb2_prefix}:src-ocr")&.text,
350
- xml.at("./#{fb2_prefix}:id").text,
351
- xml.at("./#{fb2_prefix}:version")&.text,
352
- xml.at("./#{fb2_prefix}:history")&.children&.to_s&.strip,
353
- xml.xpath("./#{fb2_prefix}:publisher").map(&:text)
395
+ program_used: xml.at("./#{fb2_prefix}:program-used")&.text,
396
+ date: date.nil? ? FB2Date.new : FB2Date.parse(date),
397
+ src_urls: xml.xpath("./#{fb2_prefix}:src-url").map(&:text),
398
+ src_ocr: xml.at("./#{fb2_prefix}:src-ocr")&.text,
399
+ id: xml.at("./#{fb2_prefix}:id").text,
400
+ version: xml.at("./#{fb2_prefix}:version")&.text,
401
+ history: xml.at("./#{fb2_prefix}:history")&.children&.to_s&.strip,
402
+ publishers: xml.xpath("./#{fb2_prefix}:publisher").map(&:text)
354
403
  )
355
404
  end
356
405
 
@@ -391,7 +440,7 @@ module FB2rb
391
440
  attr_accessor(:annotation)
392
441
  # @return [Array<String>]
393
442
  attr_accessor(:keywords)
394
- # @return [String, nil]
443
+ # @return [FB2rb::Date, nil]
395
444
  attr_accessor(:date)
396
445
  # @return [FB2rb::Coverpage, nil]
397
446
  attr_accessor(:coverpage)
@@ -404,17 +453,17 @@ module FB2rb
404
453
  # @return [Array<FB2rb::Sequence>]
405
454
  attr_accessor(:sequences)
406
455
 
407
- def initialize(genres = [], # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
408
- authors = [],
409
- book_title = '',
410
- annotation = nil,
411
- keywords = [],
412
- date = nil,
413
- coverpage = nil,
414
- lang = 'en',
415
- src_lang = nil,
416
- translators = [],
417
- sequences = [])
456
+ def initialize(genres: [], # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
457
+ authors: [],
458
+ book_title: '',
459
+ annotation: nil,
460
+ keywords: [],
461
+ date: nil,
462
+ coverpage: nil,
463
+ lang: 'en',
464
+ src_lang: nil,
465
+ translators: [],
466
+ sequences: [])
418
467
  @genres = genres
419
468
  @authors = authors
420
469
  @book_title = book_title
@@ -429,31 +478,31 @@ module FB2rb
429
478
  end
430
479
 
431
480
  # @return [FB2rb::TitleInfo]
432
- def self.parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
481
+ def self.parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
433
482
  date = xml.at("./#{fb2_prefix}:date")
434
483
  coverpage = xml.at("./#{fb2_prefix}:coverpage")
435
484
  TitleInfo.new(
436
- xml.xpath("./#{fb2_prefix}:genre/text()").map(&:text),
437
- xml.xpath("./#{fb2_prefix}:author").map do |node|
485
+ genres: xml.xpath("./#{fb2_prefix}:genre/text()").map(&:text),
486
+ authors: xml.xpath("./#{fb2_prefix}:author").map do |node|
438
487
  Author.parse(node, fb2_prefix)
439
488
  end,
440
- xml.at("./#{fb2_prefix}:book-title/text()")&.text,
441
- xml.at("./#{fb2_prefix}:annotation")&.children.to_s.strip,
442
- xml.at("./#{fb2_prefix}:keywords/text()")&.text&.split(', ') || [],
443
- date.nil? ? nil : FB2Date.parse(date),
444
- coverpage.nil? ? nil : Coverpage.parse(coverpage, fb2_prefix, xlink_prefix),
445
- xml.at("./#{fb2_prefix}:lang/text()").text,
446
- xml.at("./#{fb2_prefix}:src-lang/text()")&.text,
447
- xml.xpath("./#{fb2_prefix}:translator").map do |node|
489
+ book_title: xml.at("./#{fb2_prefix}:book-title/text()")&.text,
490
+ annotation: xml.at("./#{fb2_prefix}:annotation")&.children.to_s.strip,
491
+ keywords: xml.at("./#{fb2_prefix}:keywords/text()")&.text&.split(', ') || [],
492
+ date: date.nil? ? nil : FB2Date.parse(date),
493
+ coverpage: coverpage.nil? ? nil : Coverpage.parse(coverpage, fb2_prefix, xlink_prefix),
494
+ lang: xml.at("./#{fb2_prefix}:lang/text()").text,
495
+ src_lang: xml.at("./#{fb2_prefix}:src-lang/text()")&.text,
496
+ translators: xml.xpath("./#{fb2_prefix}:translator").map do |node|
448
497
  Author.parse(node, fb2_prefix)
449
498
  end,
450
- xml.xpath("./#{fb2_prefix}:sequence").map do |node|
499
+ sequences: xml.xpath("./#{fb2_prefix}:sequence").map do |node|
451
500
  Sequence.parse(node)
452
501
  end
453
502
  )
454
503
  end
455
504
 
456
- def to_xml(xml, tag) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
505
+ def to_xml(xml, tag) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
457
506
  xml.send(tag) do
458
507
  genres.each do |genre|
459
508
  xml.genre(genre)
@@ -487,13 +536,13 @@ module FB2rb
487
536
  # @return [Array<String>]
488
537
  attr_accessor(:images)
489
538
 
490
- def initialize(images = [])
539
+ def initialize(images: [])
491
540
  @images = images
492
541
  end
493
542
 
494
543
  def self.parse(xml, fb2_prefix, xlink_prefix)
495
544
  Coverpage.new(
496
- xml.xpath("./#{fb2_prefix}:image/@#{xlink_prefix}:href").map(&:to_s)
545
+ images: xml.xpath("./#{fb2_prefix}:image/@#{xlink_prefix}:href").map(&:to_s)
497
546
  )
498
547
  end
499
548
 
@@ -513,7 +562,7 @@ module FB2rb
513
562
  # @return [Date, nil]
514
563
  attr_accessor(:value)
515
564
 
516
- def initialize(display_value = '', value = nil)
565
+ def initialize(display_value: '', value: nil)
517
566
  @display_value = display_value
518
567
  @value = value
519
568
  end
@@ -521,8 +570,8 @@ module FB2rb
521
570
  def self.parse(xml)
522
571
  value = xml['value']
523
572
  FB2Date.new(
524
- xml.at('./text()')&.text || '',
525
- value.nil? ? nil : Date.parse(value)
573
+ display_value: xml.at('./text()')&.text || '',
574
+ value: value.nil? ? nil : Date.parse(value)
526
575
  )
527
576
  end
528
577
 
@@ -540,14 +589,14 @@ module FB2rb
540
589
  # @return [Integer, nil]
541
590
  attr_accessor(:number)
542
591
 
543
- def initialize(name = '', number = nil)
592
+ def initialize(name: '', number: nil)
544
593
  @name = name
545
594
  @number = number
546
595
  end
547
596
 
548
597
  # @return [FB2rb::Sequence]
549
598
  def self.parse(xml)
550
- Sequence.new(xml['name'], xml['number']&.to_i)
599
+ Sequence.new(name: xml['name'], number: xml['number']&.to_i)
551
600
  end
552
601
 
553
602
  def to_xml(xml)
@@ -574,13 +623,13 @@ module FB2rb
574
623
  # @return [String, nil]
575
624
  attr_accessor(:id)
576
625
 
577
- def initialize(first_name = nil, # rubocop:disable Metrics/ParameterLists
578
- middle_name = nil,
579
- last_name = nil,
580
- nickname = nil,
581
- home_pages = [],
582
- emails = [],
583
- id = nil)
626
+ def initialize(first_name: nil, # rubocop:disable Metrics/ParameterLists
627
+ middle_name: nil,
628
+ last_name: nil,
629
+ nickname: nil,
630
+ home_pages: [],
631
+ emails: [],
632
+ id: nil)
584
633
  @first_name = first_name
585
634
  @middle_name = middle_name
586
635
  @last_name = last_name
@@ -593,17 +642,17 @@ module FB2rb
593
642
  # @return [FB2rb::Author]
594
643
  def self.parse(xml, fb2_prefix) # rubocop:disable Metrics/CyclomaticComplexity
595
644
  Author.new(
596
- xml.at("./#{fb2_prefix}:first-name/text()")&.text,
597
- xml.at("./#{fb2_prefix}:middle-name/text()")&.text,
598
- xml.at("./#{fb2_prefix}:last-name/text()")&.text,
599
- xml.at("./#{fb2_prefix}:nickname/text()")&.text,
600
- xml.xpath("./#{fb2_prefix}:home-page/text()").map(&:text),
601
- xml.xpath("./#{fb2_prefix}:email/text()").map(&:text),
602
- xml.at("./#{fb2_prefix}:id/text()")&.text
645
+ first_name: xml.at("./#{fb2_prefix}:first-name/text()")&.text,
646
+ middle_name: xml.at("./#{fb2_prefix}:middle-name/text()")&.text,
647
+ last_name: xml.at("./#{fb2_prefix}:last-name/text()")&.text,
648
+ nickname: xml.at("./#{fb2_prefix}:nickname/text()")&.text,
649
+ home_pages: xml.xpath("./#{fb2_prefix}:home-page/text()").map(&:text),
650
+ emails: xml.xpath("./#{fb2_prefix}:email/text()").map(&:text),
651
+ id: xml.at("./#{fb2_prefix}:id/text()")&.text
603
652
  )
604
653
  end
605
654
 
606
- def to_xml(xml, tag) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
655
+ def to_xml(xml, tag) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
607
656
  xml.send(tag) do
608
657
  xml.send('first-name', @first_name) unless @first_name.nil?
609
658
  xml.send('middle-name', @middle_name) unless @middle_name.nil?
@@ -627,7 +676,7 @@ module FB2rb
627
676
  # @return [String]
628
677
  attr_accessor(:content)
629
678
 
630
- def initialize(name = nil, content = '')
679
+ def initialize(name: nil, content: '')
631
680
  @name = name
632
681
  @content = content
633
682
  end
@@ -635,8 +684,8 @@ module FB2rb
635
684
  # @return [FB2rb::Body]
636
685
  def self.parse(xml)
637
686
  Body.new(
638
- xml['name'],
639
- xml.children.to_s.strip
687
+ name: xml['name'],
688
+ content: xml.children.to_s.strip
640
689
  )
641
690
  end
642
691
 
@@ -659,7 +708,7 @@ module FB2rb
659
708
  # @return [String, nil]
660
709
  attr_accessor(:content_type)
661
710
 
662
- def initialize(id, content, content_type = nil)
711
+ def initialize(id: nil, content: ''.b, content_type: nil)
663
712
  @id = id
664
713
  @content = content
665
714
  @content_type = content_type
@@ -667,7 +716,7 @@ module FB2rb
667
716
 
668
717
  def self.parse(xml)
669
718
  decoded = Base64.decode64(xml.text)
670
- Binary.new(xml['id'], decoded, xml['content-type'])
719
+ Binary.new(id: xml['id'], content: decoded, content_type: xml['content-type'])
671
720
  end
672
721
 
673
722
  def to_xml(xml)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FB2rb
4
- VERSION = '0.1.1'
4
+ VERSION = '0.5.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fb2rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marat Radchenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-23 00:00:00.000000000 Z
11
+ date: 2020-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -58,42 +58,56 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 3.9.0
61
+ version: 3.10.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 3.9.0
68
+ version: 3.10.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.88.0
75
+ version: 1.5.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.88.0
82
+ version: 1.5.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.5.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.5.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rubocop-rspec
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 1.42.0
103
+ version: 2.0.0
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 1.42.0
110
+ version: 2.0.0
97
111
  description:
98
112
  email:
99
113
  - marat@slonopotamus.org
@@ -139,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
153
  - !ruby/object:Gem::Version
140
154
  version: '0'
141
155
  requirements: []
142
- rubygems_version: 3.1.2
156
+ rubygems_version: 3.1.4
143
157
  signing_key:
144
158
  specification_version: 4
145
159
  summary: Fiction Book 2 parser/generator library