concerto_simple_rss 0.0.8 → 0.0.9
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27bcb6e184059a5cbae750cb4851cf0161e966e0
|
4
|
+
data.tar.gz: ff9e1a3d2da810814ae11b4d1bbd8f9e89433ac2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 506c01f6444c666f2a5756f81c5a2c205382216a09ad5a7a9a57c3f28d326d32d06c76973e04cb0d14032a07952dc00a00cfb21eb5170daaa17aec17be2d8130
|
7
|
+
data.tar.gz: 94afe471154677c38a7ef8af2205f91e2d62cb3ae1e8a5f4f6aa52f5fb23fcc05ef571d7497081067de1217a701e79a10c9fd985b7b0a3b7d67c4effb93c30d4
|
@@ -1,41 +1,51 @@
|
|
1
|
-
function
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
function toggleSimpleRssConditionalInputs() {
|
2
|
+
if ($('select#simple_rss_config_output_format').val() == 'xslt') {
|
3
|
+
$('div#simple_rss_maxitems').hide();
|
4
|
+
$('div#simple_rss_xslmarkup').show();
|
5
|
+
} else {
|
6
|
+
$('div#simple_rss_maxitems').show();
|
7
|
+
$('div#simple_rss_xslmarkup').hide();
|
8
|
+
}
|
7
9
|
}
|
8
10
|
|
9
|
-
function
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
$('#preview_div').html("Could not load preview")
|
11
|
+
function previewSimpleRss() {
|
12
|
+
var url = $('input#simple_rss_config_url').data('url');
|
13
|
+
if (url) {
|
14
|
+
rss_url = $('input#simple_rss_config_url').val();
|
15
|
+
output_format = $('select#simple_rss_config_output_format').val();
|
16
|
+
max_items = $('input#simple_rss_config_max_items').val();
|
17
|
+
reverse_order = $('select#simple_rss_config_reverse_order').val();
|
18
|
+
xsl = $('textarea#simple_rss_config_xsl').val();
|
19
|
+
if (max_items == '') {
|
20
|
+
max_items = '0';
|
20
21
|
}
|
21
|
-
|
22
|
+
$("#preview_div").load(url, { data: {
|
23
|
+
url: rss_url,
|
24
|
+
output_format: output_format,
|
25
|
+
max_items: max_items,
|
26
|
+
reverse_order: reverse_order,
|
27
|
+
xsl: xsl
|
28
|
+
}, type: 'SimpleRss' });
|
29
|
+
}
|
22
30
|
}
|
23
31
|
|
24
|
-
|
32
|
+
var initializedSimpleRssHandlers = false;
|
33
|
+
function initializeSimpleRssHandlers() {
|
34
|
+
if (!initializedSimpleRssHandlers) {
|
35
|
+
$('select#simple_rss_config_output_format').on('change', toggleSimpleRssConditionalInputs);
|
36
|
+
toggleSimpleRssConditionalInputs();
|
25
37
|
|
26
|
-
|
27
|
-
|
28
|
-
|
38
|
+
// on blur and change of url, display format, reverse_order, max items, and xsl
|
39
|
+
// not on keyup (poor man's debouncing technique?)
|
40
|
+
$('input#simple_rss_config_url').on('blur', previewSimpleRss);
|
41
|
+
$('select#simple_rss_config_output_format').on('change', previewSimpleRss);
|
42
|
+
$('input#simple_rss_config_max_items').on('blur', previewSimpleRss);
|
43
|
+
$('select#simple_rss_config_reverse_order').on('change', previewSimpleRss);
|
44
|
+
$('textarea#simple_rss_config_xsl').on('blur', previewSimpleRss);
|
29
45
|
|
30
|
-
|
31
|
-
rss_preview = "<div><p style='font-weight: bold'>Found " + articles.length + " articles total</p></div>";
|
32
|
-
for (var i = 0; i < Math.min(4, articles.length); i++) {
|
33
|
-
rss_preview += "<div>" +
|
34
|
-
"<p style='font-size: 14px; text-decoration: underline'>" + articles[i]['title'] + "</p>" +
|
35
|
-
"<p>" + articles[i]['contentSnippet'] + "</p>" + "</div>";
|
46
|
+
initializedSimpleRssHandlers = true;
|
36
47
|
}
|
37
|
-
$('#preview_div').html(rss_preview);
|
38
48
|
}
|
39
49
|
|
40
|
-
$(document).ready(
|
41
|
-
$(document).on('page:change',
|
50
|
+
$(document).ready(initializeSimpleRssHandlers);
|
51
|
+
$(document).on('page:change', initializeSimpleRssHandlers);
|
data/app/models/simple_rss.rb
CHANGED
@@ -8,28 +8,44 @@ class SimpleRss < DynamicContent
|
|
8
8
|
contents = []
|
9
9
|
|
10
10
|
url = self.config['url']
|
11
|
-
type, feed_title, rss = fetch_feed(url)
|
11
|
+
type, feed_title, rss, raw = fetch_feed(url)
|
12
12
|
|
13
13
|
if (["RSS", "ATOM"].include? type) && !feed_title.blank?
|
14
14
|
# it is a valid feed
|
15
15
|
if !self.config['reverse_order'].blank? && self.config['reverse_order'] == '1'
|
16
16
|
rss.items.reverse!
|
17
17
|
end
|
18
|
+
feed_items = rss.items
|
19
|
+
if !self.config['max_items'].blank? && self.config['max_items'].to_i > 0
|
20
|
+
feed_items = feed_items.first(self.config['max_items'].to_i)
|
21
|
+
end
|
18
22
|
case self.config['output_format']
|
19
23
|
when 'headlines'
|
20
|
-
|
24
|
+
feed_items.each_slice(5).with_index do |items, index|
|
21
25
|
htmltext = HtmlText.new()
|
22
26
|
htmltext.name = "#{feed_title} (#{index+1})"
|
23
27
|
htmltext.data = "<h1>#{feed_title}</h1> #{items_to_html(items, type)}"
|
24
28
|
contents << htmltext
|
25
29
|
end
|
26
30
|
when 'detailed'
|
27
|
-
|
31
|
+
feed_items.each_with_index do |item, index|
|
28
32
|
htmltext = HtmlText.new()
|
29
33
|
htmltext.name = "#{feed_title} (#{index+1})"
|
30
34
|
htmltext.data = item_to_html(item, type)
|
31
35
|
contents << htmltext
|
32
36
|
end
|
37
|
+
when 'xslt'
|
38
|
+
require 'rexml/document'
|
39
|
+
require 'xml/xslt'
|
40
|
+
|
41
|
+
XML::XSLT.registerErrorHandler { |string| puts string }
|
42
|
+
xslt = XML::XSLT.new()
|
43
|
+
xslt.xml = REXML::Document.new(raw)
|
44
|
+
xslt.xsl = REXML::Document.new(self.config['xsl'])
|
45
|
+
htmltext = HtmlText.new()
|
46
|
+
htmltext.name = "#{feed_title}"
|
47
|
+
htmltext.data = xslt.serve()
|
48
|
+
contents << htmltext
|
33
49
|
else
|
34
50
|
raise ArgumentError, 'Unexpected output format for RSS feed.'
|
35
51
|
end
|
@@ -41,7 +57,7 @@ class SimpleRss < DynamicContent
|
|
41
57
|
return contents
|
42
58
|
end
|
43
59
|
|
44
|
-
# fetch the feed, return the type, title, and contents
|
60
|
+
# fetch the feed, return the type, title, and contents (parsed) and raw feed (unparsed)
|
45
61
|
def fetch_feed(url)
|
46
62
|
require 'rss'
|
47
63
|
require 'net/http'
|
@@ -49,13 +65,18 @@ class SimpleRss < DynamicContent
|
|
49
65
|
type = 'UNKNOWN'
|
50
66
|
title = ''
|
51
67
|
rss = nil
|
68
|
+
feed = nil
|
52
69
|
|
53
70
|
begin
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
71
|
+
# cache same url for 1 minute to alleviate redundant calls when previewing
|
72
|
+
feed = Rails.cache.fetch(url, :expires_in => 1.minute) do
|
73
|
+
uri = URI.parse(url)
|
74
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
75
|
+
http.use_ssl = uri.scheme == 'https'
|
76
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
77
|
+
http.request(request).body
|
78
|
+
end
|
79
|
+
|
59
80
|
rss = RSS::Parser.parse(feed, false, true)
|
60
81
|
raise "feed could not be parsed" if rss.nil?
|
61
82
|
rescue => e
|
@@ -75,7 +96,7 @@ class SimpleRss < DynamicContent
|
|
75
96
|
end
|
76
97
|
end
|
77
98
|
|
78
|
-
return type, title, rss
|
99
|
+
return type, title, rss, feed
|
79
100
|
end
|
80
101
|
|
81
102
|
def item_to_html(item, type)
|
@@ -114,7 +135,7 @@ class SimpleRss < DynamicContent
|
|
114
135
|
# Simple RSS processing needs a feed URL and the format of the output content.
|
115
136
|
def self.form_attributes
|
116
137
|
attributes = super()
|
117
|
-
attributes.concat([:config => [:url, :output_format, :reverse_order]])
|
138
|
+
attributes.concat([:config => [:url, :output_format, :reverse_order, :max_items, :xsl]])
|
118
139
|
end
|
119
140
|
|
120
141
|
# if the feed is valid we store the title in config
|
@@ -127,17 +148,60 @@ class SimpleRss < DynamicContent
|
|
127
148
|
if (["RSS", "ATOM"].include? type) && !title.blank?
|
128
149
|
self.config['title'] = title
|
129
150
|
else
|
130
|
-
errors.add(:
|
151
|
+
errors.add(:base, "URL does not appear to be an RSS feed")
|
131
152
|
end
|
132
153
|
end
|
133
154
|
end
|
134
155
|
|
135
156
|
def validate_config
|
136
157
|
if self.config['url'].blank?
|
137
|
-
errors.add(:
|
158
|
+
errors.add(:base, "URL can't be blank")
|
159
|
+
end
|
160
|
+
|
161
|
+
if !['headlines', 'detailed', 'xslt'].include?(self.config['output_format'])
|
162
|
+
errors.add(:base, "Display Format must be Headlines or Articles or XSLT")
|
163
|
+
end
|
164
|
+
|
165
|
+
if self.config['output_format'] == 'xslt'
|
166
|
+
if self.config['xsl'].blank?
|
167
|
+
errors.add(:base, "XSL Markup can't be blank when using the XSLT Display Format")
|
168
|
+
else
|
169
|
+
url = self.config['url']
|
170
|
+
unless url.blank?
|
171
|
+
require 'rexml/document'
|
172
|
+
require 'xml/xslt'
|
173
|
+
|
174
|
+
type, title, rss, raw = fetch_feed(url)
|
175
|
+
if ["RSS", "ATOM"].include? type
|
176
|
+
begin
|
177
|
+
xslt = XML::XSLT.new()
|
178
|
+
xslt.xml = REXML::Document.new(raw)
|
179
|
+
xslt.xsl = REXML::Document.new(self.config['xsl'])
|
180
|
+
rescue XML::XSLT::ParsingError
|
181
|
+
errors.add(:base, "XSL Markup could not be parsed")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
138
186
|
end
|
139
|
-
|
140
|
-
|
187
|
+
end
|
188
|
+
|
189
|
+
# return the first item for use as a preview
|
190
|
+
# data is a hash of the config
|
191
|
+
def self.preview(data)
|
192
|
+
begin
|
193
|
+
o = SimpleRss.create()
|
194
|
+
o.config['url'] = data[:url]
|
195
|
+
o.config['output_format'] = data[:output_format]
|
196
|
+
o.config['max_items'] = data[:max_items]
|
197
|
+
o.config['reverse_order'] = data[:reverse_order]
|
198
|
+
o.config['xsl'] = data[:xsl]
|
199
|
+
results = o.build_content.first.data
|
200
|
+
rescue => e
|
201
|
+
results = "Unable to preview #{e.message}"
|
141
202
|
end
|
203
|
+
|
204
|
+
return results
|
142
205
|
end
|
206
|
+
|
143
207
|
end
|
@@ -5,14 +5,14 @@
|
|
5
5
|
<div class="clearfix">
|
6
6
|
<%= config.label :url %>
|
7
7
|
<div class="input">
|
8
|
-
<%= config.url_field :url, :placeholder => 'http://feeds.bbci.co.uk/news/rss.xml', :class => "input-xxlarge", :value => @content.config['url'] %>
|
8
|
+
<%= config.url_field :url, :placeholder => 'http://feeds.bbci.co.uk/news/rss.xml', :class => "input-xxlarge", :value => @content.config['url'], "data-url" => preview_contents_path %>
|
9
9
|
<div><small>You can verify an RSS feed at <a href="http://validator.w3.org/feed/" target="_blank">http://validator.w3.org/feed/</a></small></div>
|
10
10
|
</div>
|
11
11
|
</div>
|
12
12
|
<div class="clearfix">
|
13
13
|
<%= config.label :output_format, 'Display Format' %>
|
14
14
|
<div class="input">
|
15
|
-
<%= config.select :output_format, [["Headlines", "headlines"], ["Articles", "detailed"]], :selected => @content.config['output_format'] %>
|
15
|
+
<%= config.select :output_format, [["Headlines", "headlines"], ["Articles", "detailed"], ["XSLT", "xslt"]], :selected => @content.config['output_format'] %>
|
16
16
|
</div>
|
17
17
|
</div>
|
18
18
|
<div class="clearfix">
|
@@ -21,5 +21,17 @@
|
|
21
21
|
<%= config.select :reverse_order, [["No", 0], ["Yes", 1]] %>
|
22
22
|
</div>
|
23
23
|
</div>
|
24
|
+
<div class="clearfix" id="simple_rss_maxitems">
|
25
|
+
<%= config.label :max_items, 'Maximum items from feed' %>
|
26
|
+
<div class="input">
|
27
|
+
<%= config.number_field :max_items, :min => 0, :step => 1, :value => @content.config['max_items'] %>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
<div class="clearfix" id="simple_rss_xslmarkup">
|
31
|
+
<%= label_tooltip "simple_rss", :config_xsl, "XSL Markup", :tip => "The XSL Markup field is only used when the Display Format is set to XSLT." %>
|
32
|
+
<div class="input">
|
33
|
+
<%= config.text_area :xsl, :class => "span12", :rows =>4, :value => @content.config['xsl'] %>
|
34
|
+
</div>
|
35
|
+
</div>
|
24
36
|
<% end %>
|
25
37
|
</fieldset>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concerto_simple_rss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Michalski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.2.11
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ruby-xslt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.9'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.9'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: sqlite3
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|