feedstock 0.2.0 → 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/README.md +48 -171
- data/feedstock.gemspec +5 -2
- data/lib/feedstock.rb +121 -107
- data/lib/feedstock/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b478a8e9dd24f3ac78e99189c959b247828f7a2980a979cc320a3b6f8c5306d1
|
4
|
+
data.tar.gz: 957fb142e5abef9289ca92f40ecf6f7425106a40271da4967c80c27f2b69c4eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0895e3a795d26151fc74a79107e0873afe8f0d99fe955cc4fffd94342d335075852ae71abbbfc61d47a637fc06e00c73c17f0ad023e7a712e2dd5e015e393554'
|
7
|
+
data.tar.gz: b4ef2dbf847a910813d4187b71208c50f773613cca75173152ed6f9343b3de220c98917aa074060851c89e72433f14866cf16539cf357725f8f3c5587d406062
|
data/README.md
CHANGED
@@ -5,23 +5,28 @@
|
|
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
31
|
[example]: https://github.com/pyrmont/feeds.inqk.net/tree/4a95a438f8d3a707db7946238181ab76c029ee77/src/input
|
27
32
|
"An example of using the Feedstock library"
|
@@ -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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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.
|
110
|
-
|
111
|
-
[Timeliness]: https://github.com/adzap/timeliness "The official repository for
|
112
|
-
the Timeliness library"
|
113
|
-
|
114
|
-
#### Formatting Order
|
115
|
-
|
116
|
-
The order for formatting content is: extract, process, wrapping.
|
117
|
-
|
118
|
-
### Entry
|
119
|
-
|
120
|
-
The `:entry` key is mandatory. It must be associated with a hash. In this
|
121
|
-
README, this hash is referred to as the _entry hash_.
|
122
|
-
|
123
|
-
#### Keys
|
124
|
-
|
125
|
-
The keys in the entry hash should be symbols, not strings. When used with the
|
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.
|
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:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
# Define the URL
|
50
|
+
url = "https://example.org"
|
51
|
+
|
52
|
+
# Define the rules
|
53
|
+
rules = { info: { id: url,
|
54
|
+
title: "div.title",
|
55
|
+
updated: "span.date" },
|
56
|
+
entries: "div.story",
|
57
|
+
entry: { id: { path: "a",
|
58
|
+
content: { attribute: "href" } },
|
59
|
+
title: "h2",
|
60
|
+
updated: "span.date",
|
61
|
+
author: "span.byline",
|
62
|
+
link: { path: "a",
|
63
|
+
content: { attribute: "href" } },
|
64
|
+
summary: "div.summary" } }
|
65
|
+
|
66
|
+
# Using the default format and template
|
67
|
+
Feedstock.feed url, rules
|
68
|
+
|
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.rb
CHANGED
@@ -6,148 +6,162 @@ require "open-uri"
|
|
6
6
|
require "timeliness"
|
7
7
|
|
8
8
|
module Feedstock
|
9
|
-
|
10
|
-
rules
|
11
|
-
|
12
|
-
|
13
|
-
entries = extract_entries page, rules
|
14
|
-
feed = create_feed info, entries, template_file
|
15
|
-
|
16
|
-
feed
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.create_feed(info, entries, template_file)
|
20
|
-
template = ERB.new File.read(template_file), trim_mode: "-"
|
21
|
-
template.result_with_hash info: info, entries: entries
|
22
|
-
end
|
9
|
+
class << self
|
10
|
+
def feed(url, rules, format = :html, template_file = "#{__dir__}/../default.xml")
|
11
|
+
page = download_page url, format
|
12
|
+
rules = normalise_rules rules
|
23
13
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
14
|
+
info = extract_info page, rules
|
15
|
+
entries = extract_entries page, rules
|
27
16
|
|
28
|
-
|
29
|
-
if rules[:entries]
|
30
|
-
extract_entries_wrapped page, rules
|
31
|
-
else
|
32
|
-
extract_entries_unwrapped page, rules
|
17
|
+
create_feed info, entries, template_file
|
33
18
|
end
|
34
|
-
end
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
20
|
+
private def create_feed(info, entries, template_file)
|
21
|
+
template = ERB.new File.read(template_file), trim_mode: "-"
|
22
|
+
template.result_with_hash info: info, entries: entries
|
23
|
+
end
|
39
24
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
25
|
+
private def download_page(url, format)
|
26
|
+
case format
|
27
|
+
when :html
|
28
|
+
Nokogiri::HTML URI.open(url)
|
29
|
+
when :xml
|
30
|
+
Nokogiri::XML URI.open(url)
|
45
31
|
else
|
46
|
-
|
47
|
-
entries[i] = Hash.new if entries[i].nil?
|
48
|
-
entries[i].merge!({ name.to_s => format_content(match, rule) })
|
49
|
-
end
|
32
|
+
raise "Format not recognised"
|
50
33
|
end
|
51
34
|
end
|
52
35
|
|
53
|
-
|
54
|
-
|
36
|
+
private def extract_content(node, rule)
|
37
|
+
case rule[:content]
|
38
|
+
in { attribute: attribute }
|
39
|
+
node[attribute]
|
40
|
+
in "inner_html"
|
41
|
+
node.inner_html
|
42
|
+
in "html" | "xml"
|
43
|
+
node.to_s
|
44
|
+
else
|
45
|
+
node.content.strip
|
46
|
+
end
|
55
47
|
end
|
56
48
|
|
57
|
-
|
58
|
-
|
49
|
+
private def extract_entries(page, rules)
|
50
|
+
if rules[:entries]
|
51
|
+
extract_entries_wrapped page, rules
|
52
|
+
else
|
53
|
+
extract_entries_unwrapped page, rules
|
54
|
+
end
|
55
|
+
end
|
59
56
|
|
60
|
-
|
61
|
-
|
57
|
+
private def extract_entries_unwrapped(page, rules)
|
58
|
+
static = Hash.new
|
59
|
+
entries = Array.new
|
62
60
|
|
63
|
-
page.css(rules[:entries][:path]).each.with_index do |node, i|
|
64
61
|
rules[:entry].each do |name, rule|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
62
|
+
if rule[:literal]
|
63
|
+
static[name.to_s] = rule[:literal]
|
64
|
+
elsif rule[:repeat]
|
65
|
+
static[name.to_s] = format_content page.at_css(rule[:path]), rule
|
66
|
+
else
|
67
|
+
page.css(rule[:path]).each.with_index do |match, i|
|
68
|
+
entries[i] = Hash.new if entries[i].nil?
|
69
|
+
entries[i].merge!({ name.to_s => format_content(match, rule) })
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
74
73
|
|
75
|
-
|
74
|
+
unless static.empty?
|
75
|
+
entries.each{ |entry| entry.merge!(static) }
|
76
76
|
end
|
77
|
+
|
78
|
+
entries
|
77
79
|
end
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
+
private def extract_entries_wrapped(page, rules)
|
82
|
+
entries = Array.new
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
+
page.css(rules[:entries][:path]).each.with_index do |node, i|
|
85
|
+
rules[:entry].each do |name, rule|
|
86
|
+
entries[i] = Hash.new if entries[i].nil?
|
84
87
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
88
|
+
content = if rule[:literal]
|
89
|
+
rule[:literal]
|
90
|
+
elsif rule[:repeat]
|
91
|
+
format_content page.at_css(rule[:path]), rule
|
92
|
+
else
|
93
|
+
format_content node.at_css(rule[:path]), rule
|
94
|
+
end
|
92
95
|
|
93
|
-
|
94
|
-
|
96
|
+
entries[i].merge!({ name.to_s => content })
|
97
|
+
end
|
98
|
+
end
|
95
99
|
|
96
|
-
def self.format_content(match, rule)
|
97
|
-
return "" if match.nil?
|
98
100
|
|
99
|
-
|
100
|
-
processed = process_content text, rule
|
101
|
-
wrapped = wrap_content processed, rule
|
101
|
+
return entries unless rules[:entries][:filter].is_a? Proc
|
102
102
|
|
103
|
-
|
104
|
-
when "cdata"
|
105
|
-
"<![CDATA[#{wrapped}]]>"
|
106
|
-
when "datetime"
|
107
|
-
"#{Timeliness.parse(wrapped)&.iso8601}"
|
108
|
-
else
|
109
|
-
wrapped
|
103
|
+
entries.filter(&rules[:entries][:filter])
|
110
104
|
end
|
111
|
-
end
|
112
105
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
106
|
+
private def extract_info(page, rules)
|
107
|
+
info = Hash.new
|
108
|
+
|
109
|
+
rules[:info].each do |name, rule|
|
110
|
+
if rule[:literal]
|
111
|
+
info[name.to_s] = rule[:literal]
|
112
|
+
else
|
113
|
+
info[name.to_s] = format_content page.at_css(rule[:path]), rule
|
119
114
|
end
|
120
|
-
when :entries
|
121
|
-
rule = rules[category]
|
122
|
-
rules[category] = { :path => rule } unless rule.is_a? Hash
|
123
115
|
end
|
116
|
+
|
117
|
+
info
|
124
118
|
end
|
125
119
|
|
126
|
-
|
127
|
-
|
120
|
+
private def format_content(match, rule)
|
121
|
+
return "" if match.nil?
|
122
|
+
|
123
|
+
text = extract_content match, rule
|
124
|
+
processed = process_content text, rule
|
125
|
+
wrapped = wrap_content processed, rule
|
128
126
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
127
|
+
case rule[:type]
|
128
|
+
when "cdata"
|
129
|
+
"<![CDATA[#{wrapped}]]>"
|
130
|
+
when "datetime"
|
131
|
+
"#{Timeliness.parse(wrapped)&.iso8601}"
|
132
|
+
else
|
133
|
+
wrapped
|
134
|
+
end
|
137
135
|
end
|
138
|
-
end
|
139
136
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
137
|
+
private def normalise_rules(rules)
|
138
|
+
rules.keys.each do |category|
|
139
|
+
case category
|
140
|
+
when :info, :entry
|
141
|
+
rules[category].each do |name, rule|
|
142
|
+
rules[category][name] = { :path => rule } unless rule.is_a? Hash
|
143
|
+
end
|
144
|
+
when :entries
|
145
|
+
rule = rules[category]
|
146
|
+
rules[category] = { :path => rule } unless rule.is_a? Hash
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
rules
|
145
151
|
end
|
146
|
-
end
|
147
152
|
|
148
|
-
|
149
|
-
|
153
|
+
private def process_content(content, rule)
|
154
|
+
if rule[:processor]
|
155
|
+
rule[:processor].call content, rule
|
156
|
+
else
|
157
|
+
content
|
158
|
+
end
|
159
|
+
end
|
150
160
|
|
151
|
-
|
161
|
+
private def wrap_content(content, rule)
|
162
|
+
return content unless rule[:prepend] || rule[:append]
|
163
|
+
|
164
|
+
"#{rule[:prepend]}#{content}#{rule[:append]}"
|
165
|
+
end
|
152
166
|
end
|
153
167
|
end
|
data/lib/feedstock/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feedstock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Camilleri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -80,8 +80,8 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
description: Feedstock is a library for extracting information from
|
84
|
-
|
83
|
+
description: Feedstock is a Ruby library for extracting information from an HTML/XML
|
84
|
+
document and inserting it into an ERB template.
|
85
85
|
email:
|
86
86
|
- mike@inqk.net
|
87
87
|
executables: []
|
@@ -99,6 +99,7 @@ homepage: https://github.com/pyrmont/feedstock/
|
|
99
99
|
licenses:
|
100
100
|
- Unlicense
|
101
101
|
metadata:
|
102
|
+
documentation_uri: https://github.com/pyrmont/feedstock/blob/v0.3.0/api.md
|
102
103
|
allowed_push_host: https://rubygems.org
|
103
104
|
post_install_message:
|
104
105
|
rdoc_options: []
|