rss-opds 0.0.2 → 0.0.3
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 +7 -0
- data/LICENSE +1 -1
- data/README.markdown +12 -0
- data/examples/build-catalog-from-epub.rb +62 -0
- data/examples/opds_server.ru +81 -0
- data/lib/rss/maker/opds.rb +77 -39
- data/lib/rss/opds.rb +1 -4
- data/lib/rss/opds/version.rb +1 -1
- data/rss-opds.gemspec +1 -1
- data/test/fixtures/root.opds +41 -0
- data/test/test_maker.rb +33 -2
- metadata +80 -57
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '09d755c74c4f44e54bd8a8c4edb7109f2afde6cb15678dc4d5150e24209def54'
|
4
|
+
data.tar.gz: aa8f11cc5bdb0f6146c2f77af3197f0bdde028f0b8fbae9cb5b17be43d0e9dd9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 82345f798acbb3e5baa066c3c48db0679ce8ff40fffbd51423aa80d6949e1729aee996f6be058beadc53278209d32f234ed15c035672374330e9e0c56021da58
|
7
|
+
data.tar.gz: df102e1fa2609affe6c4be21209785fc739f6c8772bb896ef32d42f072d65c382ff8c3d50c81808bcb7500748d405b39c048ed87e9b02e56b9fb153edff702ed
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -94,6 +94,18 @@ And now, this library provides utility methods which help you make OPDS navigati
|
|
94
94
|
}
|
95
95
|
puts root # => output XML including entry with 'new' sorting relation
|
96
96
|
|
97
|
+
Examples
|
98
|
+
--------
|
99
|
+
For more examples, see files in `examples` directory.
|
100
|
+
|
101
|
+
Changelog
|
102
|
+
---------
|
103
|
+
### 0.0.3
|
104
|
+
* Add sample script 'examples/build-catalog-from-epub.rb' which build OPDS catalog feed using specified EPUB files
|
105
|
+
* Add sample server 'examples/opds_server.ru' for Rack
|
106
|
+
* Remove Money from dependencies
|
107
|
+
* [BUG FIX]Add element component to XPath
|
108
|
+
|
97
109
|
Contributing
|
98
110
|
------------
|
99
111
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# This is an example that aggregates info from EPUB files and build OPDS catalog feed using them
|
2
|
+
#
|
3
|
+
# Usage:
|
4
|
+
# ruby examples/build-catalog-from-epub.rb EPUBFILE
|
5
|
+
# ruby examples/build-catalog-from-epub.rb ~/Documents/Books/*.epub
|
6
|
+
|
7
|
+
require 'rss'
|
8
|
+
require 'rss/opds'
|
9
|
+
require 'rss/maker/opds'
|
10
|
+
require 'epub/parser' # You need to exec 'gem install epub-parser' if you don't have it
|
11
|
+
|
12
|
+
def main
|
13
|
+
if ARGV.empty?
|
14
|
+
puts "Usage: ruby #{File.basename($0)} EPUBFILE [EPUBFILE ...]"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
puts make_catalog(ARGV)
|
19
|
+
end
|
20
|
+
|
21
|
+
def make_catalog(files)
|
22
|
+
RSS::Maker.make 'atom' do |maker|
|
23
|
+
maker.channel.about = 'http://example.net/'
|
24
|
+
maker.channel.title = 'My EPUB books'
|
25
|
+
maker.channel.description = 'This is an example to make OPDS catalog using RSS::OPDS library'
|
26
|
+
maker.channel.links.new_link do |link|
|
27
|
+
link.href = 'http://example.net/'
|
28
|
+
link.rel = RSS::OPDS::RELATIONS['self']
|
29
|
+
link.type = RSS::OPDS::TYPES['navigation']
|
30
|
+
end
|
31
|
+
maker.channel.links.new_link do |link|
|
32
|
+
link.href = 'http://example.net/'
|
33
|
+
link.rel = RSS::OPDS::RELATIONS['start']
|
34
|
+
link.type = RSS::OPDS::TYPES['navigation']
|
35
|
+
end
|
36
|
+
maker.channel.author = `whoami`.chomp
|
37
|
+
maker.channel.generator = 'RSS OPDS the Ruby OPDS library'
|
38
|
+
maker.channel.updated = Time.now
|
39
|
+
|
40
|
+
files.sort.each do |file|
|
41
|
+
begin
|
42
|
+
make_entry(file, maker)
|
43
|
+
rescue => error
|
44
|
+
$stderr.puts error
|
45
|
+
$stderr.puts "skip: #{file}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def make_entry(file, maker)
|
52
|
+
book = EPUB::Parser.parse(file)
|
53
|
+
maker.items.new_item do |entry|
|
54
|
+
entry.id = book.metadata.unique_identifier.content
|
55
|
+
entry.title = book.title
|
56
|
+
entry.summary = book.metadata.description
|
57
|
+
updated = book.metadata.date
|
58
|
+
entry.updated = updated ? updated.content : File.mtime(file)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
main
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# Usage
|
2
|
+
# $ DOCUMENT_ROOT=path/to/doc/root rackup examples/opds_server.ru
|
3
|
+
#
|
4
|
+
# If required gems are not installed, you need exec:
|
5
|
+
# $ gem install rack epub-parser
|
6
|
+
require 'pathname'
|
7
|
+
require 'rack'
|
8
|
+
require 'epub/parser'
|
9
|
+
require 'rss/maker/opds'
|
10
|
+
|
11
|
+
class OPDSServer
|
12
|
+
OPTIONS = {
|
13
|
+
:title => 'My EPUB Books',
|
14
|
+
:description => 'This is an example server that serves OPDS includeing information of EPUB files in a directory.',
|
15
|
+
:author => `whoami`.chomp,
|
16
|
+
:generator => self.to_s
|
17
|
+
}
|
18
|
+
|
19
|
+
def initialize(dir='.', options={})
|
20
|
+
raise "Document root not given. Usage: DOCUMENT_ROOT=path/to/docroot rackup #{__FILE__}" unless dir
|
21
|
+
@dir = Pathname(dir)
|
22
|
+
raise "Not a directory: #{dir}" unless @dir.directory?
|
23
|
+
@options = OPTIONS.merge(options)
|
24
|
+
$stderr.puts "Providing OPDS for EPUB files in #{@dir}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(env)
|
28
|
+
@files = Pathname.glob("#{@dir}/**/*.epub")
|
29
|
+
@last_modified = @files.collect(&:mtime).max
|
30
|
+
|
31
|
+
@request = Rack::Request.new(env)
|
32
|
+
response = Rack::Response.new
|
33
|
+
|
34
|
+
if_modifed_since = env['HTTP_IF_MODIFIED_SINCE']
|
35
|
+
if if_modifed_since and @last_modified.to_s <= Time.httpdate(if_modifed_since).to_s
|
36
|
+
response.status = Rack::Utils.status_code(:not_modified)
|
37
|
+
elsif !@request.head?
|
38
|
+
response.body << make_feed.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
response['Content-Type'] = RSS::OPDS::TYPES['navigation']
|
42
|
+
response['Last-Modified'] = @last_modified.httpdate
|
43
|
+
response.finish
|
44
|
+
end
|
45
|
+
|
46
|
+
def make_feed
|
47
|
+
RSS::Maker.make('atom') {|maker|
|
48
|
+
maker.channel.about = @options[:about] || @request.url
|
49
|
+
OPTIONS.keys.each do |attr|
|
50
|
+
maker.channel.send "#{attr}=", @options[attr]
|
51
|
+
end
|
52
|
+
maker.channel.updated = @last_modified
|
53
|
+
@files.each do |path|
|
54
|
+
begin
|
55
|
+
book = EPUB::Parser.parse(path)
|
56
|
+
maker.items.new_item do |entry|
|
57
|
+
entry.id = book.unique_identifier.content
|
58
|
+
entry.title = book.title
|
59
|
+
entry.summary = book.description
|
60
|
+
uri_path = path.relative_path_from(@dir)
|
61
|
+
entry.links.new_link do |link|
|
62
|
+
link.rel = RSS::OPDS::RELATIONS['acquisition']
|
63
|
+
link.href = @request.base_url + '/' + ERB::Util.url_encode(uri_path.to_path)
|
64
|
+
link.type = 'application/epub+zip'
|
65
|
+
end
|
66
|
+
updated = Time.parse(book.date.content) rescue nil
|
67
|
+
entry.updated = updated || path.mtime
|
68
|
+
end
|
69
|
+
rescue => error
|
70
|
+
$stderr.puts error
|
71
|
+
$stderr.puts "Skip: #{path}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
docroot = ENV['DOCUMENT_ROOT']
|
79
|
+
run Rack::Cascade.new(
|
80
|
+
[Rack::File.new(docroot),
|
81
|
+
OPDSServer.new(docroot)])
|
data/lib/rss/maker/opds.rb
CHANGED
@@ -3,51 +3,63 @@ require 'rss/opds'
|
|
3
3
|
|
4
4
|
module RSS
|
5
5
|
module Maker
|
6
|
-
module
|
7
|
-
|
8
|
-
class
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
6
|
+
module OPDS
|
7
|
+
module LinkBase
|
8
|
+
class << self
|
9
|
+
def included(base)
|
10
|
+
super
|
11
|
+
base.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
12
|
+
%w[facetGroup activeFacet].each do |attr|
|
13
|
+
def_other_element attr
|
14
|
+
end
|
15
|
+
def_classed_elements 'opds_price', 'value', 'Prices'
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# @note Defined to prevent NoMethodError
|
18
|
+
def setup_opds_prices(feed, current)
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
def to_feed(feed, current)
|
22
|
+
super # AtomLink#to_feed
|
23
|
+
opds_prices.to_feed(feed, current.links.last)
|
24
|
+
end
|
25
|
+
EOC
|
26
|
+
end
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
class Prices < Base
|
30
|
+
def_array_element 'opds_price', nil, 'Price'
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
class Price < Base
|
33
|
+
%w[value currencycode].each do |attr|
|
34
|
+
attr_accessor attr
|
35
|
+
end
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
def to_feed(feed, current)
|
38
|
+
price = ::RSS::OPDS::Price.new
|
39
|
+
price.value = value
|
40
|
+
price.currencycode = currencycode
|
41
|
+
current.opds_prices << price
|
42
|
+
set_parent price, current
|
43
|
+
setup_other_elements(feed)
|
44
|
+
end
|
43
45
|
|
44
|
-
|
46
|
+
private
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
def required_variable_names
|
49
|
+
%w[currencycode]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Atom
|
57
|
+
class Feed < RSSBase
|
58
|
+
class Items < ItemsBase
|
59
|
+
class Item < ItemBase
|
60
|
+
class Links < LinksBase
|
61
|
+
class Link < LinkBase
|
62
|
+
include OPDS::LinkBase
|
51
63
|
end
|
52
64
|
end
|
53
65
|
end
|
@@ -58,16 +70,42 @@ module RSS
|
|
58
70
|
raise TypeError, 'Only navigatfion feed can accept feed' unless is_navigation_feed
|
59
71
|
raise ArgumentError, 'Only acquisition feed can be accepted' unless feed.acquisition_feed?
|
60
72
|
new_item do |entry|
|
61
|
-
[:id, :title, :dc_description, :updated].each do |attr|
|
73
|
+
[:id, :title, :dc_description, :updated, :rights].each do |attr|
|
62
74
|
val = feed.__send__(attr)
|
63
75
|
entry.__send__("#{attr}=", val.content) if val
|
64
76
|
end
|
77
|
+
[:author, :contributor].each do |attr_name|
|
78
|
+
plural ||= "#{attr_name}s"
|
79
|
+
feed.__send__(plural).each do |val|
|
80
|
+
entry.__send__(plural).__send__("new_#{attr_name}") do |attr_maker|
|
81
|
+
[:name, :uri, :email].each do |elem|
|
82
|
+
attr_val = val.__send__(elem)
|
83
|
+
attr_maker.__send__("#{elem}=", attr_val)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
feed.categories.each do |cat|
|
89
|
+
entry.categories.new_category do |cat_maker|
|
90
|
+
[:term, :scheme, :label].each do |xml_attr|
|
91
|
+
val = cat.__send__(xml_attr)
|
92
|
+
cat_maker.__send__("#{xml_attr}=", val)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
entry.content.content ||= feed.dc_description || feed.title.content
|
97
|
+
|
65
98
|
entry.links.new_link do |link|
|
66
99
|
href = feed.links.find {|ln| ln.rel == RSS::OPDS::RELATIONS['self']}.href unless href
|
67
100
|
link.href = href
|
68
101
|
link.rel = relation
|
69
102
|
link.type = RSS::OPDS::TYPES['acquisition']
|
103
|
+
link.title = feed.title.content
|
104
|
+
link.hreflang = feed.lang || feed.dc_language
|
105
|
+
# Skip "length" attribute because it is for "enclosure" relation and maybe feed here doesn't have it.
|
70
106
|
end
|
107
|
+
|
108
|
+
entry
|
71
109
|
end
|
72
110
|
end
|
73
111
|
|
data/lib/rss/opds.rb
CHANGED
@@ -158,10 +158,7 @@ module RSS
|
|
158
158
|
'image' => 'http://opds-spec.org/image',
|
159
159
|
'thumbnail' => 'http://opds-spec.org/image/thumbnail'
|
160
160
|
}
|
161
|
-
RELATIONS =
|
162
|
-
ENTRY_RELATIONS[k] or CATALOG_RELATIONS[k] or REGISTERED_RELATIONS[k] or
|
163
|
-
raise KeyError, "Unsupported relation type: #{k.inspect}"
|
164
|
-
}
|
161
|
+
RELATIONS = [REGISTERED_RELATIONS, CATALOG_RELATIONS, ENTRY_RELATIONS].reduce({}) {|merged, relations| merged.merge(relations)}
|
165
162
|
|
166
163
|
class Price < Element
|
167
164
|
include Atom::CommonModel
|
data/lib/rss/opds/version.rb
CHANGED
data/rss-opds.gemspec
CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
|
19
19
|
gem.add_runtime_dependency 'rss-dcterms'
|
20
20
|
gem.add_runtime_dependency 'rss-atom-feed_history'
|
21
|
-
gem.add_runtime_dependency 'money'
|
22
21
|
|
22
|
+
gem.add_development_dependency 'rake'
|
23
23
|
gem.add_development_dependency 'test-unit'
|
24
24
|
gem.add_development_dependency 'simplecov'
|
25
25
|
gem.add_development_dependency 'yard'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom"
|
3
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
4
|
+
xmlns:dcterms="http://purl.org/dc/terms/"
|
5
|
+
xmlns:opds="http://opds-spec.org/2010/catalog">
|
6
|
+
<author>
|
7
|
+
<name>KITAITI Makoto</name>
|
8
|
+
</author>
|
9
|
+
<id>http://example.net/</id>
|
10
|
+
<link href="http://example.net/root.opds"
|
11
|
+
rel="self"
|
12
|
+
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
13
|
+
<link href="http://example.net/root.opds"
|
14
|
+
rel="start"
|
15
|
+
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
16
|
+
<subtitle>Sample OPDS</subtitle>
|
17
|
+
<title>Example Catalog Root</title>
|
18
|
+
<updated>2012-08-14T04:23:00+09:00</updated>
|
19
|
+
<entry>
|
20
|
+
<id>http://example.net/popular.opds</id>
|
21
|
+
<link href="http://example.net/popular.opds"
|
22
|
+
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
23
|
+
<summary>Popular books in this site</summary>
|
24
|
+
<title>Example Popular Books</title>
|
25
|
+
<updated>2012-07-31T00:00:00+09:00</updated>
|
26
|
+
<dc:date>2012-07-31T00:00:00+09:00</dc:date>
|
27
|
+
<dcterms:date>2012-07-31T00:00:00+09:00</dcterms:date>
|
28
|
+
</entry>
|
29
|
+
<entry>
|
30
|
+
<id>http://example.net/new.opds</id>
|
31
|
+
<link href="http://example.net/new.opds"
|
32
|
+
type="application/atom+xml;profile=opds-catalog;kind=acquisition"/>
|
33
|
+
<summary>New books in this site</summary>
|
34
|
+
<title>Example New Books</title>
|
35
|
+
<updated>2012-08-14T04:23:00+09:00</updated>
|
36
|
+
<dc:date>2012-08-14T04:23:00+09:00</dc:date>
|
37
|
+
<dcterms:date>2012-08-14T04:23:00+09:00</dcterms:date>
|
38
|
+
</entry>
|
39
|
+
<dc:date>2012-08-14T04:23:00+09:00</dc:date>
|
40
|
+
<dcterms:date>2012-08-14T04:23:00+09:00</dcterms:date>
|
41
|
+
</feed>
|
data/test/test_maker.rb
CHANGED
@@ -48,7 +48,7 @@ class TestMaker < TestOPDS
|
|
48
48
|
end
|
49
49
|
}
|
50
50
|
doc = REXML::Document.new(feed.to_s)
|
51
|
-
links = REXML::XPath.match(doc, "
|
51
|
+
links = REXML::XPath.match(doc, "//*[@opds:activeFacet]")
|
52
52
|
assert_not_empty links
|
53
53
|
assert_equal 'true', links.first.attributes['opds:activeFacet']
|
54
54
|
end
|
@@ -73,7 +73,7 @@ class TestMaker < TestOPDS
|
|
73
73
|
end
|
74
74
|
}
|
75
75
|
doc = REXML::Document.new(feed.to_s)
|
76
|
-
assert_empty REXML::XPath.match(doc, "
|
76
|
+
assert_empty REXML::XPath.match(doc, "//*[@opds:activeFacet]")
|
77
77
|
end
|
78
78
|
|
79
79
|
def test_navigation_feed_accepts_aqcuisition_feed_as_item
|
@@ -106,6 +106,35 @@ class TestMaker < TestOPDS
|
|
106
106
|
assert_equal 'http://opds-spec.org/sort/popular', links[1].attributes['rel']
|
107
107
|
end
|
108
108
|
|
109
|
+
def test_add_relation_returns_item
|
110
|
+
catalog_root = nil
|
111
|
+
assert_nothing_raised do
|
112
|
+
catalog_root = RSS::Maker.make('atom') {|maker|
|
113
|
+
maker.channel.about = 'http://example.net/'
|
114
|
+
maker.channel.title = 'Example Catalog Root'
|
115
|
+
maker.channel.description = 'Sample OPDS'
|
116
|
+
maker.channel.links.new_link do |link|
|
117
|
+
link.href = 'http://example.net/root.opds'
|
118
|
+
link.rel = RSS::OPDS::RELATIONS['self']
|
119
|
+
link.type = RSS::OPDS::TYPES['navigation']
|
120
|
+
end
|
121
|
+
maker.channel.links.new_link do |link|
|
122
|
+
link.href = 'http://example.net/root.opds'
|
123
|
+
link.rel = RSS::OPDS::RELATIONS['start']
|
124
|
+
link.type = RSS::OPDS::TYPES['navigation']
|
125
|
+
end
|
126
|
+
maker.channel.updated = '2012-08-14T05:30:00'
|
127
|
+
maker.channel.author = 'KITAITI Makoto'
|
128
|
+
|
129
|
+
entry = maker.items.add_relation recent, RSS::OPDS::RELATIONS['new']
|
130
|
+
entry.content.content = 'Overwritten entry content'
|
131
|
+
}
|
132
|
+
end
|
133
|
+
doc = REXML::Document.new(catalog_root.to_s)
|
134
|
+
links = REXML::XPath.match(doc, "/feed/entry/content")
|
135
|
+
assert_equal 'Overwritten entry content', links.first.text
|
136
|
+
end
|
137
|
+
|
109
138
|
def test_utility_to_add_entry_relations
|
110
139
|
pend
|
111
140
|
end
|
@@ -183,6 +212,7 @@ class TestMaker < TestOPDS
|
|
183
212
|
def recent
|
184
213
|
RSS::Maker.make('atom') do |maker|
|
185
214
|
maker.channel.about = 'http://example.net/'
|
215
|
+
maker.channel.language = 'en'
|
186
216
|
maker.channel.title = 'Example New Catalog'
|
187
217
|
maker.channel.description = 'New books in this site'
|
188
218
|
maker.channel.links.new_link do |link|
|
@@ -197,6 +227,7 @@ class TestMaker < TestOPDS
|
|
197
227
|
end
|
198
228
|
maker.channel.updated = '2012-08-14T04:23:00'
|
199
229
|
maker.channel.author = 'KITAITI Makoto'
|
230
|
+
maker.channel.rights = 'Copyright (c) 2012, KITAITI Makoto'
|
200
231
|
|
201
232
|
new_books.each do |book|
|
202
233
|
maker.items.new_item do |entry|
|
metadata
CHANGED
@@ -1,115 +1,141 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rss-opds
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- KITAITI Makoto
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2019-03-23 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rss-dcterms
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: rss-atom-feed_history
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - ">="
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :runtime
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement:
|
39
|
-
none: false
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
|
-
- -
|
45
|
+
- - ">="
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '0'
|
44
|
-
type: :
|
48
|
+
type: :development
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
47
55
|
- !ruby/object:Gem::Dependency
|
48
56
|
name: test-unit
|
49
|
-
requirement:
|
50
|
-
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
51
58
|
requirements:
|
52
|
-
- -
|
59
|
+
- - ">="
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '0'
|
55
62
|
type: :development
|
56
63
|
prerelease: false
|
57
|
-
version_requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: simplecov
|
60
|
-
requirement:
|
61
|
-
none: false
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
62
72
|
requirements:
|
63
|
-
- -
|
73
|
+
- - ">="
|
64
74
|
- !ruby/object:Gem::Version
|
65
75
|
version: '0'
|
66
76
|
type: :development
|
67
77
|
prerelease: false
|
68
|
-
version_requirements:
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: yard
|
71
|
-
requirement:
|
72
|
-
none: false
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
73
86
|
requirements:
|
74
|
-
- -
|
87
|
+
- - ">="
|
75
88
|
- !ruby/object:Gem::Version
|
76
89
|
version: '0'
|
77
90
|
type: :development
|
78
91
|
prerelease: false
|
79
|
-
version_requirements:
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
80
97
|
- !ruby/object:Gem::Dependency
|
81
98
|
name: redcarpet
|
82
|
-
requirement:
|
83
|
-
none: false
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
84
100
|
requirements:
|
85
|
-
- -
|
101
|
+
- - ">="
|
86
102
|
- !ruby/object:Gem::Version
|
87
103
|
version: '0'
|
88
104
|
type: :development
|
89
105
|
prerelease: false
|
90
|
-
version_requirements:
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
91
111
|
- !ruby/object:Gem::Dependency
|
92
112
|
name: pry
|
93
|
-
requirement:
|
94
|
-
none: false
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
95
114
|
requirements:
|
96
|
-
- -
|
115
|
+
- - ">="
|
97
116
|
- !ruby/object:Gem::Version
|
98
117
|
version: '0'
|
99
118
|
type: :development
|
100
119
|
prerelease: false
|
101
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
102
125
|
- !ruby/object:Gem::Dependency
|
103
126
|
name: pry-doc
|
104
|
-
requirement:
|
105
|
-
none: false
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
106
128
|
requirements:
|
107
|
-
- -
|
129
|
+
- - ">="
|
108
130
|
- !ruby/object:Gem::Version
|
109
131
|
version: '0'
|
110
132
|
type: :development
|
111
133
|
prerelease: false
|
112
|
-
version_requirements:
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
113
139
|
description: OPDS parser and maker
|
114
140
|
email:
|
115
141
|
- KitaitiMakoto@gmail.com
|
@@ -117,48 +143,45 @@ executables: []
|
|
117
143
|
extensions: []
|
118
144
|
extra_rdoc_files: []
|
119
145
|
files:
|
120
|
-
- .gitignore
|
146
|
+
- ".gitignore"
|
121
147
|
- Gemfile
|
122
148
|
- LICENSE
|
123
149
|
- README.markdown
|
124
150
|
- Rakefile
|
151
|
+
- examples/build-catalog-from-epub.rb
|
125
152
|
- examples/make-catalog.rb
|
153
|
+
- examples/opds_server.ru
|
126
154
|
- lib/rss/maker/opds.rb
|
127
155
|
- lib/rss/opds.rb
|
128
156
|
- lib/rss/opds/version.rb
|
129
157
|
- rss-opds.gemspec
|
130
158
|
- setup.rb
|
159
|
+
- test/fixtures/root.opds
|
131
160
|
- test/helper.rb
|
132
161
|
- test/test_maker.rb
|
133
162
|
homepage: http://rss-ext.rubyforge.org/
|
134
163
|
licenses: []
|
164
|
+
metadata: {}
|
135
165
|
post_install_message:
|
136
166
|
rdoc_options: []
|
137
167
|
require_paths:
|
138
168
|
- lib
|
139
169
|
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
-
none: false
|
141
170
|
requirements:
|
142
|
-
- -
|
171
|
+
- - ">="
|
143
172
|
- !ruby/object:Gem::Version
|
144
173
|
version: '0'
|
145
|
-
segments:
|
146
|
-
- 0
|
147
|
-
hash: -1275098366759959895
|
148
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
-
none: false
|
150
175
|
requirements:
|
151
|
-
- -
|
176
|
+
- - ">="
|
152
177
|
- !ruby/object:Gem::Version
|
153
178
|
version: '0'
|
154
|
-
segments:
|
155
|
-
- 0
|
156
|
-
hash: -1275098366759959895
|
157
179
|
requirements: []
|
158
|
-
|
159
|
-
rubygems_version: 1.8.8
|
180
|
+
rubygems_version: 3.0.3
|
160
181
|
signing_key:
|
161
|
-
specification_version:
|
182
|
+
specification_version: 4
|
162
183
|
summary: This gem extends Ruby bundled RSS library to parse and make OPDS catalogs
|
163
|
-
test_files:
|
164
|
-
|
184
|
+
test_files:
|
185
|
+
- test/fixtures/root.opds
|
186
|
+
- test/helper.rb
|
187
|
+
- test/test_maker.rb
|