jekyll-recker 1.2.2 → 1.7.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 +105 -0
- data/_includes/figure.html +14 -0
- data/_includes/footer.html +10 -1
- data/_includes/head.html +21 -0
- data/_includes/nav.html +3 -6
- data/_includes/pager.html +13 -0
- data/_layouts/home.html +13 -9
- data/_layouts/page.html +13 -8
- data/_layouts/post.html +20 -28
- data/lib/jekyll-recker.rb +11 -13
- data/lib/jekyll_recker/commands.rb +31 -0
- data/lib/{jekyll-recker → jekyll_recker}/configuration.rb +6 -0
- data/lib/{jekyll-recker → jekyll_recker}/error.rb +0 -0
- data/lib/jekyll_recker/filters.rb +15 -0
- data/lib/{jekyll-recker/stats.rb → jekyll_recker/generators.rb} +42 -39
- data/lib/jekyll_recker/mixins.rb +45 -0
- data/lib/{jekyll-recker → jekyll_recker}/shell.rb +0 -0
- data/lib/jekyll_recker/social.rb +173 -0
- data/lib/{jekyll-recker → jekyll_recker}/tags.rb +1 -1
- data/lib/{jekyll-recker → jekyll_recker}/version.rb +1 -1
- data/lib/{jekyll-recker → jekyll_recker}/words.rb +0 -0
- metadata +87 -35
- data/README.org +0 -205
- data/_layouts/default.html +0 -14
- data/assets/jekyll-recker.scss +0 -111
- data/lib/jekyll-recker/commands.rb +0 -12
- data/lib/jekyll-recker/commands/share.rb +0 -25
- data/lib/jekyll-recker/commands/slack.rb +0 -30
- data/lib/jekyll-recker/commands/tweet.rb +0 -31
- data/lib/jekyll-recker/generators.rb +0 -17
- data/lib/jekyll-recker/logger.rb +0 -20
- data/lib/jekyll-recker/mixins.rb +0 -27
- data/lib/jekyll-recker/slack.rb +0 -70
- data/lib/jekyll-recker/twitter.rb +0 -83
data/_layouts/default.html
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8"/>
|
5
|
-
<title>{{ site.title }} | {{ page.title | default: site.description }}</title>
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7
|
-
<link href="{{ site.baseurl }}/assets/jekyll-recker.css" rel="stylesheet"/>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
{{ content }}
|
11
|
-
<hr/>
|
12
|
-
{% include footer.html %}
|
13
|
-
</body>
|
14
|
-
</html>
|
data/assets/jekyll-recker.scss
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
---
|
2
|
-
---
|
3
|
-
@import 'https://fonts.googleapis.com/css?family=Open+Sans&display=swap';
|
4
|
-
@import 'https://fonts.googleapis.com/css?family=Inconsolata&display=swap';
|
5
|
-
|
6
|
-
.float-right {
|
7
|
-
float: right;
|
8
|
-
}
|
9
|
-
|
10
|
-
.float-left {
|
11
|
-
float: left;
|
12
|
-
}
|
13
|
-
|
14
|
-
.clearfix::after {
|
15
|
-
content: "";
|
16
|
-
clear: both;
|
17
|
-
display: block;
|
18
|
-
}
|
19
|
-
|
20
|
-
@media screen and (max-width: 600px) {
|
21
|
-
.hide-on-mobile {
|
22
|
-
display: none;
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
|
-
ul.unstyled {
|
27
|
-
list-style-type: none;
|
28
|
-
margin: 0;
|
29
|
-
padding: 0;
|
30
|
-
}
|
31
|
-
|
32
|
-
body {
|
33
|
-
margin: 40px auto;
|
34
|
-
max-width: 800px;
|
35
|
-
line-height: 1.6;
|
36
|
-
font-size: 18px;
|
37
|
-
color: #444;
|
38
|
-
padding: 0 10px;
|
39
|
-
}
|
40
|
-
|
41
|
-
h1, h2, h3 {
|
42
|
-
line-height: 1.2;
|
43
|
-
}
|
44
|
-
|
45
|
-
header {
|
46
|
-
text-transform: lowercase;
|
47
|
-
|
48
|
-
h1 {
|
49
|
-
margin-bottom: 9px;
|
50
|
-
}
|
51
|
-
|
52
|
-
p {
|
53
|
-
margin-top: 9px;
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
figure {
|
58
|
-
img {
|
59
|
-
display: block;
|
60
|
-
margin-left: auto;
|
61
|
-
margin-right: auto;
|
62
|
-
vertical-align: top;
|
63
|
-
height: auto;
|
64
|
-
max-width: 100%;
|
65
|
-
}
|
66
|
-
|
67
|
-
figcaption {
|
68
|
-
text-align: center;
|
69
|
-
}
|
70
|
-
}
|
71
|
-
|
72
|
-
nav {
|
73
|
-
a {
|
74
|
-
margin-right: 10px;
|
75
|
-
}
|
76
|
-
|
77
|
-
a.active {
|
78
|
-
color: black !important;
|
79
|
-
}
|
80
|
-
|
81
|
-
span {
|
82
|
-
color: #6f7370;
|
83
|
-
}
|
84
|
-
}
|
85
|
-
|
86
|
-
a {
|
87
|
-
text-decoration: none !important;
|
88
|
-
color: #008083 !important;
|
89
|
-
|
90
|
-
:hover {
|
91
|
-
text-decoration: underline !important;
|
92
|
-
}
|
93
|
-
|
94
|
-
:active {
|
95
|
-
color: #6f7370 !important;
|
96
|
-
}
|
97
|
-
}
|
98
|
-
|
99
|
-
* {
|
100
|
-
// font-family: 'Titillium Web', sans-serif !important;
|
101
|
-
font-family: 'Open Sans', 'sans-serif' !important;
|
102
|
-
}
|
103
|
-
|
104
|
-
code, pre, pre span {
|
105
|
-
font-family: Inconsolata, monospace !important;
|
106
|
-
}
|
107
|
-
|
108
|
-
pre, pre span {
|
109
|
-
font-size: 14px;
|
110
|
-
}
|
111
|
-
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Jekyll
|
4
|
-
module Recker
|
5
|
-
module Commands
|
6
|
-
# Share
|
7
|
-
class Share < Jekyll::Command
|
8
|
-
include Jekyll::Recker::LoggingMixin
|
9
|
-
|
10
|
-
def self.init_with_program(prog)
|
11
|
-
prog.command(:share) do |c|
|
12
|
-
c.syntax 'share'
|
13
|
-
c.description 'Share latest post with each configured backend'
|
14
|
-
c.option 'dry', '-d', '--dry', 'perform dry run'
|
15
|
-
c.action do |_args, _options|
|
16
|
-
logger.info 'normally I\'d share here'
|
17
|
-
rescue ReckerError => e
|
18
|
-
logger.abort_with e.message
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Jekyll
|
4
|
-
module Recker
|
5
|
-
module Commands
|
6
|
-
# Slack
|
7
|
-
class Slack < Jekyll::Command
|
8
|
-
class << self
|
9
|
-
def init_with_program(prog)
|
10
|
-
prog.command(:slack) do |c|
|
11
|
-
c.syntax 'slack'
|
12
|
-
c.description 'slack latest post'
|
13
|
-
c.option 'dry', '-d', '--dry', 'print message instead of posting'
|
14
|
-
c.action do |_args, options|
|
15
|
-
Recker::Slack.each_in_config(dry: options['dry']) do |client|
|
16
|
-
Recker.info "#{client.key}: discovering webhook"
|
17
|
-
client.discover_webhook!
|
18
|
-
Recker.info "#{client.key}: posting #{client.latest.data['title']}"
|
19
|
-
client.post_latest!
|
20
|
-
end
|
21
|
-
rescue ReckerError => e
|
22
|
-
Recker.abort_with e.message
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Jekyll
|
4
|
-
module Recker
|
5
|
-
module Commands
|
6
|
-
# Tweet
|
7
|
-
class Tweet < Jekyll::Command
|
8
|
-
include LoggingMixin
|
9
|
-
|
10
|
-
class << self
|
11
|
-
def init_with_program(prog)
|
12
|
-
prog.command(:tweet) do |c|
|
13
|
-
c.syntax 'tweet'
|
14
|
-
c.description 'tweet latest post'
|
15
|
-
c.option 'dry', '-d', '--dry', 'print message instead of tweeting'
|
16
|
-
c.action do |_args, options|
|
17
|
-
client = Jekyll::Recker::Twitter.new(dry: options['dry'])
|
18
|
-
logger.info 'discovering credentials'
|
19
|
-
client.discover_credentials!
|
20
|
-
logger.info "tweeting #{client.latest.data['title']}"
|
21
|
-
client.post_latest!
|
22
|
-
rescue ReckerError => e
|
23
|
-
logger.abort_with e.message
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Jekyll
|
4
|
-
module Recker
|
5
|
-
module Generators
|
6
|
-
# StatsGenerator
|
7
|
-
class StatsGenerator < Jekyll::Generator
|
8
|
-
include Jekyll::Recker::LoggingMixin
|
9
|
-
|
10
|
-
def generate(site)
|
11
|
-
logger.info 'generating site statistics'
|
12
|
-
site.data['stats'] = Stats.crunch(site)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/jekyll-recker/logger.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'logger'
|
4
|
-
|
5
|
-
module Jekyll
|
6
|
-
# Recker
|
7
|
-
module Recker
|
8
|
-
def self.logger
|
9
|
-
@logger ||= make_logger
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.make_logger
|
13
|
-
logger = Logger.new(STDOUT)
|
14
|
-
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
15
|
-
"jekyll-recker: #{msg}\n"
|
16
|
-
end
|
17
|
-
logger
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/jekyll-recker/mixins.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Jekyll
|
4
|
-
module Recker
|
5
|
-
# Descendants Mixin
|
6
|
-
module DescendantsMixin
|
7
|
-
def self.included(base)
|
8
|
-
def base.descendants
|
9
|
-
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Logging Mixin
|
15
|
-
module LoggingMixin
|
16
|
-
def self.included(base)
|
17
|
-
def base.logger
|
18
|
-
Jekyll::Recker.logger
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def logger
|
23
|
-
Jekyll::Recker.logger
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
data/lib/jekyll-recker/slack.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'slack-notifier'
|
4
|
-
|
5
|
-
module Jekyll
|
6
|
-
# Recker
|
7
|
-
module Recker
|
8
|
-
# Slack
|
9
|
-
class Slack
|
10
|
-
include Jekyll::Recker::LoggingMixin
|
11
|
-
|
12
|
-
def self.each_in_config(dry: false)
|
13
|
-
Configuration.slack.map do |key, body|
|
14
|
-
yield new(key, body, dry: dry)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :key
|
19
|
-
|
20
|
-
def initialize(config_key, config_body, dry: false)
|
21
|
-
@key = config_key
|
22
|
-
@data = config_body
|
23
|
-
@webhook = nil
|
24
|
-
@dry = dry
|
25
|
-
end
|
26
|
-
|
27
|
-
def discover_webhook!
|
28
|
-
@webhook = ENV["SLACK_#{@key.upcase}_WEBHOOK"] || extract_from_config
|
29
|
-
raise ReckerError, 'cannot find slack credentials!' if @webhook.nil?
|
30
|
-
end
|
31
|
-
|
32
|
-
def latest
|
33
|
-
@latest ||= Configuration.latest_post
|
34
|
-
end
|
35
|
-
|
36
|
-
def post_latest!
|
37
|
-
if @dry
|
38
|
-
logger.info('postign in dry mode, printing message')
|
39
|
-
logger.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
|
40
|
-
else
|
41
|
-
::Slack::Notifier.new(
|
42
|
-
@webhook.strip,
|
43
|
-
channel: @data.fetch('channel'),
|
44
|
-
username: @data.fetch('username'),
|
45
|
-
icon_emoji: @data.fetch('emoji')
|
46
|
-
).post(text: message_body)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def message_body
|
53
|
-
url = File.join Configuration.jekyll['url'], latest.url
|
54
|
-
body = <<~MSG
|
55
|
-
#{latest.data['date'].strftime('%A, %B %-d %Y')}
|
56
|
-
#{latest.data['title']}
|
57
|
-
#{url}
|
58
|
-
MSG
|
59
|
-
::Slack::Notifier::Util::LinkFormatter.format(body)
|
60
|
-
end
|
61
|
-
|
62
|
-
def extract_from_config
|
63
|
-
cmd = @data['webhook_cmd']
|
64
|
-
return nil if cmd.nil?
|
65
|
-
|
66
|
-
Recker.shell(cmd)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'twitter'
|
4
|
-
|
5
|
-
module Jekyll
|
6
|
-
module Recker
|
7
|
-
# Twitter Client
|
8
|
-
class Twitter
|
9
|
-
include LoggingMixin
|
10
|
-
|
11
|
-
def initialize(dry: false)
|
12
|
-
@dry = dry
|
13
|
-
end
|
14
|
-
|
15
|
-
def discover_credentials!
|
16
|
-
@creds = extract_from_env || extract_from_config
|
17
|
-
raise ReckerError, 'cannot find twitter credentials!' if @creds.nil?
|
18
|
-
|
19
|
-
set_credentials!
|
20
|
-
end
|
21
|
-
|
22
|
-
def post_latest!
|
23
|
-
if @dry
|
24
|
-
logger.info('tweeting in dry mode, printing message')
|
25
|
-
logger.info("BEGIN TWEET\n#{tweet_body.strip}\nEND TWEET")
|
26
|
-
else
|
27
|
-
@client.update(tweet_body)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def latest
|
32
|
-
Configuration.latest_post
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def tweet_body
|
38
|
-
url = File.join Configuration.jekyll['url'], latest.url
|
39
|
-
<<~TWEET
|
40
|
-
#{latest.data['date'].strftime('%A, %B %-d %Y')}
|
41
|
-
#{latest.data['title']}
|
42
|
-
#{url}
|
43
|
-
TWEET
|
44
|
-
end
|
45
|
-
|
46
|
-
def set_credentials!
|
47
|
-
@client ||= ::Twitter::REST::Client.new do |settings|
|
48
|
-
settings.consumer_key = @creds['consumer_api_key']
|
49
|
-
settings.consumer_secret = @creds['consumer_api_secret']
|
50
|
-
settings.access_token = @creds['access_token']
|
51
|
-
settings.access_token_secret = @creds['access_token_secret']
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def extract_from_env
|
56
|
-
values = cred_fieldnames.map { |k| ENV[k.upcase] }
|
57
|
-
|
58
|
-
return nil if values.any? { |v| v.nil? || v.empty? }
|
59
|
-
|
60
|
-
Hash[cred_fieldnames.zip(values)]
|
61
|
-
end
|
62
|
-
|
63
|
-
def extract_from_config
|
64
|
-
values = cred_fieldnames.map do |k|
|
65
|
-
Recker.shell(Configuration.twitter["#{k}_cmd"]).strip
|
66
|
-
end
|
67
|
-
|
68
|
-
return nil if values.any? { |v| v.nil? || v.empty? }
|
69
|
-
|
70
|
-
Hash[cred_fieldnames.zip(values)]
|
71
|
-
end
|
72
|
-
|
73
|
-
def cred_fieldnames
|
74
|
-
%w[
|
75
|
-
access_token_secret
|
76
|
-
access_token
|
77
|
-
consumer_api_key
|
78
|
-
consumer_api_secret
|
79
|
-
]
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|