jekyll-recker 1.7.0 → 1.12.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/_includes/figure.html +1 -1
- data/lib/jekyll-recker.rb +13 -15
- data/lib/jekyll_recker/commands.rb +21 -22
- data/lib/jekyll_recker/filters.rb +12 -9
- data/lib/jekyll_recker/generators.rb +125 -84
- data/lib/jekyll_recker/mixins.rb +26 -31
- data/lib/jekyll_recker/shell.rb +5 -8
- data/lib/jekyll_recker/social.rb +137 -129
- data/lib/jekyll_recker/tags.rb +7 -9
- data/lib/jekyll_recker/version.rb +2 -4
- metadata +30 -5
- data/lib/jekyll_recker/configuration.rb +0 -39
- data/lib/jekyll_recker/error.rb +0 -8
- data/lib/jekyll_recker/words.rb +0 -82
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0acecf9f429bcd83a0cbe8204e046bee16c5a30de1e458b4080db7502e3a831
|
|
4
|
+
data.tar.gz: 2b579e98cd7b81c71f063652a45b791708825b58d6ba83d2146ab2f321b0ce2e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a8b792c90336432c126993937c45dafcb88b1741bfbe2f0eafb32f8c6cc7607d402c442a782409b69a52664cbffe886cf8be39efff0890c15a2f96d84c5f83a9
|
|
7
|
+
data.tar.gz: 14da6696ecf19dc25ea9d02a7ef1904c7e975f8137f0a41ee333da524ff1d242391673a2d6c31d81a77a0ce11d45aed03677b7173e24dae6a91716255f146689
|
data/_includes/figure.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{%- if include.url %}
|
|
3
3
|
<a href="{{ include.url }}">
|
|
4
4
|
{%- endif %}
|
|
5
|
-
<img alt="{{ alt | default: include.filename }}" src="{{ site.baseurl }}assets/images/{{ include.filename }}"/>
|
|
5
|
+
<img alt="{{ include.alt | default: include.filename }}" src="{{ site.baseurl }}assets/images/{{ include.filename }}"/>
|
|
6
6
|
{%- if include.url %}
|
|
7
7
|
</a>
|
|
8
8
|
{%- endif %}
|
data/lib/jekyll-recker.rb
CHANGED
|
@@ -2,20 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
require 'jekyll'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
# jekyll-recker
|
|
6
|
+
#
|
|
7
|
+
# The greatest jekyll plugin in the world
|
|
8
|
+
module JekyllRecker
|
|
9
|
+
autoload :Mixins, 'jekyll_recker/mixins.rb'
|
|
10
|
+
autoload :Shell, 'jekyll_recker/shell.rb'
|
|
11
|
+
autoload :Social, 'jekyll_recker/social.rb'
|
|
12
|
+
autoload :VERSION, 'jekyll_recker/version.rb'
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
require 'jekyll_recker/shell.rb'
|
|
16
|
-
require 'jekyll_recker/social.rb'
|
|
17
|
-
require 'jekyll_recker/tags.rb'
|
|
18
|
-
require 'jekyll_recker/version.rb'
|
|
19
|
-
require 'jekyll_recker/words.rb'
|
|
20
|
-
end
|
|
14
|
+
# Eager loads!
|
|
15
|
+
require 'jekyll_recker/commands.rb'
|
|
16
|
+
require 'jekyll_recker/filters.rb'
|
|
17
|
+
require 'jekyll_recker/generators.rb'
|
|
18
|
+
require 'jekyll_recker/tags.rb'
|
|
21
19
|
end
|
|
@@ -1,30 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
include Mixins::Logging
|
|
3
|
+
module JekyllRecker
|
|
4
|
+
# Commands
|
|
5
|
+
module Commands
|
|
6
|
+
# Share
|
|
7
|
+
class Share < Jekyll::Command
|
|
8
|
+
include Mixins::Logging
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
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 { |args, opts| action(args, opts) }
|
|
18
16
|
end
|
|
17
|
+
end
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
def self.action(args, options)
|
|
20
|
+
site = Jekyll::Site.new(configuration_from_options(options))
|
|
21
|
+
site.reset
|
|
22
|
+
site.read
|
|
23
|
+
Social.action(site, args, options)
|
|
24
|
+
rescue StandardError => e
|
|
25
|
+
logger.error e.message
|
|
26
|
+
exit 1
|
|
28
27
|
end
|
|
29
28
|
end
|
|
30
29
|
end
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
module JekyllRecker
|
|
4
|
+
# Filters
|
|
5
|
+
module Filters
|
|
6
|
+
# Converts a date object to standard Uhh Yeah Dude format.
|
|
7
|
+
def uyd_date(date)
|
|
8
|
+
date.strftime('%A, %B %d %Y')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Adds commas to a number
|
|
12
|
+
def pretty(num)
|
|
13
|
+
num.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
16
|
end
|
|
14
17
|
|
|
15
|
-
Liquid::Template.register_filter(
|
|
18
|
+
Liquid::Template.register_filter(JekyllRecker::Filters)
|
|
@@ -1,111 +1,152 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
require 'mini_magick'
|
|
4
|
+
require 'fastimage'
|
|
5
|
+
|
|
6
|
+
module JekyllRecker
|
|
7
|
+
module Generators
|
|
8
|
+
# Image Resize Generator
|
|
9
|
+
class ImageResize < Jekyll::Generator
|
|
10
|
+
include Mixins::Logging
|
|
11
|
+
|
|
12
|
+
def generate(site)
|
|
13
|
+
@site = site
|
|
14
|
+
logger.info 'checking images'
|
|
15
|
+
resizeable_images.each do |f, d|
|
|
16
|
+
logger.info "resizing #{f} to fit #{d}"
|
|
17
|
+
image = MiniMagick::Image.new(f)
|
|
18
|
+
image.resize d
|
|
16
19
|
end
|
|
20
|
+
end
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@site.data['stats'] ||= {}
|
|
22
|
-
@site.data['stats'][key] = crunch
|
|
23
|
-
end
|
|
22
|
+
def image?(file)
|
|
23
|
+
['.jpg', 'jpeg', '.png', '.svg'].include? File.extname(file)
|
|
24
|
+
end
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
def too_big?(width, height)
|
|
27
|
+
width > 800 || height > 800
|
|
28
|
+
end
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
# @return [Numeric] rounded, calculated average of numlist.
|
|
33
|
-
def average(numlist)
|
|
34
|
-
calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
|
|
35
|
-
calc.round
|
|
36
|
-
end
|
|
30
|
+
def images
|
|
31
|
+
@site.static_files.collect(&:path).select { |f| image?(f) }
|
|
32
|
+
end
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
def resizeable_images
|
|
35
|
+
with_sizes = images.map { |f| [f, FastImage.size(f)].flatten }
|
|
36
|
+
with_sizes.select! { |f| too_big?(f[1], f[2]) }
|
|
37
|
+
with_sizes.map do |f, w, h|
|
|
38
|
+
dimensions = if w > h
|
|
39
|
+
'800x600'
|
|
40
|
+
else
|
|
41
|
+
'600x800'
|
|
42
|
+
end
|
|
43
|
+
[f, dimensions]
|
|
44
44
|
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
# Stats Module
|
|
49
|
+
#
|
|
50
|
+
# Functions for stats generators.
|
|
51
|
+
# @abstract
|
|
52
|
+
module Stats
|
|
53
|
+
include Mixins::Logging
|
|
54
|
+
include Jekyll::Filters
|
|
55
|
+
|
|
56
|
+
def key
|
|
57
|
+
self.class.const_get(:KEY)
|
|
49
58
|
end
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
def generate(site)
|
|
61
|
+
@site = site
|
|
62
|
+
logger.info "crunching stats.#{key}"
|
|
63
|
+
@site.data['stats'] ||= {}
|
|
64
|
+
@site.data['stats'][key] = crunch
|
|
65
|
+
end
|
|
54
66
|
|
|
55
|
-
|
|
67
|
+
def crunch
|
|
68
|
+
raise NotImplementedError, '#crunch not implemented!'
|
|
69
|
+
end
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
# Calculates the average of a list of numbers.
|
|
72
|
+
#
|
|
73
|
+
# @param [Array<Numeric>] numlist list of numbers to be averaged.
|
|
74
|
+
# @return [Numeric] rounded, calculated average of numlist.
|
|
75
|
+
def average(numlist)
|
|
76
|
+
calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
|
|
77
|
+
calc.round
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Calculates the total of a list of numbers.
|
|
81
|
+
#
|
|
82
|
+
# @param [Array<Numeric>] numlist list of numbers to be totaled.
|
|
83
|
+
# @return [Numeric] calculated total of numlist.
|
|
84
|
+
def total(numlist)
|
|
85
|
+
numlist.inject(0) { |sum, x| sum + x }
|
|
60
86
|
end
|
|
61
87
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
88
|
+
def entries
|
|
89
|
+
@site.posts.docs.select(&:published?)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
65
92
|
|
|
66
|
-
|
|
93
|
+
# Post Count Generator
|
|
94
|
+
class PostCount < Jekyll::Generator
|
|
95
|
+
include Stats
|
|
67
96
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'total' => total(total_counts).pretty
|
|
73
|
-
}
|
|
74
|
-
end
|
|
97
|
+
KEY = 'posts'
|
|
98
|
+
|
|
99
|
+
def crunch
|
|
100
|
+
entries.count
|
|
75
101
|
end
|
|
102
|
+
end
|
|
76
103
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
104
|
+
# Word Count Generator
|
|
105
|
+
class Words < Jekyll::Generator
|
|
106
|
+
include Stats
|
|
80
107
|
|
|
81
|
-
|
|
108
|
+
KEY = 'words'
|
|
82
109
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
end
|
|
110
|
+
def crunch
|
|
111
|
+
total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
|
|
112
|
+
{
|
|
113
|
+
'average' => average(total_counts),
|
|
114
|
+
'total' => total(total_counts)
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
end
|
|
92
118
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
curr != prev - 1
|
|
99
|
-
end.each do |dates|
|
|
100
|
-
first, last = dates.minmax
|
|
101
|
-
_streaks << [(last - first).to_i, [first, last]]
|
|
102
|
-
end
|
|
103
|
-
_streaks
|
|
104
|
-
end
|
|
119
|
+
# Streak Count Generator
|
|
120
|
+
class Streaks < Jekyll::Generator
|
|
121
|
+
include Stats
|
|
122
|
+
|
|
123
|
+
KEY = 'days'
|
|
105
124
|
|
|
106
|
-
|
|
107
|
-
|
|
125
|
+
def crunch
|
|
126
|
+
streaks.take(1).map do |count, dates|
|
|
127
|
+
{
|
|
128
|
+
'days' => count,
|
|
129
|
+
'start' => dates[0],
|
|
130
|
+
'end' => dates[1]
|
|
131
|
+
}
|
|
132
|
+
end.first
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
def streaks
|
|
138
|
+
_streaks = []
|
|
139
|
+
entry_dates.slice_when do |prev, curr|
|
|
140
|
+
curr != prev - 1
|
|
141
|
+
end.each do |dates|
|
|
142
|
+
first, last = dates.minmax
|
|
143
|
+
_streaks << [(last - first).to_i, [first, last]]
|
|
108
144
|
end
|
|
145
|
+
_streaks
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def entry_dates
|
|
149
|
+
entries.collect(&:date).map { |t| Date.new(t.year, t.month, t.day) }.sort.reverse
|
|
109
150
|
end
|
|
110
151
|
end
|
|
111
152
|
end
|
data/lib/jekyll_recker/mixins.rb
CHANGED
|
@@ -2,43 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
require 'logger'
|
|
4
4
|
|
|
5
|
-
module
|
|
6
|
-
module
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def descendants
|
|
15
|
-
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
|
16
|
-
end
|
|
5
|
+
module JekyllRecker
|
|
6
|
+
module Mixins
|
|
7
|
+
# Introspection
|
|
8
|
+
#
|
|
9
|
+
# Adds functions which let the class see things about itself.
|
|
10
|
+
module Introspection
|
|
11
|
+
def self.included(base)
|
|
12
|
+
base.extend(self)
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end
|
|
15
|
+
# Get the class instance
|
|
16
|
+
def class_name
|
|
17
|
+
self.class.name.split('::').last
|
|
18
|
+
end
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
# Get a list of all classes which inherit from this class
|
|
21
|
+
def descendants
|
|
22
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
|
28
23
|
end
|
|
24
|
+
end
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
# Logging
|
|
27
|
+
module Logging
|
|
28
|
+
def self.included(base)
|
|
29
|
+
base.extend(self)
|
|
30
|
+
end
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
end
|
|
32
|
+
def logger
|
|
33
|
+
@logger ||= Logger.new(
|
|
34
|
+
STDOUT,
|
|
35
|
+
formatter: proc { |_severity, _datetime, _progname, msg| "jekyll-recker: #{msg}\n" }
|
|
36
|
+
)
|
|
42
37
|
end
|
|
43
38
|
end
|
|
44
39
|
end
|
data/lib/jekyll_recker/shell.rb
CHANGED
|
@@ -2,13 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require 'open3'
|
|
4
4
|
|
|
5
|
-
module
|
|
6
|
-
#
|
|
7
|
-
module
|
|
8
|
-
|
|
9
|
-
class ShellCommandFailed < ReckerError; end
|
|
10
|
-
|
|
11
|
-
def self.shell(cmd)
|
|
5
|
+
module JekyllRecker
|
|
6
|
+
# Shell
|
|
7
|
+
module Shell
|
|
8
|
+
def self.run(cmd)
|
|
12
9
|
out, err, status = Open3.capture3(cmd)
|
|
13
10
|
return out if status.success?
|
|
14
11
|
|
|
@@ -22,7 +19,7 @@ module Jekyll
|
|
|
22
19
|
#{err}
|
|
23
20
|
ERROR
|
|
24
21
|
|
|
25
|
-
raise
|
|
22
|
+
raise msg
|
|
26
23
|
end
|
|
27
24
|
end
|
|
28
25
|
end
|
data/lib/jekyll_recker/social.rb
CHANGED
|
@@ -3,170 +3,178 @@
|
|
|
3
3
|
require 'slack-notifier'
|
|
4
4
|
require 'twitter'
|
|
5
5
|
|
|
6
|
-
module
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# @abstract
|
|
14
|
-
class Share
|
|
15
|
-
include Mixins::Introspection
|
|
16
|
-
include Mixins::Logging
|
|
17
|
-
|
|
18
|
-
def self.share(dry: false)
|
|
19
|
-
backend = new(dry: dry)
|
|
20
|
-
logger.info "#{backend.name} - building configuration"
|
|
21
|
-
backend.configure!
|
|
22
|
-
|
|
23
|
-
logger.info "#{backend.name} - sharing \"#{backend.latest_title}\""
|
|
24
|
-
backend.post!
|
|
25
|
-
end
|
|
6
|
+
module JekyllRecker
|
|
7
|
+
module Social
|
|
8
|
+
def self.action(site, args, options)
|
|
9
|
+
args += %w[slack twitter] if args.empty?
|
|
10
|
+
Slack.share(site, dry: options['dry']) if args.include?('slack')
|
|
11
|
+
Twitter.share(site, dry: options['dry']) if args.include?('twitter')
|
|
12
|
+
end
|
|
26
13
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
# Backend
|
|
15
|
+
#
|
|
16
|
+
# Backend base class for social sharing backends.
|
|
17
|
+
# @abstract
|
|
18
|
+
class Share
|
|
19
|
+
include Mixins::Introspection
|
|
20
|
+
include Mixins::Logging
|
|
21
|
+
|
|
22
|
+
def self.share(site, dry: false)
|
|
23
|
+
backend = new(site, dry: dry)
|
|
24
|
+
logger.info "#{backend.name} - building configuration"
|
|
25
|
+
backend.configure!
|
|
26
|
+
|
|
27
|
+
logger.info "#{backend.name} - sharing \"#{backend.latest_title}\""
|
|
28
|
+
backend.post!
|
|
29
|
+
end
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
def initialize(site, dry: false)
|
|
32
|
+
@site = site
|
|
33
|
+
@dry = dry
|
|
34
|
+
end
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
def dry?
|
|
37
|
+
@dry
|
|
38
|
+
end
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
alias name config_key
|
|
43
|
-
|
|
44
|
-
def post_body
|
|
45
|
-
url = File.join Configuration.jekyll['url'], latest.url
|
|
46
|
-
<<~BODY
|
|
47
|
-
#{latest.data['date'].strftime('%A, %B %-d %Y')}
|
|
48
|
-
#{latest.data['title']}
|
|
49
|
-
#{url}
|
|
50
|
-
BODY
|
|
51
|
-
end
|
|
40
|
+
def config
|
|
41
|
+
@site.config.fetch('recker', {}).fetch(config_key, {})
|
|
42
|
+
end
|
|
52
43
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
def config_key
|
|
45
|
+
class_name.downcase
|
|
46
|
+
end
|
|
47
|
+
alias name config_key
|
|
48
|
+
|
|
49
|
+
def post_body
|
|
50
|
+
url = File.join @site.config['url'], latest.url
|
|
51
|
+
<<~BODY
|
|
52
|
+
#{latest.data['date'].strftime('%A, %B %-d %Y')}
|
|
53
|
+
#{latest.data['title']}
|
|
54
|
+
#{url}
|
|
55
|
+
BODY
|
|
56
|
+
end
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
def latest
|
|
59
|
+
@latest ||= @site.posts.docs.last
|
|
60
|
+
end
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
def latest_title
|
|
63
|
+
latest.data['title']
|
|
64
|
+
end
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
end
|
|
66
|
+
def configure!
|
|
67
|
+
raise NotImplementedError
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def configure!
|
|
75
|
-
@creds = {}
|
|
76
|
-
workspaces.each do |key, data|
|
|
77
|
-
webhook = ENV["SLACK_#{key.upcase}_WEBHOOK"] || extract_from_config(data)
|
|
78
|
-
if webhook.nil?
|
|
79
|
-
raise ReckerError, "cannot find slack webhook for #{key} workspace!"
|
|
80
|
-
end
|
|
70
|
+
def post!
|
|
71
|
+
raise NotImplementedError
|
|
72
|
+
end
|
|
73
|
+
end
|
|
81
74
|
|
|
82
|
-
|
|
75
|
+
# Slack
|
|
76
|
+
#
|
|
77
|
+
# Slack social sharing backend
|
|
78
|
+
class Slack < Share
|
|
79
|
+
def configure!
|
|
80
|
+
@creds = {}
|
|
81
|
+
workspaces.each do |key, data|
|
|
82
|
+
webhook = ENV["SLACK_#{key.upcase}_WEBHOOK"] || extract_from_config(data)
|
|
83
|
+
if webhook.nil?
|
|
84
|
+
raise "cannot find slack webhook for #{key} workspace!"
|
|
83
85
|
end
|
|
86
|
+
|
|
87
|
+
@creds[key] = webhook
|
|
84
88
|
end
|
|
89
|
+
end
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
end
|
|
91
|
+
def post!
|
|
92
|
+
message_body = ::Slack::Notifier::Util::LinkFormatter.format(post_body)
|
|
93
|
+
workspaces.each do |key, config|
|
|
94
|
+
logger.info "posting to #{key} workspace"
|
|
95
|
+
if @dry
|
|
96
|
+
logger.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
|
|
97
|
+
else
|
|
98
|
+
::Slack::Notifier.new(
|
|
99
|
+
@creds[key].strip,
|
|
100
|
+
channel: config.fetch('channel'),
|
|
101
|
+
username: config.fetch('username'),
|
|
102
|
+
icon_emoji: config.fetch('emoji')
|
|
103
|
+
).post(text: message_body)
|
|
100
104
|
end
|
|
101
105
|
end
|
|
106
|
+
end
|
|
102
107
|
|
|
103
|
-
|
|
108
|
+
private
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
def extract_from_config(data)
|
|
111
|
+
cmd = data['webhook_cmd']
|
|
112
|
+
return nil if cmd.nil?
|
|
108
113
|
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
Shell.run(cmd)
|
|
115
|
+
end
|
|
111
116
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
end
|
|
117
|
+
def workspaces
|
|
118
|
+
config.each
|
|
115
119
|
end
|
|
120
|
+
end
|
|
116
121
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
# Twitter
|
|
123
|
+
#
|
|
124
|
+
# Twitter social sharing backend
|
|
125
|
+
class Twitter < Share
|
|
126
|
+
def configure!
|
|
127
|
+
creds = extract_from_env || extract_from_config
|
|
128
|
+
raise 'cannot find twitter credentials!' if creds.nil?
|
|
124
129
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
end
|
|
130
|
+
@client = ::Twitter::REST::Client.new do |settings|
|
|
131
|
+
settings.consumer_key = creds['consumer_api_key']
|
|
132
|
+
settings.consumer_secret = creds['consumer_api_secret']
|
|
133
|
+
settings.access_token = creds['access_token']
|
|
134
|
+
settings.access_token_secret = creds['access_token_secret']
|
|
131
135
|
end
|
|
136
|
+
end
|
|
132
137
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
end
|
|
138
|
+
def post!
|
|
139
|
+
if dry?
|
|
140
|
+
logger.info('tweeting in dry mode, printing message')
|
|
141
|
+
logger.info("BEGIN TWEET\n#{post_body}END TWEET")
|
|
142
|
+
else
|
|
143
|
+
@client.update(post_body)
|
|
140
144
|
end
|
|
145
|
+
end
|
|
141
146
|
|
|
142
|
-
|
|
147
|
+
private
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
def extract_from_env
|
|
150
|
+
values = cred_fieldnames.map { |k| ENV["TWITTER_#{k.upcase}"] }
|
|
146
151
|
|
|
147
|
-
|
|
152
|
+
return nil if values.any? { |v| v.nil? || v.empty? }
|
|
153
|
+
|
|
154
|
+
Hash[cred_fieldnames.zip(values)]
|
|
155
|
+
end
|
|
148
156
|
|
|
149
|
-
|
|
157
|
+
def extract_from_config
|
|
158
|
+
values = cred_fieldnames.map do |k|
|
|
159
|
+
Shell.run(twitter_config["#{k}_cmd"]).strip
|
|
150
160
|
end
|
|
151
161
|
|
|
152
|
-
|
|
153
|
-
values = cred_fieldnames.map do |k|
|
|
154
|
-
Recker.shell(Configuration.twitter["#{k}_cmd"]).strip
|
|
155
|
-
end
|
|
162
|
+
return nil if values.any? { |v| v.nil? || v.empty? }
|
|
156
163
|
|
|
157
|
-
|
|
164
|
+
Hash[cred_fieldnames.zip(values)]
|
|
165
|
+
end
|
|
158
166
|
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
def twitter_config
|
|
168
|
+
@site.config.fetch('recker', {}).fetch('twitter', {})
|
|
169
|
+
end
|
|
161
170
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
end
|
|
171
|
+
def cred_fieldnames
|
|
172
|
+
%w[
|
|
173
|
+
access_token_secret
|
|
174
|
+
access_token
|
|
175
|
+
consumer_api_key
|
|
176
|
+
consumer_api_secret
|
|
177
|
+
]
|
|
170
178
|
end
|
|
171
179
|
end
|
|
172
180
|
end
|
data/lib/jekyll_recker/tags.rb
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
VERSION
|
|
10
|
-
end
|
|
3
|
+
module JekyllRecker
|
|
4
|
+
module Tags
|
|
5
|
+
# Returns the VERSION of the running jekyll-recker gem.
|
|
6
|
+
class Version < Liquid::Tag
|
|
7
|
+
def render(_context)
|
|
8
|
+
VERSION
|
|
11
9
|
end
|
|
12
10
|
end
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
|
|
16
|
-
Liquid::Template.register_tag('recker_version',
|
|
14
|
+
Liquid::Template.register_tag('recker_version', JekyllRecker::Tags::Version)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-recker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex Recker
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-07-
|
|
11
|
+
date: 2020-07-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bump
|
|
@@ -94,6 +94,20 @@ dependencies:
|
|
|
94
94
|
- - ">="
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: fastimage
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
97
111
|
- !ruby/object:Gem::Dependency
|
|
98
112
|
name: jekyll
|
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +122,20 @@ dependencies:
|
|
|
108
122
|
- - "~>"
|
|
109
123
|
- !ruby/object:Gem::Version
|
|
110
124
|
version: '3.8'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: mini_magick
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :runtime
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
111
139
|
- !ruby/object:Gem::Dependency
|
|
112
140
|
name: slack-notifier
|
|
113
141
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -156,8 +184,6 @@ files:
|
|
|
156
184
|
- _layouts/post.html
|
|
157
185
|
- lib/jekyll-recker.rb
|
|
158
186
|
- lib/jekyll_recker/commands.rb
|
|
159
|
-
- lib/jekyll_recker/configuration.rb
|
|
160
|
-
- lib/jekyll_recker/error.rb
|
|
161
187
|
- lib/jekyll_recker/filters.rb
|
|
162
188
|
- lib/jekyll_recker/generators.rb
|
|
163
189
|
- lib/jekyll_recker/mixins.rb
|
|
@@ -165,7 +191,6 @@ files:
|
|
|
165
191
|
- lib/jekyll_recker/social.rb
|
|
166
192
|
- lib/jekyll_recker/tags.rb
|
|
167
193
|
- lib/jekyll_recker/version.rb
|
|
168
|
-
- lib/jekyll_recker/words.rb
|
|
169
194
|
homepage: https://www.github.com/arecker/jekyll-recker/
|
|
170
195
|
licenses:
|
|
171
196
|
- GPLv3
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Jekyll
|
|
4
|
-
module Recker
|
|
5
|
-
# Configuration
|
|
6
|
-
module Configuration
|
|
7
|
-
def self.jekyll
|
|
8
|
-
@jekyll ||= Jekyll.configuration
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def self.recker
|
|
12
|
-
jekyll.fetch('recker', {})
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def self.facebook
|
|
16
|
-
recker.fetch('facebook', {})
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def self.twitter
|
|
20
|
-
recker.fetch('twitter', {})
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.slack
|
|
24
|
-
recker.fetch('slack', {})
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.site
|
|
28
|
-
@site = Jekyll::Site.new(jekyll)
|
|
29
|
-
@site.reset
|
|
30
|
-
@site.read
|
|
31
|
-
@site
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.latest_post
|
|
35
|
-
@latest_post ||= site.posts.docs.last
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
data/lib/jekyll_recker/error.rb
DELETED
data/lib/jekyll_recker/words.rb
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Jekyll
|
|
4
|
-
module Recker
|
|
5
|
-
# Words
|
|
6
|
-
module Words
|
|
7
|
-
def self.array_to_and_list(array)
|
|
8
|
-
case array.length
|
|
9
|
-
when 0
|
|
10
|
-
''
|
|
11
|
-
when 1
|
|
12
|
-
array.first
|
|
13
|
-
when 2
|
|
14
|
-
"#{array.first} and #{array.last}"
|
|
15
|
-
else
|
|
16
|
-
array[0...-1].join(', ') + ", and #{array.last}"
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def self.and_list_to_array(str)
|
|
21
|
-
str = str.gsub(' and ', ', ')
|
|
22
|
-
str.split(',').map(&:strip).reject(&:empty?)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.prettify_number(number)
|
|
26
|
-
number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def self.prettify_path(path, home = nil)
|
|
30
|
-
home ||= File.expand_path('~/')
|
|
31
|
-
path.sub(home, '~')
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.to_word_list(str)
|
|
35
|
-
str.split(' ')
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def self.to_weighted_list(arr)
|
|
39
|
-
arr.uniq.map do |word|
|
|
40
|
-
[word, arr.count(word)]
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Array extensions
|
|
48
|
-
class Array
|
|
49
|
-
def to_and_list
|
|
50
|
-
Jekyll::Recker::Words.array_to_and_list(self)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def to_weighted_list
|
|
54
|
-
Jekyll::Recker::Words.to_weighted_list(self)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Integer extensions
|
|
59
|
-
class Integer
|
|
60
|
-
def pretty
|
|
61
|
-
Jekyll::Recker::Words.prettify_number(self)
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# String extensions
|
|
66
|
-
class String
|
|
67
|
-
def words
|
|
68
|
-
Jekyll::Recker::Words.to_word_list(self)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def word_count
|
|
72
|
-
Jekyll::Recker::Words.to_word_list(self).count
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def pretty_path(home = nil)
|
|
76
|
-
Jekyll::Recker::Words.prettify_path(self, home)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def to_and_array
|
|
80
|
-
Jekyll::Recker::Words.and_list_to_array(self)
|
|
81
|
-
end
|
|
82
|
-
end
|