jekyll-recker 1.3.0 → 1.9.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 +4 -4
- data/_includes/figure.html +14 -0
- data/_includes/head.html +21 -0
- 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 +15 -16
- data/lib/jekyll_recker/commands.rb +17 -64
- data/lib/jekyll_recker/configuration.rb +27 -25
- data/lib/jekyll_recker/error.rb +3 -5
- data/lib/jekyll_recker/filters.rb +18 -0
- data/lib/jekyll_recker/generators.rb +83 -85
- data/lib/jekyll_recker/mixins.rb +33 -19
- data/lib/jekyll_recker/shell.rb +5 -5
- data/lib/jekyll_recker/social.rb +175 -0
- data/lib/jekyll_recker/tags.rb +7 -9
- data/lib/jekyll_recker/version.rb +2 -4
- metadata +7 -7
- data/_layouts/default.html +0 -14
- data/lib/jekyll_recker/logger.rb +0 -20
- data/lib/jekyll_recker/slack.rb +0 -70
- data/lib/jekyll_recker/twitter.rb +0 -83
- 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: bc0bc14a94bfceaa78cca2b93c977b7f54ec9b25f40aead7be6462eb0ccb01cb
|
|
4
|
+
data.tar.gz: 280235bc9e48a76f7e7a8731e7737fa3a5618cee5f14d39a6b427b6ec22bb93d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6f469867ce018439e8bbde4406f627e643c969cd65f1d33e70efa966db22c7e2fa3e0f8930e5e23af2861fa88fc68b34072cf37d6646d8e58f0ee5038e006a42
|
|
7
|
+
data.tar.gz: 2bf8be1723090a4350ec2945d4cd615395f819e7442ab1cb116a3c626003ab3613ee6f60b0c83c3e287a5d995e4f2947da6c4205df45af96c95e15d141fa1567
|
data/README.md
CHANGED
|
@@ -95,10 +95,10 @@ Configure the tweet share in `_config.yml`.
|
|
|
95
95
|
|
|
96
96
|
Alternatively, ensure these environment variables are set.
|
|
97
97
|
|
|
98
|
-
export
|
|
99
|
-
export
|
|
100
|
-
export
|
|
101
|
-
export
|
|
98
|
+
export TWITTER_ACCESS_TOKEN_SECRET="..."
|
|
99
|
+
export TWITTER_ACCESS_TOKEN="..."
|
|
100
|
+
export TWITTER_CONSUMER_API_KEY="..."
|
|
101
|
+
export TWITTER_CONSUMER_API_SECRET="..."
|
|
102
102
|
|
|
103
103
|
[example slack]: screenshots/example-slack.png
|
|
104
104
|
[example tweet]: screenshots/example-tweet.png
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<figure>
|
|
2
|
+
{%- if include.url %}
|
|
3
|
+
<a href="{{ include.url }}">
|
|
4
|
+
{%- endif %}
|
|
5
|
+
<img alt="{{ include.alt | default: include.filename }}" src="{{ site.baseurl }}assets/images/{{ include.filename }}"/>
|
|
6
|
+
{%- if include.url %}
|
|
7
|
+
</a>
|
|
8
|
+
{%- endif %}
|
|
9
|
+
{%- if include.caption %}
|
|
10
|
+
<figcaption>
|
|
11
|
+
<p>{{ include.caption }}</p>
|
|
12
|
+
</figcaption>
|
|
13
|
+
{%- endif %}
|
|
14
|
+
</figure>
|
data/_includes/head.html
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{%- capture title %}{{ include.title | default: page.title }}{%- endcapture %}
|
|
2
|
+
{%- capture description %}{{ include.description | default: site.description }}{%- endcapture %}
|
|
3
|
+
{%- capture image %}{{ include.image | default: page.image }}{%- endcapture %}
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8"/>
|
|
6
|
+
<title>{{ title }} | {{ description }}</title>
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<meta name="twitter:card" content="summary" />
|
|
9
|
+
<meta name="twitter:site" content="@{{ site.twitter_username }}" />
|
|
10
|
+
<meta name="twitter:title" content="{{ include.title }}" />
|
|
11
|
+
<meta name="twitter:description" content="{{ include.description }}" />
|
|
12
|
+
<meta property="og:url" content="{{ site.url }}{{ page.url }}" />
|
|
13
|
+
<meta property="og:type" content="article" />
|
|
14
|
+
<meta property="og:title" content="{{ title }}"/>
|
|
15
|
+
<meta property="og:description" content="{{ description }}" />
|
|
16
|
+
{%- if image %}
|
|
17
|
+
<meta name="twitter:image" content="{{ site.url }}{{ site.base_url }}/assets/images/{{ image }}"/>
|
|
18
|
+
<meta property="og:image" content="{{ site.url }}{{ site.base_url }}/assets/images/{{ image }}"/>
|
|
19
|
+
{%- endif %}
|
|
20
|
+
<link href="{{ site.baseurl }}/assets/jekyll-recker.css" rel="stylesheet"/>
|
|
21
|
+
</head>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<nav class="clearfix">
|
|
2
|
+
{%- if page.next -%}
|
|
3
|
+
<a href="{{ page.next.url }}">
|
|
4
|
+
⟵ {{ page.next.slug }}
|
|
5
|
+
</a>
|
|
6
|
+
{%- endif -%}
|
|
7
|
+
{%- if page.previous -%}
|
|
8
|
+
<a class="float-right" href="{{ page.previous.url }}">
|
|
9
|
+
{{ page.previous.slug }} ⟶
|
|
10
|
+
</a>
|
|
11
|
+
{%- endif -%}
|
|
12
|
+
</nav>
|
|
13
|
+
|
data/_layouts/home.html
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
{% include head.html title=site.title %}
|
|
4
|
+
<body>
|
|
5
|
+
{% include header.html title=site.title subtitle=site.description %}
|
|
6
|
+
<hr/>
|
|
7
|
+
{% include nav.html %}
|
|
8
|
+
<hr/>
|
|
9
|
+
{{ content }}
|
|
10
|
+
<hr/>
|
|
11
|
+
{% include footer.html %}
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
data/_layouts/page.html
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
{% include head.html title=site.title %}
|
|
4
|
+
<body>
|
|
5
|
+
{% include header.html title=page.title subtitle=page.description %}
|
|
6
|
+
<hr/>
|
|
7
|
+
{% include nav.html %}
|
|
8
|
+
<hr/>
|
|
9
|
+
{{ content }}
|
|
10
|
+
<hr/>
|
|
11
|
+
{% include footer.html %}
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
data/_layouts/post.html
CHANGED
|
@@ -1,28 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
{%
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
{
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</a>
|
|
22
|
-
{%- endif -%}
|
|
23
|
-
{%- if page.previous -%}
|
|
24
|
-
<a class="float-right" href="{{ page.previous.url }}">
|
|
25
|
-
{{ page.previous.slug }} ⟶
|
|
26
|
-
</a>
|
|
27
|
-
</nav>
|
|
28
|
-
{%- endif -%}
|
|
1
|
+
{%- capture datestring %}{{ page.date | uyd_date }}{% endcapture %}
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
{% include head.html title=datestring description=page.title %}
|
|
5
|
+
<body>
|
|
6
|
+
{% include header.html title=datestring subtitle=page.title %}
|
|
7
|
+
<hr/>
|
|
8
|
+
{% include nav.html %}
|
|
9
|
+
<hr/>
|
|
10
|
+
{%- if page.image -%}
|
|
11
|
+
<br/>
|
|
12
|
+
{% include figure.html filename=page.image %}
|
|
13
|
+
<br/>
|
|
14
|
+
{%- endif -%}
|
|
15
|
+
{{ content }}
|
|
16
|
+
{% include pager.html %}
|
|
17
|
+
<hr/>
|
|
18
|
+
{% include footer.html %}
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
data/lib/jekyll-recker.rb
CHANGED
|
@@ -2,21 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
require 'jekyll'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
# jekyll-recker
|
|
6
|
+
#
|
|
7
|
+
# The greatest jekyll plugin in the world
|
|
8
|
+
module JekyllRecker
|
|
9
|
+
autoload :Configuration, 'jekyll_recker/configuration.rb'
|
|
10
|
+
autoload :Error, 'jekyll_recker/error.rb'
|
|
11
|
+
autoload :Mixins, 'jekyll_recker/mixins.rb'
|
|
12
|
+
autoload :Shell, 'jekyll_recker/shell.rb'
|
|
13
|
+
autoload :Social, 'jekyll_recker/social.rb'
|
|
14
|
+
autoload :VERSION, 'jekyll_recker/version.rb'
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
require 'jekyll_recker/slack.rb'
|
|
17
|
-
require 'jekyll_recker/tags.rb'
|
|
18
|
-
require 'jekyll_recker/twitter.rb'
|
|
19
|
-
require 'jekyll_recker/version.rb'
|
|
20
|
-
require 'jekyll_recker/words.rb'
|
|
21
|
-
end
|
|
16
|
+
# Eager loads!
|
|
17
|
+
require 'jekyll_recker/commands.rb'
|
|
18
|
+
require 'jekyll_recker/filters.rb'
|
|
19
|
+
require 'jekyll_recker/generators.rb'
|
|
20
|
+
require 'jekyll_recker/tags.rb'
|
|
22
21
|
end
|
|
@@ -1,73 +1,26 @@
|
|
|
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
|
-
logger.info 'normally I\'d share here'
|
|
18
|
-
rescue ReckerError => e
|
|
19
|
-
logger.abort_with e.message
|
|
20
|
-
end
|
|
21
|
-
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) }
|
|
22
16
|
end
|
|
23
17
|
end
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
c.syntax 'slack'
|
|
31
|
-
c.description 'slack latest post'
|
|
32
|
-
c.option 'dry', '-d', '--dry', 'print message instead of posting'
|
|
33
|
-
c.action { |args, opts| action(args, opts) }
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def self.action(_args, options)
|
|
38
|
-
Recker::Slack.each_in_config(dry: options['dry']) do |client|
|
|
39
|
-
logger.info "#{client.key}: discovering webhook"
|
|
40
|
-
client.discover_webhook!
|
|
41
|
-
logger.info "#{client.key}: posting #{client.latest.data['title']}"
|
|
42
|
-
client.post_latest!
|
|
43
|
-
end
|
|
44
|
-
rescue ReckerError => e
|
|
45
|
-
logger.abort_with e.message
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Tweet
|
|
50
|
-
class Tweet < Jekyll::Command
|
|
51
|
-
include Mixins::Logging
|
|
52
|
-
|
|
53
|
-
def self.init_with_program(prog)
|
|
54
|
-
prog.command(:tweet) do |c|
|
|
55
|
-
c.syntax 'tweet'
|
|
56
|
-
c.description 'tweet latest post'
|
|
57
|
-
c.option 'dry', '-d', '--dry', 'print message instead of tweeting'
|
|
58
|
-
c.action { |args, opts| action(args, opts) }
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def self.action(_args, options)
|
|
63
|
-
client = Jekyll::Recker::Twitter.new(dry: options['dry'])
|
|
64
|
-
logger.info 'discovering credentials'
|
|
65
|
-
client.discover_credentials!
|
|
66
|
-
logger.info "tweeting #{client.latest.data['title']}"
|
|
67
|
-
client.post_latest!
|
|
68
|
-
rescue ReckerError => e
|
|
69
|
-
logger.abort_with e.message
|
|
70
|
-
end
|
|
19
|
+
def self.action(args, options)
|
|
20
|
+
JekyllRecker::Social.action(args, options)
|
|
21
|
+
rescue ::JekyllRecker::Error => e
|
|
22
|
+
logger.error e.message
|
|
23
|
+
exit 1
|
|
71
24
|
end
|
|
72
25
|
end
|
|
73
26
|
end
|
|
@@ -1,35 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
end
|
|
3
|
+
module JekyllRecker
|
|
4
|
+
# Configuration
|
|
5
|
+
module Configuration
|
|
6
|
+
def self.jekyll
|
|
7
|
+
@jekyll ||= Jekyll.configuration
|
|
8
|
+
end
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
def self.recker
|
|
11
|
+
jekyll.fetch('recker', {})
|
|
12
|
+
end
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
def self.facebook
|
|
15
|
+
recker.fetch('facebook', {})
|
|
16
|
+
end
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
def self.twitter
|
|
19
|
+
recker.fetch('twitter', {})
|
|
20
|
+
end
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
def self.slack
|
|
23
|
+
recker.fetch('slack', {})
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.site
|
|
27
|
+
@site = Jekyll::Site.new(jekyll)
|
|
28
|
+
@site.reset
|
|
29
|
+
@site.read
|
|
30
|
+
@site
|
|
31
|
+
end
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
+
def self.latest_post
|
|
34
|
+
@latest_post ||= site.posts.docs.last
|
|
33
35
|
end
|
|
34
36
|
end
|
|
35
37
|
end
|
data/lib/jekyll_recker/error.rb
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
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
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Liquid::Template.register_filter(JekyllRecker::Filters)
|
|
@@ -1,111 +1,109 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
module JekyllRecker
|
|
4
|
+
module Generators
|
|
5
|
+
# Stats Module
|
|
6
|
+
#
|
|
7
|
+
# Functions for stats generators.
|
|
8
|
+
# @abstract
|
|
9
|
+
module Stats
|
|
10
|
+
include Mixins::Logging
|
|
11
|
+
include Jekyll::Filters
|
|
12
|
+
|
|
13
|
+
def key
|
|
14
|
+
self.class.const_get(:KEY)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def generate(site)
|
|
18
|
+
@site = site
|
|
19
|
+
logger.info "crunching stats.#{key}"
|
|
20
|
+
@site.data['stats'] ||= {}
|
|
21
|
+
@site.data['stats'][key] = crunch
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def crunch
|
|
25
|
+
raise NotImplementedError, '#crunch not implemented!'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Calculates the average of a list of numbers.
|
|
7
29
|
#
|
|
8
|
-
#
|
|
9
|
-
# @
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def key
|
|
15
|
-
self.class.const_get(:KEY)
|
|
16
|
-
end
|
|
30
|
+
# @param [Array<Numeric>] numlist list of numbers to be averaged.
|
|
31
|
+
# @return [Numeric] rounded, calculated average of numlist.
|
|
32
|
+
def average(numlist)
|
|
33
|
+
calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
|
|
34
|
+
calc.round
|
|
35
|
+
end
|
|
17
36
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
37
|
+
# Calculates the total of a list of numbers.
|
|
38
|
+
#
|
|
39
|
+
# @param [Array<Numeric>] numlist list of numbers to be totaled.
|
|
40
|
+
# @return [Numeric] calculated total of numlist.
|
|
41
|
+
def total(numlist)
|
|
42
|
+
numlist.inject(0) { |sum, x| sum + x }
|
|
43
|
+
end
|
|
24
44
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
def entries
|
|
46
|
+
@site.posts.docs.select(&:published?)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
28
49
|
|
|
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
|
|
50
|
+
# Post Count Generator
|
|
51
|
+
class PostCount < Jekyll::Generator
|
|
52
|
+
include Stats
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
# @param [Array<Numeric>] numlist list of numbers to be totaled.
|
|
41
|
-
# @return [Numeric] calculated total of numlist.
|
|
42
|
-
def total(numlist)
|
|
43
|
-
numlist.inject(0) { |sum, x| sum + x }
|
|
44
|
-
end
|
|
54
|
+
KEY = 'posts'
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
end
|
|
56
|
+
def crunch
|
|
57
|
+
entries.count
|
|
49
58
|
end
|
|
59
|
+
end
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
# Word Count Generator
|
|
62
|
+
class Words < Jekyll::Generator
|
|
63
|
+
include Stats
|
|
54
64
|
|
|
55
|
-
|
|
65
|
+
KEY = 'words'
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
def crunch
|
|
68
|
+
total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
|
|
69
|
+
{
|
|
70
|
+
'average' => average(total_counts),
|
|
71
|
+
'total' => total(total_counts)
|
|
72
|
+
}
|
|
60
73
|
end
|
|
74
|
+
end
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
# Streak Count Generator
|
|
77
|
+
class Streaks < Jekyll::Generator
|
|
78
|
+
include Stats
|
|
65
79
|
|
|
66
|
-
|
|
80
|
+
KEY = 'days'
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
def crunch
|
|
83
|
+
streaks.take(1).map do |count, dates|
|
|
70
84
|
{
|
|
71
|
-
'
|
|
72
|
-
'
|
|
85
|
+
'days' => count,
|
|
86
|
+
'start' => dates[0],
|
|
87
|
+
'end' => dates[1]
|
|
73
88
|
}
|
|
74
|
-
end
|
|
89
|
+
end.first
|
|
75
90
|
end
|
|
76
91
|
|
|
77
|
-
|
|
78
|
-
class Streaks < Jekyll::Generator
|
|
79
|
-
include Stats
|
|
80
|
-
|
|
81
|
-
KEY = 'days'
|
|
82
|
-
|
|
83
|
-
def crunch
|
|
84
|
-
streaks.take(1).map do |count, dates|
|
|
85
|
-
{
|
|
86
|
-
'days' => count.pretty,
|
|
87
|
-
'start' => dates[0],
|
|
88
|
-
'end' => dates[1]
|
|
89
|
-
}
|
|
90
|
-
end.first
|
|
91
|
-
end
|
|
92
|
+
private
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
first, last = dates.minmax
|
|
101
|
-
_streaks << [(last - first).to_i, [first, last]]
|
|
102
|
-
end
|
|
103
|
-
_streaks
|
|
94
|
+
def streaks
|
|
95
|
+
_streaks = []
|
|
96
|
+
entry_dates.slice_when do |prev, curr|
|
|
97
|
+
curr != prev - 1
|
|
98
|
+
end.each do |dates|
|
|
99
|
+
first, last = dates.minmax
|
|
100
|
+
_streaks << [(last - first).to_i, [first, last]]
|
|
104
101
|
end
|
|
102
|
+
_streaks
|
|
103
|
+
end
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
end
|
|
105
|
+
def entry_dates
|
|
106
|
+
entries.collect(&:date).map { |t| Date.new(t.year, t.month, t.day) }.sort.reverse
|
|
109
107
|
end
|
|
110
108
|
end
|
|
111
109
|
end
|
data/lib/jekyll_recker/mixins.rb
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
module Recker
|
|
5
|
-
module Mixins
|
|
6
|
-
# Descendants
|
|
7
|
-
module Descendants
|
|
8
|
-
def self.included(base)
|
|
9
|
-
base.extend(self)
|
|
10
|
-
end
|
|
3
|
+
require 'logger'
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
module JekyllRecker
|
|
6
|
+
module Mixins
|
|
7
|
+
# Descendants
|
|
8
|
+
module Descendants
|
|
9
|
+
def self.included(base)
|
|
10
|
+
base.extend(self)
|
|
15
11
|
end
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
def descendants
|
|
14
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Introspection
|
|
19
|
+
module Introspection
|
|
20
|
+
def self.included(base)
|
|
21
|
+
base.extend(self)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def class_name
|
|
25
|
+
self.class.name.split('::').last
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Logging
|
|
30
|
+
module Logging
|
|
31
|
+
def self.included(base)
|
|
32
|
+
base.extend(self)
|
|
33
|
+
end
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
def logger
|
|
36
|
+
@logger ||= Logger.new(
|
|
37
|
+
STDOUT,
|
|
38
|
+
formatter: proc { |_severity, _datetime, _progname, msg| "jekyll-recker: #{msg}\n" }
|
|
39
|
+
)
|
|
26
40
|
end
|
|
27
41
|
end
|
|
28
42
|
end
|
data/lib/jekyll_recker/shell.rb
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
require 'open3'
|
|
4
4
|
|
|
5
|
-
module
|
|
6
|
-
#
|
|
7
|
-
module
|
|
5
|
+
module JekyllRecker
|
|
6
|
+
# Shell
|
|
7
|
+
module Shell
|
|
8
8
|
# ShellCommandFailed
|
|
9
|
-
class ShellCommandFailed <
|
|
9
|
+
class ShellCommandFailed < JekyllRecker::Error; end
|
|
10
10
|
|
|
11
|
-
def self.
|
|
11
|
+
def self.run(cmd)
|
|
12
12
|
out, err, status = Open3.capture3(cmd)
|
|
13
13
|
return out if status.success?
|
|
14
14
|
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'slack-notifier'
|
|
4
|
+
require 'twitter'
|
|
5
|
+
|
|
6
|
+
module JekyllRecker
|
|
7
|
+
module Social
|
|
8
|
+
def self.action(args, options)
|
|
9
|
+
args += %w[slack twitter] if args.empty?
|
|
10
|
+
Slack.share(dry: options['dry']) if args.include?('slack')
|
|
11
|
+
Twitter.share(dry: options['dry']) if args.include?('twitter')
|
|
12
|
+
end
|
|
13
|
+
# Backend
|
|
14
|
+
#
|
|
15
|
+
# Backend base class for social sharing backends.
|
|
16
|
+
# @abstract
|
|
17
|
+
class Share
|
|
18
|
+
include Mixins::Introspection
|
|
19
|
+
include Mixins::Logging
|
|
20
|
+
|
|
21
|
+
def self.share(dry: false)
|
|
22
|
+
backend = new(dry: dry)
|
|
23
|
+
logger.info "#{backend.name} - building configuration"
|
|
24
|
+
backend.configure!
|
|
25
|
+
|
|
26
|
+
logger.info "#{backend.name} - sharing \"#{backend.latest_title}\""
|
|
27
|
+
backend.post!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(dry: false)
|
|
31
|
+
@dry = dry
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def dry?
|
|
35
|
+
@dry
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def config
|
|
39
|
+
@config ||= JekyllRecker::Configuration.recker.fetch(config_key)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def config_key
|
|
43
|
+
class_name.downcase
|
|
44
|
+
end
|
|
45
|
+
alias name config_key
|
|
46
|
+
|
|
47
|
+
def post_body
|
|
48
|
+
url = File.join Configuration.jekyll['url'], latest.url
|
|
49
|
+
<<~BODY
|
|
50
|
+
#{latest.data['date'].strftime('%A, %B %-d %Y')}
|
|
51
|
+
#{latest.data['title']}
|
|
52
|
+
#{url}
|
|
53
|
+
BODY
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def latest
|
|
57
|
+
@latest ||= Configuration.latest_post
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def latest_title
|
|
61
|
+
latest.data['title']
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def configure!
|
|
65
|
+
raise NotImplementedError
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def post!
|
|
69
|
+
raise NotImplementedError
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Slack
|
|
74
|
+
#
|
|
75
|
+
# Slack social sharing backend
|
|
76
|
+
class Slack < Share
|
|
77
|
+
def configure!
|
|
78
|
+
@creds = {}
|
|
79
|
+
workspaces.each do |key, data|
|
|
80
|
+
webhook = ENV["SLACK_#{key.upcase}_WEBHOOK"] || extract_from_config(data)
|
|
81
|
+
if webhook.nil?
|
|
82
|
+
raise ReckerError, "cannot find slack webhook for #{key} workspace!"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
@creds[key] = webhook
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def post!
|
|
90
|
+
message_body = ::Slack::Notifier::Util::LinkFormatter.format(post_body)
|
|
91
|
+
workspaces.each do |key, config|
|
|
92
|
+
logger.info "posting to #{key} workspace"
|
|
93
|
+
if @dry
|
|
94
|
+
logger.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
|
|
95
|
+
else
|
|
96
|
+
::Slack::Notifier.new(
|
|
97
|
+
@creds[key].strip,
|
|
98
|
+
channel: config.fetch('channel'),
|
|
99
|
+
username: config.fetch('username'),
|
|
100
|
+
icon_emoji: config.fetch('emoji')
|
|
101
|
+
).post(text: message_body)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def extract_from_config(data)
|
|
109
|
+
cmd = data['webhook_cmd']
|
|
110
|
+
return nil if cmd.nil?
|
|
111
|
+
|
|
112
|
+
Shell.run(cmd)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def workspaces
|
|
116
|
+
config.each
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Twitter
|
|
121
|
+
#
|
|
122
|
+
# Twitter social sharing backend
|
|
123
|
+
class Twitter < Share
|
|
124
|
+
def configure!
|
|
125
|
+
creds = extract_from_env || extract_from_config
|
|
126
|
+
raise ReckerError, 'cannot find twitter credentials!' if creds.nil?
|
|
127
|
+
|
|
128
|
+
@client = ::Twitter::REST::Client.new do |settings|
|
|
129
|
+
settings.consumer_key = creds['consumer_api_key']
|
|
130
|
+
settings.consumer_secret = creds['consumer_api_secret']
|
|
131
|
+
settings.access_token = creds['access_token']
|
|
132
|
+
settings.access_token_secret = creds['access_token_secret']
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def post!
|
|
137
|
+
if dry?
|
|
138
|
+
logger.info('tweeting in dry mode, printing message')
|
|
139
|
+
logger.info("BEGIN TWEET\n#{post_body}END TWEET")
|
|
140
|
+
else
|
|
141
|
+
@client.update(post_body)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
|
|
147
|
+
def extract_from_env
|
|
148
|
+
values = cred_fieldnames.map { |k| ENV["TWITTER_#{k.upcase}"] }
|
|
149
|
+
|
|
150
|
+
return nil if values.any? { |v| v.nil? || v.empty? }
|
|
151
|
+
|
|
152
|
+
Hash[cred_fieldnames.zip(values)]
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def extract_from_config
|
|
156
|
+
values = cred_fieldnames.map do |k|
|
|
157
|
+
Shell.run(Configuration.twitter["#{k}_cmd"]).strip
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
return nil if values.any? { |v| v.nil? || v.empty? }
|
|
161
|
+
|
|
162
|
+
Hash[cred_fieldnames.zip(values)]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def cred_fieldnames
|
|
166
|
+
[
|
|
167
|
+
'access_token_secret',
|
|
168
|
+
'access_token',
|
|
169
|
+
'consumer_api_key',
|
|
170
|
+
'consumer_api_secret'
|
|
171
|
+
]
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
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.9.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-
|
|
11
|
+
date: 2020-07-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bump
|
|
@@ -145,10 +145,12 @@ extra_rdoc_files: []
|
|
|
145
145
|
files:
|
|
146
146
|
- LICENSE
|
|
147
147
|
- README.md
|
|
148
|
+
- _includes/figure.html
|
|
148
149
|
- _includes/footer.html
|
|
150
|
+
- _includes/head.html
|
|
149
151
|
- _includes/header.html
|
|
150
152
|
- _includes/nav.html
|
|
151
|
-
-
|
|
153
|
+
- _includes/pager.html
|
|
152
154
|
- _layouts/home.html
|
|
153
155
|
- _layouts/page.html
|
|
154
156
|
- _layouts/post.html
|
|
@@ -156,15 +158,13 @@ files:
|
|
|
156
158
|
- lib/jekyll_recker/commands.rb
|
|
157
159
|
- lib/jekyll_recker/configuration.rb
|
|
158
160
|
- lib/jekyll_recker/error.rb
|
|
161
|
+
- lib/jekyll_recker/filters.rb
|
|
159
162
|
- lib/jekyll_recker/generators.rb
|
|
160
|
-
- lib/jekyll_recker/logger.rb
|
|
161
163
|
- lib/jekyll_recker/mixins.rb
|
|
162
164
|
- lib/jekyll_recker/shell.rb
|
|
163
|
-
- lib/jekyll_recker/
|
|
165
|
+
- lib/jekyll_recker/social.rb
|
|
164
166
|
- lib/jekyll_recker/tags.rb
|
|
165
|
-
- lib/jekyll_recker/twitter.rb
|
|
166
167
|
- lib/jekyll_recker/version.rb
|
|
167
|
-
- lib/jekyll_recker/words.rb
|
|
168
168
|
homepage: https://www.github.com/arecker/jekyll-recker/
|
|
169
169
|
licenses:
|
|
170
170
|
- GPLv3
|
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/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/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::Mixins::Logging
|
|
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 Mixins::Logging
|
|
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
|
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
|