mako_rss 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +8 -8
- data/README.md +13 -1
- data/Rakefile +1 -1
- data/lib/mako.rb +3 -1
- data/lib/mako/cli.rb +3 -1
- data/lib/mako/commands/subscribe.rb +19 -0
- data/lib/mako/feed_finder.rb +68 -0
- data/lib/mako/feed_requester.rb +7 -5
- data/lib/mako/subscription_list_parser.rb +10 -4
- data/lib/mako/subscription_list_writer.rb +70 -0
- data/lib/mako/version.rb +1 -1
- data/lib/templates/Gemfile +1 -1
- data/mako_rss.gemspec +1 -1
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 770630990cc3595bb157dee7f3d764d6a91b4e92
|
4
|
+
data.tar.gz: add1706141f24d42b880ae7f0b2ab819c2eeed60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58295d6d252e28a6ed94bbac881d2b35ea69f81cb965ede92c3f32598fb5201596f5b610a3d1e54b0ca4c2ed1828bc08f8a05edde5d4345ce30505cf76598796
|
7
|
+
data.tar.gz: 066590c44fb0fb8a6660f8085aa9bc24cd33986f82bacb0688522a590ed1292c67f8cd1f988b59768dc81cf7c45d1ee538412c63bfcb9524db3a8e0fb62c3070
|
data/.rubocop_todo.yml
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2017-
|
3
|
+
# on 2017-07-11 13:25:18 -0400 using RuboCop version 0.49.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 4
|
10
10
|
Metrics/AbcSize:
|
11
|
-
Max:
|
11
|
+
Max: 28
|
12
12
|
|
13
|
-
# Offense count:
|
14
|
-
# Configuration parameters: AllowURI, URISchemes.
|
13
|
+
# Offense count: 40
|
14
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
15
|
+
# URISchemes: http, https
|
15
16
|
Metrics/LineLength:
|
16
17
|
Max: 629
|
17
18
|
|
18
|
-
# Offense count:
|
19
|
+
# Offense count: 8
|
19
20
|
# Configuration parameters: CountComments.
|
20
21
|
Metrics/MethodLength:
|
21
22
|
Max: 25
|
@@ -25,8 +26,7 @@ Style/AccessorMethodName:
|
|
25
26
|
Exclude:
|
26
27
|
- 'lib/mako/core.rb'
|
27
28
|
|
28
|
-
# Offense count:
|
29
|
-
# Configuration parameters: Exclude.
|
29
|
+
# Offense count: 25
|
30
30
|
Style/Documentation:
|
31
31
|
Enabled: false
|
32
32
|
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ I designed Mako with the following principals in mind:
|
|
13
13
|
|
14
14
|
To install Mako, do:
|
15
15
|
|
16
|
-
$ gem install
|
16
|
+
$ gem install mako_rss
|
17
17
|
|
18
18
|
Once the gem is installed, you'll need to generate a new Mako site. You can do
|
19
19
|
this in 1 of 2 ways.
|
@@ -62,6 +62,18 @@ Whichever you choose, place the file in the root directory and be sure its name
|
|
62
62
|
is `subscriptions`. The file extension (`.xml`/`.opml`, `.json`, or `.txt`)
|
63
63
|
will tell Mako what kind of subscription file you have.
|
64
64
|
|
65
|
+
## Subscribing to Additional Feeds
|
66
|
+
|
67
|
+
If you already have imported your subscription file, and subsequently want to
|
68
|
+
subscribe to additional feeds, Mako has a handy `subscribe` command to help you
|
69
|
+
out.
|
70
|
+
|
71
|
+
$ mako subscribe [url or urls]
|
72
|
+
|
73
|
+
It's generally best if you use the root URL of the site you would like to
|
74
|
+
subscribe to, such as https://jonathanpike.net. Mako will look at the site,
|
75
|
+
find a feed URL if it can, and add that URL to your subscription file. Easy!
|
76
|
+
|
65
77
|
## Configuration
|
66
78
|
|
67
79
|
Mako has very few configuration options. You can see all of them in the
|
data/Rakefile
CHANGED
data/lib/mako.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'time'
|
4
4
|
require 'erb'
|
5
5
|
require 'logger'
|
6
|
-
require '
|
6
|
+
require 'httparty'
|
7
7
|
require 'feedjira'
|
8
8
|
require 'nokogiri'
|
9
9
|
require 'json'
|
@@ -16,10 +16,12 @@ require_relative 'mako/mako_logger'
|
|
16
16
|
require_relative 'mako/view_helpers'
|
17
17
|
require_relative 'mako/configuration'
|
18
18
|
require_relative 'mako/subscription_list_parser'
|
19
|
+
require_relative 'mako/subscription_list_writer'
|
19
20
|
require_relative 'mako/feed'
|
20
21
|
require_relative 'mako/article'
|
21
22
|
require_relative 'mako/feed_requester'
|
22
23
|
require_relative 'mako/feed_constructor'
|
24
|
+
require_relative 'mako/feed_finder'
|
23
25
|
require_relative 'mako/html_renderer'
|
24
26
|
require_relative 'mako/sass_renderer'
|
25
27
|
require_relative 'mako/writer'
|
data/lib/mako/cli.rb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
require_relative 'commands/build'
|
4
4
|
require_relative 'commands/new'
|
5
|
+
require_relative 'commands/subscribe'
|
5
6
|
require_relative 'commands/version'
|
6
7
|
|
7
8
|
module Mako
|
8
9
|
class CLI
|
9
|
-
COMMANDS = %w[build new version].freeze
|
10
|
+
COMMANDS = %w[build new subscribe version].freeze
|
10
11
|
|
11
12
|
# Takes ARGV and parses the first element (command) to see if it is
|
12
13
|
# in the commands array. If not, display help.
|
@@ -24,6 +25,7 @@ module Mako
|
|
24
25
|
Subcommands:
|
25
26
|
new Create a new Mako scaffold in PATH. If no PATH provided, defaults to current directory.
|
26
27
|
build Build your Mako site. Default: only build HTML.
|
28
|
+
subscribe Subscribe to the supplied URL or URLs. Accepts a list separated by spaces.
|
27
29
|
version Display the version.
|
28
30
|
|
29
31
|
Options:
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class Subscribe
|
5
|
+
def self.perform(args)
|
6
|
+
if args.empty?
|
7
|
+
Mako.errors.add_error 'No feeds to find'
|
8
|
+
return
|
9
|
+
end
|
10
|
+
feeds = Mako::FeedFinder.new(uris: args).find
|
11
|
+
write_to_subscriptions(feeds)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.write_to_subscriptions(feed_urls)
|
15
|
+
path = File.expand_path(Dir.glob('subscriptions.*').first, Dir.pwd)
|
16
|
+
Mako::SubscriptionListWriter.new(feeds: feed_urls, destination: path).append_and_write
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class FeedFinder
|
5
|
+
# Patterns for RSS, Atom, and JSON feeds
|
6
|
+
XPATHS = ["//link[@rel='alternate'][@type='application/rss+xml']/@href",
|
7
|
+
"//link[@rel='alternate'][@type='application/atom+xml']/@href",
|
8
|
+
"//link[@rel='alternate'][@type='application/json']/@href"].freeze
|
9
|
+
MIME_TYPES = ['text/xml',
|
10
|
+
'application/xml',
|
11
|
+
'application/rss+xml',
|
12
|
+
'application/atom+xml',
|
13
|
+
'application/json'].freeze
|
14
|
+
|
15
|
+
attr_reader :uris
|
16
|
+
|
17
|
+
def initialize(args)
|
18
|
+
@uris = args.fetch(:uris)
|
19
|
+
end
|
20
|
+
|
21
|
+
# From an array of supplied URIs, will request each one and attempt to
|
22
|
+
# find a feed URI on the page. If one is found, it will be added to
|
23
|
+
# an array and returned.
|
24
|
+
#
|
25
|
+
# @return [Array]
|
26
|
+
def find
|
27
|
+
request_uris.map do |request|
|
28
|
+
if request[:body].nil?
|
29
|
+
request[:uri]
|
30
|
+
else
|
31
|
+
html = Nokogiri::HTML(request[:body])
|
32
|
+
potential_feed_uris = html.xpath(XPATHS.detect { |path| !html.xpath(path).empty? })
|
33
|
+
next if potential_feed_uris.empty?
|
34
|
+
uri_string = potential_feed_uris.first.value
|
35
|
+
feed_uri = URI.parse(uri_string)
|
36
|
+
if request[:uri].host == feed_uri.host
|
37
|
+
feed_uri.to_s
|
38
|
+
else
|
39
|
+
request[:uri].merge(feed_uri).to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end.compact
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# @private
|
48
|
+
# Make requests for each URI passed in and return an array of hashes
|
49
|
+
# with either just the URI (in the case that the URI passed in was already
|
50
|
+
# a feed URI), or the URI and the response body.
|
51
|
+
#
|
52
|
+
# @return [Array]
|
53
|
+
def request_uris
|
54
|
+
uris.map do |uri|
|
55
|
+
parsed_uri = URI.parse(uri)
|
56
|
+
# Try giving the URI a scheme if one isn't passed
|
57
|
+
parsed_uri = URI.parse('http://' + uri) if parsed_uri.scheme.nil?
|
58
|
+
request = Mako::FeedRequester.new(feed_url: parsed_uri).fetch
|
59
|
+
next unless request.ok?
|
60
|
+
if MIME_TYPES.include? request.headers['content-type'].split(';').first
|
61
|
+
{ uri: parsed_uri.to_s }
|
62
|
+
else
|
63
|
+
{ uri: parsed_uri, body: request.body }
|
64
|
+
end
|
65
|
+
end.compact
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/mako/feed_requester.rb
CHANGED
@@ -3,11 +3,12 @@
|
|
3
3
|
module Mako
|
4
4
|
class FeedRequester
|
5
5
|
attr_reader :feed_url
|
6
|
-
attr_accessor :ok, :body
|
6
|
+
attr_accessor :ok, :body, :headers
|
7
7
|
|
8
8
|
def initialize(args)
|
9
9
|
@ok = true
|
10
10
|
@body = ''
|
11
|
+
@headers = {}
|
11
12
|
@feed_url = args.fetch(:feed_url)
|
12
13
|
end
|
13
14
|
|
@@ -18,17 +19,18 @@ module Mako
|
|
18
19
|
# @return [Mako::FeedRequester]
|
19
20
|
def fetch
|
20
21
|
begin
|
21
|
-
request =
|
22
|
-
rescue
|
22
|
+
request = HTTParty.get(feed_url)
|
23
|
+
rescue SocketError
|
23
24
|
Mako.errors.add_error "Could not complete request to #{feed_url}."
|
24
25
|
self.ok = false
|
25
26
|
return self
|
26
27
|
end
|
27
|
-
unless request.
|
28
|
-
Mako.errors.add_error "Request to #{feed_url} returned #{request.
|
28
|
+
unless request.code == 200
|
29
|
+
Mako.errors.add_error "Request to #{feed_url} returned #{request.code}."
|
29
30
|
self.ok = false
|
30
31
|
return self
|
31
32
|
end
|
33
|
+
self.headers = request.headers
|
32
34
|
self.body = request.body
|
33
35
|
self
|
34
36
|
end
|
@@ -14,15 +14,21 @@ module Mako
|
|
14
14
|
#
|
15
15
|
# @return [Array]
|
16
16
|
def parse
|
17
|
-
loaded_list = load_resource(list)
|
18
17
|
case File.extname list
|
19
18
|
when '.xml' || '.opml'
|
20
|
-
Nokogiri::XML(
|
19
|
+
Nokogiri::XML(load_list).xpath('//@xmlUrl').map(&:value)
|
21
20
|
when '.json'
|
22
|
-
JSON.parse(
|
21
|
+
JSON.parse(load_list)
|
23
22
|
when '.txt'
|
24
|
-
|
23
|
+
load_list.split("\n")
|
25
24
|
end
|
26
25
|
end
|
26
|
+
|
27
|
+
# Load the subscription list file
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
def load_list
|
31
|
+
load_resource(list)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class SubscriptionListWriter
|
5
|
+
include FileOpenUtil
|
6
|
+
|
7
|
+
attr_reader :feeds, :destination
|
8
|
+
|
9
|
+
def initialize(args)
|
10
|
+
@feeds = args.fetch(:feeds)
|
11
|
+
@destination = args.fetch(:destination)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Appends the new subscriptions to the subscription list and
|
15
|
+
# writes the results out to the file.
|
16
|
+
def append_and_write
|
17
|
+
contents = append_and_render
|
18
|
+
File.open(destination, 'w+', encoding: 'utf-8') do |f|
|
19
|
+
f.write(contents)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# @private
|
26
|
+
# Returns the rendered string for the correct file type.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
def append_and_render
|
30
|
+
loaded_list = SubscriptionListParser.new(list: destination)
|
31
|
+
case File.extname destination
|
32
|
+
when '.xml' || '.opml'
|
33
|
+
render_opml(loaded_list)
|
34
|
+
when '.json'
|
35
|
+
render_json(loaded_list)
|
36
|
+
when '.txt'
|
37
|
+
render_txt(loaded_list)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Append feeds to current subscription list and return a string separated
|
42
|
+
# by \n characters
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
def render_txt(list)
|
46
|
+
(list.parse + feeds).join("\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Append feeds to current subscription list and return a JSON array
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
def render_json(list)
|
53
|
+
(list.parse + feeds).to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
# Append feeds to current subscription list and return XML document
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
def render_opml(list)
|
60
|
+
document = Nokogiri::XML(list.load_list)
|
61
|
+
feeds.each do |feed_url|
|
62
|
+
node = "<outline xmlUrl='#{feed_url}' />\n"
|
63
|
+
document.xpath("//outline[@text='Subscriptions']").last.add_child node
|
64
|
+
end
|
65
|
+
formatted_no_decl = Nokogiri::XML::Node::SaveOptions::FORMAT +
|
66
|
+
Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
67
|
+
document.to_xml(encoding: 'utf-8', save_with: formatted_no_decl)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/mako/version.rb
CHANGED
data/lib/templates/Gemfile
CHANGED
data/mako_rss.gemspec
CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency 'coveralls', '~> 0.8'
|
31
31
|
|
32
32
|
spec.add_runtime_dependency 'feedjira', '~> 2.0'
|
33
|
-
spec.add_runtime_dependency '
|
33
|
+
spec.add_runtime_dependency 'httparty', '~> 0.15'
|
34
34
|
spec.add_runtime_dependency 'nokogiri', '~> 1.8'
|
35
35
|
spec.add_runtime_dependency 'sass', '~> 3.4'
|
36
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mako_rss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Pike
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -109,19 +109,19 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '2.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: httparty
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0.
|
117
|
+
version: '0.15'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0.
|
124
|
+
version: '0.15'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: nokogiri
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -174,6 +174,7 @@ files:
|
|
174
174
|
- lib/mako/commands/build.rb
|
175
175
|
- lib/mako/commands/new.rb
|
176
176
|
- lib/mako/commands/schedule.rb
|
177
|
+
- lib/mako/commands/subscribe.rb
|
177
178
|
- lib/mako/commands/version.rb
|
178
179
|
- lib/mako/configuration.rb
|
179
180
|
- lib/mako/core.rb
|
@@ -183,6 +184,7 @@ files:
|
|
183
184
|
- lib/mako/errors.rb
|
184
185
|
- lib/mako/feed.rb
|
185
186
|
- lib/mako/feed_constructor.rb
|
187
|
+
- lib/mako/feed_finder.rb
|
186
188
|
- lib/mako/feed_requester.rb
|
187
189
|
- lib/mako/file_open_util.rb
|
188
190
|
- lib/mako/html_renderer.rb
|
@@ -190,6 +192,7 @@ files:
|
|
190
192
|
- lib/mako/mako_logger.rb
|
191
193
|
- lib/mako/sass_renderer.rb
|
192
194
|
- lib/mako/subscription_list_parser.rb
|
195
|
+
- lib/mako/subscription_list_writer.rb
|
193
196
|
- lib/mako/version.rb
|
194
197
|
- lib/mako/view_helpers.rb
|
195
198
|
- lib/mako/writer.rb
|