feedstock 0.2.0 → 0.4.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/README.md +43 -166
- data/feedstock.gemspec +5 -2
- data/lib/feedstock/version.rb +1 -1
- data/lib/feedstock.rb +114 -106
- metadata +6 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1a02c229edb1b2d7c98904d6263aab47cfe5ef4d605c5a3c78ec412c1bb2083
|
4
|
+
data.tar.gz: f0c35d3a675eeb01cbbc73952b85f484df631459a1542161d2b198b8c3b1ccf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b31805cfc5c8aedaabf286f2a76b269df4883daf24850121a94edb349a219c1d7177e161df20a434d07b17eed3bd129c7529d94093559fc5520fe19bc0dc2b45
|
7
|
+
data.tar.gz: b47eac95bda32a4a5a7a7a4a904d4baeb6b1055a18e39f09d1d2ed38c1c7b0a6ab9d0672db4f614b210d5bb1969afbd3de962292d6ccf750895e00f6a4b13d6c
|
data/README.md
CHANGED
@@ -5,25 +5,30 @@
|
|
5
5
|
[gem-badge]: https://badge.fury.io/rb/feedstock.svg
|
6
6
|
[gem-link]: https://rubygems.org/gems/feedstock
|
7
7
|
|
8
|
-
Feedstock is a Ruby library for extracting information from
|
9
|
-
|
8
|
+
Feedstock is a Ruby library for extracting information from an HTML/XML document
|
9
|
+
and inserting it into an ERB template. Its primary purpose is to create a feed
|
10
|
+
for a webpage that doesn't offer one.
|
10
11
|
|
11
12
|
## Rationale
|
12
13
|
|
13
|
-
|
14
|
-
provide a feed for the specific content that you want. That's where Feedstock
|
15
|
-
can help.
|
14
|
+
I love RSS feeds.
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
That's why I think it's a shame not every website has a feed. However, even when
|
17
|
+
a website does have a feed, sometimes it doesn't include quite the mix
|
18
|
+
information that I want. I made Feedstock to solve those two problems.
|
19
|
+
|
20
|
+
Feedstock is a Ruby library that you can use to create an Atom or RSS feed. It
|
21
|
+
requires a URL to a document and a hash of rules. The rules tell Feedstock how
|
22
|
+
to extract and transform the data found on the webpage. That data is stuffed
|
23
|
+
into a hash and then run through an ERB template. Feedstock comes with a
|
24
|
+
template but you can use your own, too.
|
20
25
|
|
21
26
|
## Example
|
22
27
|
|
23
|
-
The [feeds.inqk.net repository][example] includes an example of how the
|
24
|
-
library can be used in practice.
|
28
|
+
The [feeds.inqk.net repository][example] includes an example of how the
|
29
|
+
Feedstock library can be used in practice.
|
25
30
|
|
26
|
-
[example]: https://github.com/pyrmont/feeds.inqk.net/
|
31
|
+
[example]: https://github.com/pyrmont/feeds.inqk.net/
|
27
32
|
"An example of using the Feedstock library"
|
28
33
|
|
29
34
|
## Installation
|
@@ -36,169 +41,42 @@ $ gem install feedstock
|
|
36
41
|
|
37
42
|
## Usage
|
38
43
|
|
39
|
-
Feedstock extracts information from a given
|
40
|
-
_rules_.
|
41
|
-
|
42
|
-
A collection of rules is expressed as a hash. The hash has two mandatory keys
|
43
|
-
and one optional key.
|
44
|
-
|
45
|
-
### Info
|
46
|
-
|
47
|
-
The `:info` key is mandatory. It must be associated with a hash. In this
|
48
|
-
README, this hash is referred to as the _info hash_.
|
49
|
-
|
50
|
-
#### Keys
|
51
|
-
|
52
|
-
The keys in the info hash should be symbols, not strings. When used with the
|
53
|
-
default template, Feedstock will use the key as the name of the XML entity in
|
54
|
-
the resulting feed. For example, if the key is `:id`, the XML entity in the
|
55
|
-
resulting feed will be `<id>`.
|
56
|
-
|
57
|
-
#### Values
|
58
|
-
|
59
|
-
The value associated with each key in the info hash can be either a string or a
|
60
|
-
hash.
|
61
|
-
|
62
|
-
##### String
|
63
|
-
|
64
|
-
If the value is a string, this defines a path to a node in the document. The
|
65
|
-
path is expressed using CSS's selector syntax. Although a CSS selector can match
|
66
|
-
more than one node, when used in the info hash, a path will only match the first
|
67
|
-
matching node in the document.
|
68
|
-
|
69
|
-
##### Hash
|
70
|
-
|
71
|
-
If the value is a hash, this is a _data hash_. A data hash defines the rules
|
72
|
-
that Feedstock uses to extract data. It must contain one of two keys:
|
73
|
-
|
74
|
-
- `:literal`: The value associated with this key is used for the content of the
|
75
|
-
XML entity. This can be useful for elements that are not on the page or that
|
76
|
-
don't change.
|
77
|
-
|
78
|
-
- `:path`: The path to the node in the document expressed in CSS's selector
|
79
|
-
syntax. As noted above, if the value of a key in the info hash is a string,
|
80
|
-
this is treated as a path. The reason to use a data hash with a `:path` key
|
81
|
-
is when using one or more of the keys below. In the info hash, a path matches
|
82
|
-
only the first matching node in the document.
|
83
|
-
|
84
|
-
The following keys may also be defined in a data hash:
|
85
|
-
|
86
|
-
- `:content`: The default is `nil`. The `:content` key can be set to
|
87
|
-
`"inner_html"` or a _hash_ of the form `{attribute: "<attribute>"}`. If the
|
88
|
-
value is `"inner_html"`, Feedstock will extract the content of the node as
|
89
|
-
HTML. If the value is an attribute hash, Feedstock will extract the value of
|
90
|
-
that attribute. This is important for links, where the link itself is
|
91
|
-
typically the content of the `href` attribute rather than the content of the
|
92
|
-
`<a>` element. For all other values, the plaintext content of the node is
|
93
|
-
extracted.
|
94
|
-
|
95
|
-
- `:processor`: The default is `nil`. The `:processor` key can be set to a
|
96
|
-
lambda function that takes two arguments. The first is the extracted content,
|
97
|
-
the second is the rule being processed. The content extracted by Feedstock for
|
98
|
-
the given path is processed by the processor.
|
99
|
-
|
100
|
-
- `:prefix`: The default is `nil`. If a prefix is provided, the string value of
|
101
|
-
the prefix is appended to the beginning of the content extracted.
|
102
|
-
|
103
|
-
- `:suffix`: The default is `nil`. If a suffix is provided, the string value of
|
104
|
-
the suffix is appended to the end of the content extracted.
|
105
|
-
|
106
|
-
- `:type`: The default is `nil`. A user may specify `"datetime"` or `"cdata"`.
|
107
|
-
If the value is `"datetime"`, the content is parsed by the [Timeliness
|
108
|
-
library][Timeliness] to return a string. If the value is `"cdata"`, the
|
109
|
-
content is wrapped in `<![CDATA[` and `]]>` tags.
|
44
|
+
Feedstock extracts information from a document at a given _URL_ using a
|
45
|
+
collection of _rules_. The feed is generated by calling `Feedstock.feed` as
|
46
|
+
below:
|
110
47
|
|
111
|
-
|
112
|
-
the
|
48
|
+
```ruby
|
49
|
+
# Define the URL
|
50
|
+
url = "https://example.org"
|
113
51
|
|
114
|
-
|
52
|
+
# Define the rules
|
53
|
+
rules = { info: { id: url,
|
54
|
+
title: Feedstock::Extract.new(selector: "div.title"),
|
55
|
+
updated: Feedstock::Extract.new(selector: "span.date") },
|
115
56
|
|
116
|
-
|
57
|
+
entry: { id: Feedstock::Extract.new(selector: "a", content: { attribute: "href" }),
|
58
|
+
title: Feedstock::Extract.new(selector: "h2"),
|
59
|
+
updated: Feedstock::Extract.new(selector: "span.date"),
|
60
|
+
author: Feedstock::Extract.new(selector: "span.byline"),
|
61
|
+
link: Feedstock::Extract.new(selector: "a", content: { attribute: "href" }),
|
62
|
+
summary: Feedstock::Extract.new(selector: "div.summary") },
|
117
63
|
|
118
|
-
|
64
|
+
entries: Feedstock::Extract.new(selector: "div.story") }
|
119
65
|
|
120
|
-
|
121
|
-
|
66
|
+
# Using the default format and template
|
67
|
+
Feedstock.feed url, rules
|
122
68
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
default template, Feedstock will use the key as the name of the XML entity in
|
127
|
-
the resulting feed. For example, if the key is `"id"`, the XML entity in the
|
128
|
-
resulting feed will be `<id>`.
|
129
|
-
|
130
|
-
#### Values
|
131
|
-
|
132
|
-
The value associated with each key in the entry hash can be either a string or a
|
133
|
-
hash.
|
134
|
-
|
135
|
-
##### String
|
136
|
-
|
137
|
-
If the value is a string, this defines a path to a node in the document. The
|
138
|
-
path is expressed using CSS's selector syntax. Unlike with the info hash, a
|
139
|
-
the CSS selector will match all nodes.
|
140
|
-
|
141
|
-
##### Hash
|
142
|
-
|
143
|
-
If the value is a hash, this is a _data hash_. A data hash defines the
|
144
|
-
rules that Feedstock uses to extract data. It must contain one of two keys:
|
145
|
-
|
146
|
-
- `:literal`: The value associated with this key is used for the content of the
|
147
|
-
XML entity. This can be useful for elements that are not on the page or that
|
148
|
-
don't change.
|
149
|
-
|
150
|
-
- `:path`: The path to the node in the document expressed in CSS's selector
|
151
|
-
syntax. Unlike with the info hash, the CSS selector will match all nodes.
|
152
|
-
|
153
|
-
The following keys may also be defined in a data hash:
|
154
|
-
|
155
|
-
- `:content`: The default is `nil`. The `:content` key can be set to
|
156
|
-
`"inner_html"` or a _hash_ of the form `{attribute: "<attribute>"}`. If the
|
157
|
-
value is `"inner_html"`, Feedstock will extract the content of the node as
|
158
|
-
HTML. If the value is an attribute hash, Feedstock will extract the value of
|
159
|
-
that attribute. This is important for links, where the link itself is
|
160
|
-
typically the content of the `href` attribute rather than the content of the
|
161
|
-
`<a>` element. For all other values, the plaintext content of the node is
|
162
|
-
extracted.
|
163
|
-
|
164
|
-
- `:repeat`: The default is `nil`. If repeat is set to `true`, Feedstock will
|
165
|
-
use the content provided by either `:literal` or `:path` repeatedly. Since
|
166
|
-
the value of `:literal` implies `:repeat`, it is not necessary to specify it
|
167
|
-
expressly.
|
168
|
-
|
169
|
-
- `:processor`: The default is `nil`. The `:processor` key can be set to a
|
170
|
-
lambda function that takes two arguments. The first is the extracted content,
|
171
|
-
the second is the rule being processed. The content extracted by Feedstock for
|
172
|
-
the given path is processed by the processor.
|
173
|
-
|
174
|
-
- `:prefix`: The default is `nil`. If a prefix is provided, the string value of
|
175
|
-
the prefix is appended to the beginning of the content extracted.
|
176
|
-
|
177
|
-
- `:suffix`: The default is `nil`. If a suffix is provided, the string value of
|
178
|
-
the suffix is appended to the end of the content extracted.
|
179
|
-
|
180
|
-
- `:type`: The default is `nil`. A user may specify `"datetime"` or `"cdata"`.
|
181
|
-
If the value is `"datetime"`, the content is parsed by the [Timeliness
|
182
|
-
library][Timeliness] to return a string. If the value is `"cdata"`, the
|
183
|
-
content is wrapped in `<![CDATA[` and `]]>` tags.
|
184
|
-
|
185
|
-
### Entries
|
186
|
-
|
187
|
-
The `:entries` key is optional. It can be associated with a hash. In this
|
188
|
-
README, this hash is referred to as the _entries hash_.
|
189
|
-
|
190
|
-
The entries hash is offered as a convenience. It allows a user to simplify
|
191
|
-
the paths used in the entry hash by omitting a reference to the node
|
192
|
-
containing the entries.
|
69
|
+
# Using the XML format and a user-specified template
|
70
|
+
Feedstock.feed url, rules, :xml, "podcast.xml"
|
71
|
+
```
|
193
72
|
|
194
|
-
|
73
|
+
More information is available in [api.md].
|
195
74
|
|
196
|
-
|
197
|
-
syntax. This path is used as the root for the paths in the entry hash.
|
75
|
+
[api.md]: https://github.com/pyrmont/feedstock/blob/master/api.md
|
198
76
|
|
199
77
|
## Bugs
|
200
78
|
|
201
|
-
Found a bug? I'd love to know about it. The best way is to report
|
79
|
+
Found a bug? I'd love to know about it. The best way is to report it in the
|
202
80
|
[Issues section][ghi] on GitHub.
|
203
81
|
|
204
82
|
[ghi]: https://github.com/pyrmont/feedstock/issues
|
@@ -211,7 +89,6 @@ Feedstock uses [Semantic Versioning 2.0.0][sv2].
|
|
211
89
|
|
212
90
|
## Licence
|
213
91
|
|
214
|
-
Feedstock is released into the public domain. See [LICENSE
|
215
|
-
details.
|
92
|
+
Feedstock is released into the public domain. See [LICENSE][] for more details.
|
216
93
|
|
217
|
-
[
|
94
|
+
[LICENSE]: https://github.com/pyrmont/feedstock/blob/master/LICENSE
|
data/feedstock.gemspec
CHANGED
@@ -9,12 +9,15 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["mike@inqk.net"]
|
10
10
|
s.summary = "A library for creating RSS feeds from webpages"
|
11
11
|
s.description = <<-desc.strip.gsub(/\s+/, " ")
|
12
|
-
Feedstock is a library for extracting information from
|
13
|
-
|
12
|
+
Feedstock is a Ruby library for extracting information from an HTML/XML
|
13
|
+
document and inserting it into an ERB template.
|
14
14
|
desc
|
15
15
|
s.homepage = "https://github.com/pyrmont/feedstock/"
|
16
16
|
s.licenses = "Unlicense"
|
17
17
|
s.required_ruby_version = ">= 2.7"
|
18
|
+
s.metadata = {
|
19
|
+
"documentation_uri" => "https://github.com/pyrmont/feedstock/blob/v0.3.0/api.md"
|
20
|
+
}
|
18
21
|
|
19
22
|
s.files = Dir["Gemfile", "default.xml", "LICENSE", "README.md",
|
20
23
|
"feedstock.gemspec", "lib/feedstock.rb", "lib/**/*.rb"]
|
data/lib/feedstock/version.rb
CHANGED
data/lib/feedstock.rb
CHANGED
@@ -6,148 +6,156 @@ require "open-uri"
|
|
6
6
|
require "timeliness"
|
7
7
|
|
8
8
|
module Feedstock
|
9
|
-
|
10
|
-
|
11
|
-
page = download_page url
|
12
|
-
info = extract_info page, rules
|
13
|
-
entries = extract_entries page, rules
|
14
|
-
feed = create_feed info, entries, template_file
|
15
|
-
|
16
|
-
feed
|
17
|
-
end
|
9
|
+
class Extract < Struct.new("Extract", :selector, :absolute, :content, :processor, :prefix,
|
10
|
+
:suffix, :type, :filter, keyword_init: true); end
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
12
|
+
class << self
|
13
|
+
def data(url, rules, format = :html)
|
14
|
+
page = download_page url, format
|
23
15
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
16
|
+
info = extract_info page, rules
|
17
|
+
entries = extract_entries page, rules
|
27
18
|
|
28
|
-
|
29
|
-
if rules[:entries]
|
30
|
-
extract_entries_wrapped page, rules
|
31
|
-
else
|
32
|
-
extract_entries_unwrapped page, rules
|
19
|
+
{ info: info, entries: entries }
|
33
20
|
end
|
34
|
-
end
|
35
21
|
|
36
|
-
|
37
|
-
|
38
|
-
|
22
|
+
def feed(url, rules, format = :html, template_file = "#{__dir__}/../default.xml")
|
23
|
+
info, entries = data(url, rules, format).values_at(:info, :entries)
|
24
|
+
|
25
|
+
create_feed info, entries, template_file
|
26
|
+
end
|
27
|
+
|
28
|
+
private def create_feed(info, entries, template_file)
|
29
|
+
template = ERB.new File.read(template_file), trim_mode: "-"
|
30
|
+
template.result_with_hash info: info, entries: entries
|
31
|
+
end
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
33
|
+
private def download_page(url, format)
|
34
|
+
case format
|
35
|
+
when :html
|
36
|
+
Nokogiri::HTML URI.open(url)
|
37
|
+
when :xml
|
38
|
+
Nokogiri::XML URI.open(url)
|
45
39
|
else
|
46
|
-
|
47
|
-
entries[i] = Hash.new if entries[i].nil?
|
48
|
-
entries[i].merge!({ name.to_s => format_content(match, rule) })
|
49
|
-
end
|
40
|
+
raise "Format not recognised"
|
50
41
|
end
|
51
42
|
end
|
52
43
|
|
53
|
-
|
54
|
-
|
44
|
+
private def extract_content(node, rule)
|
45
|
+
case rule.content
|
46
|
+
in { attribute: attribute }
|
47
|
+
node[attribute]
|
48
|
+
in "inner_html"
|
49
|
+
node.inner_html
|
50
|
+
in "html" | "xml"
|
51
|
+
node.to_s
|
52
|
+
else
|
53
|
+
node.content.strip
|
54
|
+
end
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
|
-
|
57
|
+
private def extract_entries(page, rules)
|
58
|
+
if rules[:entries]
|
59
|
+
extract_entries_wrapped page, rules
|
60
|
+
else
|
61
|
+
extract_entries_unwrapped page, rules
|
62
|
+
end
|
63
|
+
end
|
59
64
|
|
60
|
-
|
61
|
-
|
65
|
+
private def extract_entries_unwrapped(page, rules)
|
66
|
+
static = Hash.new
|
67
|
+
entries = Array.new
|
62
68
|
|
63
|
-
page.css(rules[:entries][:path]).each.with_index do |node, i|
|
64
69
|
rules[:entry].each do |name, rule|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
if rule.is_a? String
|
71
|
+
static[name.to_s] = rule
|
72
|
+
elsif rule.absolute
|
73
|
+
static[name.to_s] = format_content page.at_css(rule.selector), rule
|
74
|
+
else
|
75
|
+
page.css(rule.selector).each.with_index do |match, i|
|
76
|
+
entries[i] = Hash.new if entries[i].nil?
|
77
|
+
entries[i].merge!({ name.to_s => format_content(match, rule) })
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
74
81
|
|
75
|
-
|
82
|
+
unless static.empty?
|
83
|
+
entries.each{ |entry| entry.merge!(static) }
|
76
84
|
end
|
85
|
+
|
86
|
+
entries
|
77
87
|
end
|
78
88
|
|
79
|
-
|
80
|
-
|
89
|
+
private def extract_entries_wrapped(page, rules)
|
90
|
+
entries = Array.new
|
81
91
|
|
82
|
-
|
83
|
-
|
92
|
+
page.css(rules[:entries].selector).each.with_index do |parent, i|
|
93
|
+
rules[:entry].each do |name, rule|
|
94
|
+
entries[i] = Hash.new if entries[i].nil?
|
84
95
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
96
|
+
content = if rule.is_a? String
|
97
|
+
rule
|
98
|
+
elsif rule.absolute
|
99
|
+
format_content page.at_css(rule.selector), rule
|
100
|
+
elsif rule.selector.empty?
|
101
|
+
format_content parent, rule
|
102
|
+
else
|
103
|
+
format_content parent.at_css(rule.selector), rule
|
104
|
+
end
|
105
|
+
|
106
|
+
entries[i].merge!({ name.to_s => content })
|
107
|
+
end
|
90
108
|
end
|
91
|
-
end
|
92
109
|
|
93
|
-
info
|
94
|
-
end
|
95
|
-
|
96
|
-
def self.format_content(match, rule)
|
97
|
-
return "" if match.nil?
|
98
110
|
|
99
|
-
|
100
|
-
processed = process_content text, rule
|
101
|
-
wrapped = wrap_content processed, rule
|
111
|
+
return entries unless rules[:entries].filter.is_a? Proc
|
102
112
|
|
103
|
-
|
104
|
-
when "cdata"
|
105
|
-
"<![CDATA[#{wrapped}]]>"
|
106
|
-
when "datetime"
|
107
|
-
"#{Timeliness.parse(wrapped)&.iso8601}"
|
108
|
-
else
|
109
|
-
wrapped
|
113
|
+
entries.filter(&rules[:entries].filter)
|
110
114
|
end
|
111
|
-
end
|
112
115
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
private def extract_info(page, rules)
|
117
|
+
info = Hash.new
|
118
|
+
|
119
|
+
rules[:info].each do |name, rule|
|
120
|
+
if rule.is_a? String
|
121
|
+
info[name.to_s] = rule
|
122
|
+
else
|
123
|
+
info[name.to_s] = format_content page.at_css(rule.selector), rule
|
119
124
|
end
|
120
|
-
when :entries
|
121
|
-
rule = rules[category]
|
122
|
-
rules[category] = { :path => rule } unless rule.is_a? Hash
|
123
125
|
end
|
126
|
+
|
127
|
+
info
|
124
128
|
end
|
125
129
|
|
126
|
-
|
127
|
-
|
130
|
+
private def format_content(match, rule)
|
131
|
+
return "" if match.nil?
|
132
|
+
|
133
|
+
text = extract_content match, rule
|
134
|
+
processed = process_content text, rule
|
135
|
+
wrapped = wrap_content processed, rule
|
128
136
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
+
case rule.type
|
138
|
+
when "cdata"
|
139
|
+
"<![CDATA[#{wrapped}]]>"
|
140
|
+
when "datetime"
|
141
|
+
"#{Timeliness.parse(wrapped)&.iso8601}"
|
142
|
+
else
|
143
|
+
wrapped
|
144
|
+
end
|
137
145
|
end
|
138
|
-
end
|
139
146
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
147
|
+
private def process_content(content, rule)
|
148
|
+
if rule.processor
|
149
|
+
rule.processor.call content, rule
|
150
|
+
else
|
151
|
+
content
|
152
|
+
end
|
145
153
|
end
|
146
|
-
end
|
147
154
|
|
148
|
-
|
149
|
-
|
155
|
+
private def wrap_content(content, rule)
|
156
|
+
return content unless (rule.prefix || rule.suffix)
|
150
157
|
|
151
|
-
|
158
|
+
"#{rule.prefix}#{content}#{rule.suffix}"
|
159
|
+
end
|
152
160
|
end
|
153
161
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feedstock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Camilleri
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-21 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: nokogiri
|
@@ -80,8 +79,8 @@ dependencies:
|
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
82
81
|
version: '0'
|
83
|
-
description: Feedstock is a library for extracting information from
|
84
|
-
|
82
|
+
description: Feedstock is a Ruby library for extracting information from an HTML/XML
|
83
|
+
document and inserting it into an ERB template.
|
85
84
|
email:
|
86
85
|
- mike@inqk.net
|
87
86
|
executables: []
|
@@ -99,8 +98,8 @@ homepage: https://github.com/pyrmont/feedstock/
|
|
99
98
|
licenses:
|
100
99
|
- Unlicense
|
101
100
|
metadata:
|
101
|
+
documentation_uri: https://github.com/pyrmont/feedstock/blob/v0.3.0/api.md
|
102
102
|
allowed_push_host: https://rubygems.org
|
103
|
-
post_install_message:
|
104
103
|
rdoc_options: []
|
105
104
|
require_paths:
|
106
105
|
- lib
|
@@ -115,8 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
114
|
- !ruby/object:Gem::Version
|
116
115
|
version: '0'
|
117
116
|
requirements: []
|
118
|
-
rubygems_version: 3.2
|
119
|
-
signing_key:
|
117
|
+
rubygems_version: 3.6.2
|
120
118
|
specification_version: 4
|
121
119
|
summary: A library for creating RSS feeds from webpages
|
122
120
|
test_files: []
|