fb2rb 0.2.1 → 0.3.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/CHANGELOG.adoc +4 -0
- data/README.adoc +19 -1
- data/lib/fb2rb.rb +73 -41
- data/lib/fb2rb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc31542e10b2b534c4a4ffd960f6155eebee2c06a8fe5d5527739a653a7be68d
|
4
|
+
data.tar.gz: 9863b69c7c307de46f4e5c15389c2b9934818c2a0b2bf4f3ee9126e015277b94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1366e3268dc0711bc00eeb7936fba94dfd9f6ad29f497eaed56e9ddf4aff188bd5270e1c552ebfe80fefa2053ab5f39f186d1499e19c3b29edfd181ef3f7edba
|
7
|
+
data.tar.gz: 7edd5ad64f31355bd5f014855a8e49d2c5264495ef42e144f978ce4e8fc962e7de04b838ead0688a0ef81a64d9b7229f74ade2887b4f758ed78a29ff93b66f01
|
data/CHANGELOG.adoc
CHANGED
@@ -7,6 +7,10 @@
|
|
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.3.0 (2020-07-27) - @slonopotamus
|
11
|
+
|
12
|
+
* Support reading/writing uncompressed FB2. https://github.com/slonopotamus/fb2rb/issues/5[#5]
|
13
|
+
|
10
14
|
== 0.2.1 (2020-07-24) - @slonopotamus
|
11
15
|
|
12
16
|
* Fix field annotation on `FB2rb::TitleInfo::date`
|
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/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]
|
@@ -29,40 +29,65 @@ module FB2rb
|
|
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
|
44
46
|
end
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
# Reads existing uncompressed FB2 file from an IO object, and creates new Book object.
|
49
|
+
# @return [FB2rb::Book]
|
50
|
+
def read_uncompressed(filename_or_io)
|
51
|
+
xml = read_xml(filename_or_io)
|
52
|
+
fb2_prefix = ns_prefix(FB2rb::FB2_NAMESPACE, xml.namespaces)
|
53
|
+
xlink_prefix = ns_prefix(FB2rb::XLINK_NAMESPACE, xml.namespaces)
|
54
|
+
parse(xml, fb2_prefix, xlink_prefix)
|
55
|
+
end
|
51
56
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
def ns_prefix(namespace, namespaces)
|
58
|
+
prefix = namespaces.key(namespace)
|
59
|
+
prefix.nil? ? nil : prefix.sub(/^xmlns:/, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# @return [FB2rb::Book]
|
65
|
+
def parse(xml, fb2_prefix, xlink_prefix) # rubocop:disable Metrics/MethodLength
|
66
|
+
Book.new(
|
67
|
+
Description.parse(
|
68
|
+
xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:description"), fb2_prefix, xlink_prefix
|
69
|
+
),
|
70
|
+
xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:body").map do |node|
|
71
|
+
Body.parse(node)
|
72
|
+
end,
|
73
|
+
xml.xpath("#{fb2_prefix}:FictionBook/#{fb2_prefix}:binary").map do |node|
|
74
|
+
Binary.parse(node)
|
75
|
+
end,
|
76
|
+
xml.xpath("/#{fb2_prefix}:FictionBook/#{fb2_prefix}:stylesheet").map do |node|
|
77
|
+
Stylesheet.parse(node)
|
78
|
+
end
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
def read_xml(filename_or_io)
|
83
|
+
if filename_or_io.respond_to? :read
|
84
|
+
Nokogiri::XML::Document.parse(filename_or_io)
|
85
|
+
else
|
86
|
+
File.open(filename_or_io, 'rb') do |io|
|
87
|
+
return Nokogiri::XML::Document.parse(io)
|
88
|
+
end
|
64
89
|
end
|
65
|
-
|
90
|
+
end
|
66
91
|
end
|
67
92
|
|
68
93
|
def to_xml(xml) # rubocop:disable Metrics/MethodLength
|
@@ -91,8 +116,8 @@ module FB2rb
|
|
91
116
|
end
|
92
117
|
end
|
93
118
|
|
94
|
-
# Writes FB2 to file or IO object. If file exists, it will be overwritten.
|
95
|
-
def
|
119
|
+
# Writes compressed FB2 to file or IO object. If file exists, it will be overwritten.
|
120
|
+
def write_compressed(filename_or_io = StringIO.new)
|
96
121
|
if filename_or_io.respond_to?(:write)
|
97
122
|
Zip::OutputStream.write_buffer(filename_or_io) do |zos|
|
98
123
|
write_to_zip(zos)
|
@@ -104,6 +129,22 @@ module FB2rb
|
|
104
129
|
end
|
105
130
|
end
|
106
131
|
|
132
|
+
# Writes FB2 (uncompressed) to file or IO object specified by the argument.
|
133
|
+
def write_uncompressed(filename_or_io = StringIO.new) # rubocop:disable Metrics/MethodLength
|
134
|
+
data = (Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
135
|
+
to_xml(xml)
|
136
|
+
end).to_xml
|
137
|
+
|
138
|
+
if filename_or_io.respond_to?(:write)
|
139
|
+
filename_or_io.write(data)
|
140
|
+
else
|
141
|
+
File.open(filename_or_io, 'wb') do |io|
|
142
|
+
io.write(data)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
filename_or_io
|
146
|
+
end
|
147
|
+
|
107
148
|
private
|
108
149
|
|
109
150
|
def write_to_zip(zos)
|
@@ -115,7 +156,7 @@ module FB2rb
|
|
115
156
|
# TODO: entry name
|
116
157
|
mimetype_entry = Zip::Entry.new(nil, 'book.fb2', nil, nil, nil, nil, nil, nil, mod_time)
|
117
158
|
zos.put_next_entry(mimetype_entry, nil, nil, Zip::Entry::DEFLATED)
|
118
|
-
|
159
|
+
write_uncompressed(zos)
|
119
160
|
end
|
120
161
|
|
121
162
|
def add_binary_io(name, io, content_type = nil)
|
@@ -124,15 +165,6 @@ module FB2rb
|
|
124
165
|
@binaries << Binary.new(name, content, content_type)
|
125
166
|
self
|
126
167
|
end
|
127
|
-
|
128
|
-
# Writes FB2 (uncompressed) to stream specified by the argument.
|
129
|
-
def write_to_stream(io)
|
130
|
-
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
131
|
-
to_xml(xml)
|
132
|
-
end
|
133
|
-
xml = builder.to_xml
|
134
|
-
io.write(xml)
|
135
|
-
end
|
136
168
|
end
|
137
169
|
|
138
170
|
# Holds <description> data
|
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.3.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-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|