mako_rss 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +38 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +124 -0
- data/Rakefile +13 -0
- data/bin/mako +6 -0
- data/lib/mako/article.rb +36 -0
- data/lib/mako/cli.rb +49 -0
- data/lib/mako/commands/build.rb +33 -0
- data/lib/mako/commands/new.rb +28 -0
- data/lib/mako/commands/schedule.rb +12 -0
- data/lib/mako/commands/version.rb +11 -0
- data/lib/mako/configuration.rb +44 -0
- data/lib/mako/core.rb +81 -0
- data/lib/mako/core_ext/numeric.rb +10 -0
- data/lib/mako/core_ext/time.rb +10 -0
- data/lib/mako/core_ext.rb +4 -0
- data/lib/mako/errors.rb +25 -0
- data/lib/mako/feed.rb +29 -0
- data/lib/mako/feed_constructor.rb +71 -0
- data/lib/mako/feed_requester.rb +43 -0
- data/lib/mako/file_open_util.rb +19 -0
- data/lib/mako/html_renderer.rb +30 -0
- data/lib/mako/layouts/_feed_container.html.erb +19 -0
- data/lib/mako/mako_logger.rb +12 -0
- data/lib/mako/sass_renderer.rb +30 -0
- data/lib/mako/subscription_list_parser.rb +28 -0
- data/lib/mako/version.rb +5 -0
- data/lib/mako/view_helpers.rb +28 -0
- data/lib/mako/writer.rb +18 -0
- data/lib/mako.rb +41 -0
- data/lib/templates/Gemfile +5 -0
- data/lib/templates/config.yaml +14 -0
- data/lib/templates/sample_subscriptions/subscriptions.json +1 -0
- data/lib/templates/sample_subscriptions/subscriptions.txt +5 -0
- data/lib/templates/sample_subscriptions/subscriptions.xml +12 -0
- data/lib/templates/themes/sass/_fonts.scss +38 -0
- data/lib/templates/themes/sass/_layout.scss +97 -0
- data/lib/templates/themes/sass/_reboot.scss +473 -0
- data/lib/templates/themes/sass/_utilities.scss +13 -0
- data/lib/templates/themes/sass/_variables.scss +57 -0
- data/lib/templates/themes/simple.html.erb +46 -0
- data/lib/templates/themes/simple.scss +6 -0
- data/mako_rss.gemspec +36 -0
- metadata +233 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bb8b5a3c394b989b9722f6ae04b6373d23ba7e08
|
4
|
+
data.tar.gz: 11efdfb201da11cf3ec348d84ae41c639c7a52a8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a7603d695ded87c83719c2cd159d4e33f85878525fdd29c597c6a6fd033148c7e7a3add809f824c6e544634b196b109b3a1ada4d8cb0fcb5b6a44f7c93751f99
|
7
|
+
data.tar.gz: 0ba4e36181aa8dd232ad7f83fb3960dba146c136095cd0e875e0547a262aee1ceb80980e2a98a886a1534bb000bfd5259df3e77815ea87c0da2f8ea1bec675d9
|
data/.gitignore
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
.byebug_history
|
13
|
+
.sass-cache
|
14
|
+
|
15
|
+
# Used by dotenv library to load environment variables.
|
16
|
+
# .env
|
17
|
+
|
18
|
+
## Documentation cache and generated files:
|
19
|
+
/.yardoc/
|
20
|
+
/_yardoc/
|
21
|
+
/doc/
|
22
|
+
/rdoc/
|
23
|
+
|
24
|
+
## Environment normalization:
|
25
|
+
/.bundle/
|
26
|
+
/vendor/bundle
|
27
|
+
/lib/bundler/man/
|
28
|
+
|
29
|
+
# for a library or gem, you might want to ignore these files since the code is
|
30
|
+
# intended to run in multiple environments; otherwise, check them in:
|
31
|
+
Gemfile.lock
|
32
|
+
# .ruby-version
|
33
|
+
# .ruby-gemset
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2017-06-06 16:33:49 -0400 using RuboCop version 0.35.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 3
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Max: 26
|
12
|
+
|
13
|
+
# Offense count: 37
|
14
|
+
# Configuration parameters: AllowURI, URISchemes.
|
15
|
+
Metrics/LineLength:
|
16
|
+
Max: 629
|
17
|
+
|
18
|
+
# Offense count: 5
|
19
|
+
# Configuration parameters: CountComments.
|
20
|
+
Metrics/MethodLength:
|
21
|
+
Max: 25
|
22
|
+
|
23
|
+
# Offense count: 1
|
24
|
+
Style/AccessorMethodName:
|
25
|
+
Exclude:
|
26
|
+
- 'lib/mako/core.rb'
|
27
|
+
|
28
|
+
# Offense count: 22
|
29
|
+
# Configuration parameters: Exclude.
|
30
|
+
Style/Documentation:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
# Offense count: 1
|
34
|
+
# Cop supports --auto-correct.
|
35
|
+
# Configuration parameters: AllowAsExpressionSeparator.
|
36
|
+
Style/Semicolon:
|
37
|
+
Exclude:
|
38
|
+
- 'lib/mako/article.rb'
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Jonathan Pike
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# Mako 🥛 [![Build Status](https://travis-ci.org/jonathanpike/mako.svg?branch=master)](https://travis-ci.org/jonathanpike/mako) [![Coverage Status](https://coveralls.io/repos/github/jonathanpike/mako/badge.svg?branch=master)](https://coveralls.io/github/jonathanpike/mako?branch=master)
|
2
|
+
|
3
|
+
Mako is a static-site generating RSS reader. Mako is also my son's name for
|
4
|
+
milk.
|
5
|
+
|
6
|
+
I designed Mako with the following principals in mind:
|
7
|
+
|
8
|
+
1. RSS feeds are freely available, so reader software should be freely
|
9
|
+
available.
|
10
|
+
2. RSS feeds are part of the web, so reader software should be part of the web.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
To install Mako, do:
|
15
|
+
|
16
|
+
$ gem install mako
|
17
|
+
|
18
|
+
Once the gem is installed, you'll need to generate a new Mako site. You can do
|
19
|
+
this in 1 of 2 ways.
|
20
|
+
|
21
|
+
1. If you already have a directory that you want Mako to live in, run:
|
22
|
+
|
23
|
+
$ mako new
|
24
|
+
|
25
|
+
2. If you don't have a directory and want Mako to create on, run:
|
26
|
+
|
27
|
+
$ mako new path/to/directory
|
28
|
+
|
29
|
+
In your new Mako site, you'll see a directory structure like this:
|
30
|
+
|
31
|
+
```
|
32
|
+
.
|
33
|
+
├── sample_subscriptions
|
34
|
+
| ├── subscriptions.json
|
35
|
+
| ├── subscriptions.txt
|
36
|
+
| └── subscriptions.xml
|
37
|
+
├── site
|
38
|
+
├── themes
|
39
|
+
| ├── sass
|
40
|
+
| | ├── _fonts.scss
|
41
|
+
| | ├── _layout.scss
|
42
|
+
| | ├── _reboot.scss
|
43
|
+
| | ├── _utitilies.scss
|
44
|
+
| | └── _variables.scss
|
45
|
+
| ├── simple.html.erb
|
46
|
+
| └── simple.scss
|
47
|
+
├── Gemfile
|
48
|
+
└── config.yaml
|
49
|
+
```
|
50
|
+
|
51
|
+
## Adding Feeds
|
52
|
+
|
53
|
+
Once Mako is installed and your Mako site has been created, the next step is to
|
54
|
+
add your own feeds. Mako currently supports 3 formats:
|
55
|
+
|
56
|
+
1. OPML
|
57
|
+
2. JSON
|
58
|
+
3. Plain Text
|
59
|
+
|
60
|
+
In the [`sample_subscriptions`](/lib/templates/sample_subscriptions) directory, you'll see an example of each format.
|
61
|
+
Whichever you choose, place the file in the root directory and be sure its name
|
62
|
+
is `subscriptions`. The file extension (`.xml`/`.opml`, `.json`, or `.txt`)
|
63
|
+
will tell Mako what kind of subscription file you have.
|
64
|
+
|
65
|
+
## Configuration
|
66
|
+
|
67
|
+
Mako has very few configuration options. You can see all of them in the
|
68
|
+
comments in [`config.yaml`](/lib/templates/config.yaml).
|
69
|
+
|
70
|
+
## Building your Site
|
71
|
+
|
72
|
+
Once you've added your subscriptions, you can build your Mako site for the first
|
73
|
+
time. By default, Mako only builds the HTML portion of the site with the `mako
|
74
|
+
build` command. Since the CSS has not been generated, use the `--with-sass`
|
75
|
+
flag, like this:
|
76
|
+
|
77
|
+
$ mako build --with-sass
|
78
|
+
|
79
|
+
The built files will be present in the `site` directory after the `build`
|
80
|
+
command has been run.
|
81
|
+
|
82
|
+
At present, Mako only displays the last 2 days worth of content from your feeds.
|
83
|
+
If a feed has not been updated in the last 2 days, it will not be displayed on
|
84
|
+
your Mako site. Similarly, articles that were published > 2 days in the past
|
85
|
+
will not be displayed on your Mako site.
|
86
|
+
|
87
|
+
## Themes
|
88
|
+
|
89
|
+
Mako comes with a simple theme of my own design (and own liking). Perhaps you
|
90
|
+
want something different. Mako's themes are templated with
|
91
|
+
[ERB](https://ruby-doc.org/stdlib-2.4.1/libdoc/erb/rdoc/ERB.html). You have
|
92
|
+
access to the following convenience methods:
|
93
|
+
- `today` - Gives you the current date in Day, `Date Month Year` format.
|
94
|
+
- `last_updated` - Gives you the current date and time in `day month year
|
95
|
+
hour:minute:second` format.
|
96
|
+
|
97
|
+
Within your template, you can access the feed data through the `feeds` array.
|
98
|
+
The `feeds` array contains `feed` objects, which have the following attributes:
|
99
|
+
- `title` - a string of the feed title.
|
100
|
+
- `url` - a string of the feed url.
|
101
|
+
- `articles` - an array of the articles associated with the feed.
|
102
|
+
|
103
|
+
To access the `articles` within a `feed`, you can use:
|
104
|
+
- `articles_desc` - sorts the array of articles by newest first.
|
105
|
+
- `articles_asc` - sorts the array of articles by oldest first.
|
106
|
+
|
107
|
+
`articles` contain the following attributes:
|
108
|
+
- `title` - a string of the article title.
|
109
|
+
- `url` - a string of the article url.
|
110
|
+
- `published` - a `Time` instance of the published date. Can also be accessed
|
111
|
+
by `formatted_published` to get it as formatted string.
|
112
|
+
- `summary` - a string of the article content.
|
113
|
+
|
114
|
+
When in doubt, check out the implementation of [my
|
115
|
+
theme](/lib/templates/themese/simple.html.erb).
|
116
|
+
|
117
|
+
## Contributing
|
118
|
+
|
119
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jonathanpike/mako.
|
120
|
+
|
121
|
+
## License
|
122
|
+
|
123
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
124
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.pattern = 'test/*_test.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
RuboCop::RakeTask.new(:rubocop)
|
12
|
+
|
13
|
+
task default: %i[test rubocop]
|
data/bin/mako
ADDED
data/lib/mako/article.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class Article
|
5
|
+
attr_reader :title, :published, :summary, :url
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
@title = args.fetch(:title, '')
|
9
|
+
@published = args.fetch(:published)
|
10
|
+
@summary = sanitize(args.fetch(:summary))
|
11
|
+
@url = args.fetch(:url)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Converts published Time object to formatted string
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
def formatted_published
|
18
|
+
@published.strftime('%A, %d %B %Y at %I:%M %P')
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# @private
|
24
|
+
# Removes img tags (if configured) and transforms h1 tags into
|
25
|
+
# p tags with the class bold
|
26
|
+
#
|
27
|
+
# @param [String] html an html document string
|
28
|
+
# @return [String] a sanitized html document string
|
29
|
+
def sanitize(html)
|
30
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
31
|
+
doc.css('img').each(&:remove) if Mako.config.sanitize_images
|
32
|
+
doc.css('h1,h2,h3,h4,h5,h6').each { |n| n.name = 'p'; n.set_attribute('class', 'bold') }
|
33
|
+
doc.to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/mako/cli.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'commands/build'
|
4
|
+
require_relative 'commands/new'
|
5
|
+
require_relative 'commands/version'
|
6
|
+
|
7
|
+
module Mako
|
8
|
+
class CLI
|
9
|
+
COMMANDS = %w[build new version].freeze
|
10
|
+
|
11
|
+
# Takes ARGV and parses the first element (command) to see if it is
|
12
|
+
# in the commands array. If not, display help.
|
13
|
+
#
|
14
|
+
# @param [Array] argv
|
15
|
+
def self.start(argv)
|
16
|
+
command = argv.shift
|
17
|
+
if COMMANDS.include? command
|
18
|
+
CLI.invoke(command, argv)
|
19
|
+
else
|
20
|
+
help = <<~EOS
|
21
|
+
Usage:
|
22
|
+
mako [subcommand] [path...]
|
23
|
+
|
24
|
+
Subcommands:
|
25
|
+
new Create a new Mako scaffold in PATH. If no PATH provided, defaults to current directory.
|
26
|
+
build Build your Mako site. Default: only build HTML.
|
27
|
+
version Display the version.
|
28
|
+
|
29
|
+
Options:
|
30
|
+
--with-sass When supplied to build, also generates CSS from SCSS files.
|
31
|
+
EOS
|
32
|
+
Mako.logger.info help
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Calls #perform on the provided command class. When the command is done
|
37
|
+
# running, print out any errors that the command had.
|
38
|
+
#
|
39
|
+
# @param [String] command
|
40
|
+
# @param [Array] args the remainder of the ARGV arguments
|
41
|
+
def self.invoke(command, args = [])
|
42
|
+
Object.const_get("Mako::#{command.capitalize}").perform(args)
|
43
|
+
return unless Mako.errors.any?
|
44
|
+
Mako.errors.messages.each do |error_msg|
|
45
|
+
Mako.logger.warn error_msg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class Build
|
5
|
+
# Calls #build on Mako::Core. This class stores knowledge of all of the
|
6
|
+
# different component classes needed to build the site.
|
7
|
+
#
|
8
|
+
# @param [Array] args the following are accepted arguments:
|
9
|
+
# "--with-sass": builds with SassRenderer
|
10
|
+
def self.perform(args)
|
11
|
+
subscription_list = load_subscription_list
|
12
|
+
if args.include? '--with-sass'
|
13
|
+
Mako::Core.new(requester: FeedRequester,
|
14
|
+
constructor: FeedConstructor,
|
15
|
+
renderers: [HTMLRenderer,
|
16
|
+
SassRenderer],
|
17
|
+
writer: Writer,
|
18
|
+
subscription_list: subscription_list).build
|
19
|
+
else
|
20
|
+
Mako::Core.new(requester: FeedRequester,
|
21
|
+
constructor: FeedConstructor,
|
22
|
+
renderers: [HTMLRenderer],
|
23
|
+
writer: Writer,
|
24
|
+
subscription_list: subscription_list).build
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.load_subscription_list
|
29
|
+
path = File.expand_path(Dir.glob('subscriptions.*').first, Dir.pwd)
|
30
|
+
Mako::SubscriptionListParser.new(list: path).parse
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Mako
|
6
|
+
class New
|
7
|
+
# Copies template files stored in ../lib/templates to specified directory.
|
8
|
+
# If the directory specified doesn't exist, it will be created.
|
9
|
+
# If no directory is specified, it defaults to the current directory.
|
10
|
+
def self.perform(args)
|
11
|
+
location = args.empty? ? Dir.pwd : File.expand_path(args.join(' '), Dir.pwd)
|
12
|
+
create_dir(File.basename(location)) if location != Dir.pwd && File.directory?(location)
|
13
|
+
copy_templates(location)
|
14
|
+
Mako.logger.info "Created new Mako installation in #{location}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# @private
|
18
|
+
# Copies source templates to specified path.
|
19
|
+
def self.copy_templates(path)
|
20
|
+
FileUtils.cp_r "#{Mako.config.source_templates}/.", path
|
21
|
+
end
|
22
|
+
|
23
|
+
# If the directory does not exist, create the specified directory.
|
24
|
+
def self.create_dir(path)
|
25
|
+
FileUtils.mkdir path
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Mako
|
6
|
+
class Configuration
|
7
|
+
DEFAULT_CONFIGURATION = { 'source_templates' => File.expand_path('../templates', File.dirname(__FILE__)),
|
8
|
+
'destination' => File.expand_path('site/', Dir.pwd),
|
9
|
+
'theme' => 'simple',
|
10
|
+
'sanitize_images' => true,
|
11
|
+
'config_file' => '' }.freeze
|
12
|
+
|
13
|
+
include FileOpenUtil
|
14
|
+
|
15
|
+
# Loads default config file and attempts to merge in any user settings.
|
16
|
+
# Creates a new instance of Mako::Configuration.
|
17
|
+
#
|
18
|
+
# @param [String]
|
19
|
+
# @return [Mako::Configuration]
|
20
|
+
def self.load(file)
|
21
|
+
begin
|
22
|
+
user_config_yaml = load_resource(file)
|
23
|
+
rescue SystemCallError
|
24
|
+
config = DEFAULT_CONFIGURATION
|
25
|
+
return new(config)
|
26
|
+
end
|
27
|
+
user_config = YAML.safe_load(user_config_yaml) || {}
|
28
|
+
user_config['config_file'] = file
|
29
|
+
config = DEFAULT_CONFIGURATION.merge(user_config)
|
30
|
+
new(config)
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :source_templates, :theme, :destination, :sanitize_images,
|
34
|
+
:config_file
|
35
|
+
|
36
|
+
def initialize(args)
|
37
|
+
@source_templates = args.fetch('source_templates')
|
38
|
+
@theme = args.fetch('theme')
|
39
|
+
@destination = args.fetch('destination')
|
40
|
+
@sanitize_images = args.fetch('sanitize_images')
|
41
|
+
@config_file = args.fetch('config_file')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/mako/core.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class Core
|
5
|
+
include ERB::Util
|
6
|
+
include ViewHelpers
|
7
|
+
|
8
|
+
attr_reader :feeds, :requester, :constructor, :renderers, :writer,
|
9
|
+
:subscription_list
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
@feeds = []
|
13
|
+
@requester = args.fetch(:requester)
|
14
|
+
@constructor = args.fetch(:constructor)
|
15
|
+
@renderers = args.fetch(:renderers)
|
16
|
+
@writer = args.fetch(:writer)
|
17
|
+
@subscription_list = args.fetch(:subscription_list)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Gets list of feed_urls, requests each of them and uses the constructor to
|
21
|
+
# make Feed and Article objects, then calls to the renderers to render
|
22
|
+
# the page and stylesheets.
|
23
|
+
def build
|
24
|
+
log_configuration_information
|
25
|
+
|
26
|
+
if subscription_list.empty?
|
27
|
+
Mako.logger.warn 'No feeds were found in your subscriptions file. Please add feeds and try again.'
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
log_time do
|
32
|
+
request_and_build_feeds
|
33
|
+
renderers.each do |renderer|
|
34
|
+
renderer_instance = renderer.new(bound: self)
|
35
|
+
writer.new(renderer: renderer_instance,
|
36
|
+
destination: File.expand_path(renderer_instance.file_path, Mako.config.destination)).write
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the Binding of Core for the ERB renderer. Binding encapsulates the
|
42
|
+
# execution context for the Core class, and makes all of the variables
|
43
|
+
# and methods of Core available to the renderer.
|
44
|
+
#
|
45
|
+
# @return [Binding]
|
46
|
+
def get_binding
|
47
|
+
binding
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# @private
|
53
|
+
# Prints configuration file, source, and destination directory to STDOUT.
|
54
|
+
def log_configuration_information
|
55
|
+
Mako.logger.info "Configuration File: #{Mako.config.config_file}"
|
56
|
+
Mako.logger.info "Theme: #{Mako.config.theme}"
|
57
|
+
Mako.logger.info "Destination: #{Mako.config.destination}"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Provides build time logging information and writes it to STDOUT.
|
61
|
+
def log_time
|
62
|
+
Mako.logger.info 'Generating...'
|
63
|
+
start_time = Time.now.to_f
|
64
|
+
yield
|
65
|
+
generation_time = Time.now.to_f - start_time
|
66
|
+
Mako.logger.info "done in #{generation_time} seconds"
|
67
|
+
end
|
68
|
+
|
69
|
+
def request_and_build_feeds
|
70
|
+
requesters = subscription_list.map { |feed_url| requester.new(feed_url: feed_url) }
|
71
|
+
requesters.each do |feed_request|
|
72
|
+
feed_response = feed_request.fetch
|
73
|
+
next unless feed_request.ok?
|
74
|
+
constructed_feed = constructor.new(feed_data: feed_response.body,
|
75
|
+
feed_url: feed_response.feed_url)
|
76
|
+
.parse_and_create
|
77
|
+
feeds << constructed_feed if constructed_feed
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/mako/errors.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class Errors
|
5
|
+
attr_accessor :messages
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@messages = []
|
9
|
+
end
|
10
|
+
|
11
|
+
# Add an error message to the messages array
|
12
|
+
#
|
13
|
+
# @param [String]
|
14
|
+
def add_error(msg)
|
15
|
+
messages << msg
|
16
|
+
end
|
17
|
+
|
18
|
+
# Predicate method to see if there are any error messages
|
19
|
+
#
|
20
|
+
# @return [Boolean]
|
21
|
+
def any?
|
22
|
+
messages.count.positive?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/mako/feed.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mako
|
4
|
+
class Feed
|
5
|
+
attr_accessor :feed_url, :url, :title, :articles
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
@url = args.fetch(:url)
|
9
|
+
@title = args.fetch(:title)
|
10
|
+
@articles = []
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the articles array sorted by date published ascending
|
14
|
+
# (oldest first).
|
15
|
+
#
|
16
|
+
# @return [Array]
|
17
|
+
def articles_asc
|
18
|
+
articles.sort_by(&:published)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the articles array sorted by date published descending
|
22
|
+
# (newest first).
|
23
|
+
#
|
24
|
+
# @return [Array]
|
25
|
+
def articles_desc
|
26
|
+
articles_asc.reverse
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|