fb2rb 0.1.1 → 0.5.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 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