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 +4 -4
- data/.github/dependabot.yml +5 -0
- data/.github/workflows/release.yml +3 -9
- data/CHANGELOG.adoc +24 -1
- data/README.adoc +19 -1
- data/fb2rb.gemspec +4 -3
- data/lib/fb2rb.rb +203 -154
- data/lib/fb2rb/version.rb +1 -1
- metadata +23 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3232aa66bba2be36e9f72b67c198a6b2e1b8e13d2cb51746264b44daaab9c60e
|
4
|
+
data.tar.gz: 00c679822965363b7ffade747f1898f9d5a687c408cab6240afa8ac150108593
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7684b0249c15f2ca45fd209df32b6dae4f52192d0aa2cf17fff9c63c83666bbec7c1c7aafc5c4055e87a13f2967113056a81d94c5bc490448897a61f73695255
|
7
|
+
data.tar.gz: 9e93f45e0567bac65cdf97b9c18d2912b869d5a605d228e1bf667e58739a915a092d5623b6b385fe844817e337457444bca74580ebdb9bcd5720dcaef6af304a
|
data/.github/dependabot.yml
CHANGED
@@ -13,12 +13,6 @@ jobs:
|
|
13
13
|
with:
|
14
14
|
ruby-version: 2.7
|
15
15
|
- name: Publish to RubyGems.org
|
16
|
-
|
17
|
-
|
18
|
-
|
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 }}
|
data/CHANGELOG.adoc
CHANGED
@@ -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
|
-
*
|
35
|
+
* Annotate field types
|
13
36
|
* Fix serialization of `<publisher>` in `<document-info>`
|
14
37
|
|
15
38
|
== 0.1.0 (2020-07-23) - @slonopotamus
|
data/README.adoc
CHANGED
@@ -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.
|
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
|
data/fb2rb.gemspec
CHANGED
@@ -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.
|
26
|
-
s.add_development_dependency 'rubocop', '~>
|
27
|
-
s.add_development_dependency 'rubocop-
|
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
|
data/lib/fb2rb.rb
CHANGED
@@ -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
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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(
|
110
|
+
def add_binary(id, filename_or_io, content_type = nil)
|
85
111
|
if filename_or_io.respond_to?(:read)
|
86
|
-
add_binary_io
|
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
|
115
|
+
add_binary_io id, io, content_type
|
90
116
|
end
|
91
117
|
end
|
92
118
|
end
|
93
119
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
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
|
-
|
120
|
-
|
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(
|
173
|
+
def add_binary_io(id, io, content_type = nil)
|
124
174
|
io.binmode
|
125
175
|
content = io.read
|
126
|
-
@binaries << Binary.new(
|
176
|
+
@binaries << Binary.new(id: id, content: content, content_type: content_type)
|
127
177
|
self
|
128
178
|
end
|
129
179
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
155
|
-
document_info
|
156
|
-
publish_info
|
157
|
-
src_title_info
|
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(:
|
246
|
+
attr_accessor(:content_type)
|
198
247
|
# @return [String, nil]
|
199
248
|
attr_accessor(:content)
|
200
249
|
|
201
|
-
def initialize(
|
202
|
-
@
|
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' => @
|
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(:
|
269
|
+
attr_accessor(:type)
|
221
270
|
# @return [String, nil]
|
222
271
|
attr_accessor(:content)
|
223
272
|
|
224
|
-
def initialize(
|
225
|
-
@
|
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' => @
|
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
|
257
|
-
publisher
|
258
|
-
city
|
259
|
-
year
|
260
|
-
isbn
|
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
|
320
|
-
program_used
|
321
|
-
date
|
322
|
-
src_urls
|
323
|
-
src_ocr
|
324
|
-
id
|
325
|
-
version
|
326
|
-
history
|
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 [
|
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
|
408
|
-
authors
|
409
|
-
book_title
|
410
|
-
annotation
|
411
|
-
keywords
|
412
|
-
date
|
413
|
-
coverpage
|
414
|
-
lang
|
415
|
-
src_lang
|
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
|
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
|
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
|
578
|
-
middle_name
|
579
|
-
last_name
|
580
|
-
nickname
|
581
|
-
home_pages
|
582
|
-
emails
|
583
|
-
id
|
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/
|
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
|
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
|
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)
|
data/lib/fb2rb/version.rb
CHANGED
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.
|
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
|
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.
|
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.
|
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:
|
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:
|
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:
|
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:
|
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.
|
156
|
+
rubygems_version: 3.1.4
|
143
157
|
signing_key:
|
144
158
|
specification_version: 4
|
145
159
|
summary: Fiction Book 2 parser/generator library
|