jekyll-recker 1.2.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62dc4c8500d533aaf0843cacf329e785cd310580524c97f490bf80a7f114cbc0
4
- data.tar.gz: dae3a437b31889c3b926542d4e62239aff5dc91d57e8d374e5f3ffbb34b0a32d
3
+ metadata.gz: efd3587e247f83a9294d79e67abe0edf58dfe64aa413a18ee591bc2b5225687e
4
+ data.tar.gz: 28f7d50132af62ac1955dbc5657e54f1c4f67a996d34c79aded6add417a815c1
5
5
  SHA512:
6
- metadata.gz: 895958e1b87f99f06e05a38e2af51203da8977b92755419560c491ee09d9034bbb101068e7b102a81faaf651ed653aac918c77f6d3d367ea458da7d37979b14f
7
- data.tar.gz: 760729a485246dac07ced50aec301af45153a174872994c5959d9f1b68941ac143c0b3d022123be8b8fb2a8dae9274d7aeb83ee1c21228bb12375ee99fcae08a
6
+ metadata.gz: df34b7690acd0abd08d79271e3c262e7367c184968bb6db587e681f0a5df3b62e7d1f54bd6f346c684e77541cf1f8acb979e55f9a460a4acac786d59ba48db3c
7
+ data.tar.gz: 0f90b95a366cbffde52647320aca1152322f36eccc5f791dd393696f1414da630624bb2bdadf54f632f378b1d3cb55af61b0d59308c704952fc344914df8fa44
@@ -0,0 +1,105 @@
1
+ # jekyll-recker
2
+
3
+ The Greatest Jekyll Plugin in the World. For a live example, check
4
+ out [my personal website].
5
+
6
+ ## Installation
7
+
8
+ Add `jekyll-recker` to the `jekyll_plugins` group in your `Gemfile`.
9
+
10
+ group :jekyll_plugins do
11
+ gem 'jekyll-recker'
12
+ end
13
+
14
+ Then add the plugin to jekyll site's `config.yml` file.
15
+
16
+ pugins:
17
+ - jekyll-recker
18
+
19
+ If you'd like to make your site look like mine too, set the theme in
20
+ `config.yml` too.
21
+
22
+ theme: jekyll-recker
23
+
24
+ ## Usage
25
+
26
+ ### Share
27
+
28
+ Use the `share` jekyll command to post a link to your latest published
29
+ blog post to any or all of the configured Shares.
30
+
31
+ # TODO: example of `be jekyll share`
32
+
33
+ Perform a test run with the `--dry` flag.
34
+
35
+ # TODO: example of `be jekyll share --dry`
36
+
37
+ Send to all configured shares, or just pick one of them.
38
+
39
+ $ jekyll share slack
40
+ $ jekyll share twitter
41
+
42
+ #### Slack
43
+
44
+ Send the latest published post to a slack channel.
45
+
46
+ ![example slack]
47
+
48
+ Configure the slack share in `_config.yml`.
49
+
50
+ recker:
51
+ slack:
52
+ myteam:
53
+ channel: '#blogs'
54
+ username: 'blogbot'
55
+ emoji: ':robot:'
56
+ webhook_cmd: cat ~/.secrets/slack-webhook.txt
57
+
58
+ Use the `webhook_cmd` option to shell out to `gpg` or another CLI
59
+ password manager. Alternatively, you can supply the private incoming
60
+ webhook using an environment variable.
61
+
62
+ export SLACK_MYTEAM_WEBHOOK="https://.../" # SLACK_ + MyTeam.upcase + _WEBHOOK
63
+
64
+ Multiple teams are supported as well.
65
+
66
+ recker:
67
+ slack:
68
+ MyTeamA:
69
+ channel: '#blogs'
70
+ username: 'blogbot'
71
+ emoji: ':robot:'
72
+ MyTeamB:
73
+ channel: '#blogs'
74
+ username: 'blogbot'
75
+ emoji: ':robot:'
76
+ MyTeamC:
77
+ channel: '#blogs'
78
+ username: 'blogbot'
79
+ emoji: ':robot:'
80
+
81
+ #### Twitter
82
+
83
+ Send a tweet with a link to the latest published post.
84
+
85
+ ![example tweet]
86
+
87
+ Configure the tweet share in `_config.yml`.
88
+
89
+ recker:
90
+ twitter:
91
+ access_token_secret_cmd: pass twitter/reckerbot/access-token-secret
92
+ access_token_cmd: pass twitter/reckerbot/access-token
93
+ consumer_api_key_cmd: pass twitter/reckerbot/consumer-api-key
94
+ consumer_api_secret_cmd: pass twitter/reckerbot/consumer-api-secret-key
95
+
96
+ Alternatively, ensure these environment variables are set.
97
+
98
+ export ACCESS_TOKEN_SECRET="..."
99
+ export ACCESS_TOKEN="..."
100
+ export CONSUMER_API_KEY="..."
101
+ export CONSUMER_API_SECRET="..."
102
+
103
+ [example slack]: screenshots/example-slack.png
104
+ [example tweet]: screenshots/example-tweet.png
105
+ [my personal website]: https://www.alexrecker.com
@@ -0,0 +1,14 @@
1
+ <figure>
2
+ {%- if include.url %}
3
+ <a href="{{ include.url }}">
4
+ {%- endif %}
5
+ <img alt="{{ 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>
@@ -1,5 +1,14 @@
1
1
  <footer>
2
- built with <a href="https://jekyllrb.com/">jekyll</a> using <a href="{% link README.org %}">jekyll-recker</a> v{% recker_version %}
2
+ <nav>
3
+ find me on: &nbsp
4
+ <a href="mailto:{{ site.email }}">email</a>
5
+ <a href="https://www.github.com/{{ site.github_username }}">github</a>
6
+ <a href="https://www.twitter.com/{{ site.twitter_username }}">twitter</a>
7
+ <a href="{{ site.basurl }}/assets/public.gpg.asc">gpg</a>
8
+ <a href="https://www.linkedin.com/in/{{ site.linkedin_username }}">linkedin</a>
9
+ <a href="https://www.facebook.com/{{ site.facebook_username }}">facebook</a>
10
+ </nav>
11
+ built with <a href="https://jekyllrb.com/">jekyll</a> using <a href="https://www.github.com/arecker/jekyll-recker/">jekyll-recker</a> v{% recker_version %}
3
12
  <br/>
4
13
  <small>&copy; copyright {{ 'now' | date: '%Y' }}, {{ site.author }}</small>
5
- </foote>
14
+ </footer>
@@ -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>
@@ -1,7 +1,5 @@
1
1
  <nav>
2
- <a href="{{ site.baseurl }}/" class="{% if page.active == 'index' %}active{% endif %}">index</a>
3
- <a href="{% link archive.html %}" class="{% if page.active == 'archive' %}active{% endif %}">archive</a>
4
- <a href="{% link stats.org %}" class="{% if page.active == 'stats' %}active{% endif %}">stats</a>
5
- <a href="{% link contact.html %}" class="{% if page.active == 'contact' %}active{% endif %}">contact</a>
2
+ <a href="{{ site.baseurl }}/" class="{% if page.active == 'index' %}active{% endif %}">index.html</a>
3
+ <a href="{{ site.basurl }}/feed.xml">feed.xml</a>
6
4
  <span class="float-right hide-on-mobile">{{ page.slug }}</span>
7
- </nav>
5
+ </nav>
@@ -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
+
@@ -1,9 +1,13 @@
1
- ---
2
- layout: default
3
- ---
4
- {% include header.html title=site.title subtitle=site.description %}
5
- <hr/>
6
- {% include nav.html %}
7
- <hr/>
8
- {{ content }}
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>
@@ -1,8 +1,13 @@
1
- ---
2
- layout: default
3
- ---
4
- {% include header.html title=page.title subtitle=page.description %}
5
- <hr/>
6
- {% include nav.html %}
7
- <hr/>
8
- {{ content }}
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>
@@ -1,21 +1,20 @@
1
- ---
2
- layout: default
3
- ---
4
- {% capture datestring %}{{ page.date | date: '%A, %B %d %Y' }}{% endcapture %}
5
- {% include header.html title=datestring subtitle=page.title %}
6
- <hr/>
7
- {% include nav.html %}
8
- <hr/>
9
- {{ content }}
10
- <nav class="clearfix">
11
- {%- if page.next -%}
12
- <a href="{{ page.next.url }}">
13
- ⟵ {{ page.next.slug }}
14
- </a>
15
- {%- endif -%}
16
- {%- if page.previous -%}
17
- <a class="float-right" href="{{ page.previous.url }}">
18
- {{ page.previous.slug }} ⟶
19
- </a>
20
- </nav>
21
- {%- 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>
@@ -5,17 +5,19 @@ require 'jekyll'
5
5
  module Jekyll
6
6
  # Recker
7
7
  module Recker
8
- require 'jekyll-recker/commands.rb'
9
- require 'jekyll-recker/configuration.rb'
10
- require 'jekyll-recker/error.rb'
11
- require 'jekyll-recker/generators.rb'
12
- require 'jekyll-recker/log.rb'
13
- require 'jekyll-recker/shell.rb'
14
- require 'jekyll-recker/slack.rb'
15
- require 'jekyll-recker/stats.rb'
16
- require 'jekyll-recker/tags.rb'
17
- require 'jekyll-recker/twitter.rb'
18
- require 'jekyll-recker/version.rb'
19
- require 'jekyll-recker/words.rb'
8
+ require 'jekyll_recker/logger.rb'
9
+ require 'jekyll_recker/mixins.rb'
10
+
11
+ require 'jekyll_recker/commands.rb'
12
+ require 'jekyll_recker/configuration.rb'
13
+ require 'jekyll_recker/error.rb'
14
+ require 'jekyll_recker/filters.rb'
15
+ require 'jekyll_recker/generators.rb'
16
+ require 'jekyll_recker/shell.rb'
17
+ require 'jekyll_recker/slack.rb'
18
+ require 'jekyll_recker/tags.rb'
19
+ require 'jekyll_recker/twitter.rb'
20
+ require 'jekyll_recker/version.rb'
21
+ require 'jekyll_recker/words.rb'
20
22
  end
21
23
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Recker
5
+ # Commands
6
+ module Commands
7
+ # Share
8
+ class Share < Jekyll::Command
9
+ include Mixins::Logging
10
+
11
+ def self.init_with_program(prog)
12
+ prog.command(:share) do |c|
13
+ c.syntax 'share'
14
+ c.description 'Share latest post with each configured backend'
15
+ c.option 'dry', '-d', '--dry', 'perform dry run'
16
+ c.action do |_args, _options|
17
+ logger.info 'normally I\'d share here'
18
+ rescue ReckerError => e
19
+ logger.abort_with e.message
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # Slack
26
+ class Slack < Jekyll::Command
27
+ include Mixins::Logging
28
+ def self.init_with_program(prog)
29
+ prog.command(:slack) do |c|
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
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jekyll
2
4
  module Recker
3
5
  # Configuration
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Recker
5
+ # Filters
6
+ module Filters
7
+ # Converts a date object to standard Uhh Yeah Dude format.
8
+ def uyd_date(date)
9
+ date.strftime('%A, %B %d %Y')
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ Liquid::Template.register_filter(Jekyll::Recker::Filters)
@@ -1,42 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
4
-
5
3
  module Jekyll
6
4
  module Recker
7
- # Stats
8
- module Stats
9
- def self.crunch(site)
10
- stats = {}
11
- BaseCruncher.descendants.each do |cruncher_class|
12
- cruncher = cruncher_class.new(site)
13
- Recker.info "crunching stats.#{cruncher.stats_key}"
14
- stats[cruncher.stats_key] = cruncher.crunch
15
- end
16
- stats
17
- end
18
-
19
- # Base Cruncher
20
- class BaseCruncher
5
+ module Generators
6
+ # Stats Module
7
+ #
8
+ # Functions for stats generators.
9
+ # @abstract
10
+ module Stats
11
+ include Mixins::Logging
21
12
  include Jekyll::Filters
22
13
 
23
- def self.descendants
24
- ObjectSpace.each_object(Class).select { |klass| klass < self }
14
+ def key
15
+ self.class.const_get(:KEY)
25
16
  end
26
17
 
27
- def initialize(site)
18
+ def generate(site)
28
19
  @site = site
20
+ logger.info "crunching stats.#{key}"
21
+ @site.data['stats'] ||= {}
22
+ @site.data['stats'][key] = crunch
29
23
  end
30
24
 
31
- private
32
-
33
- attr_reader :journal
25
+ def crunch
26
+ raise NotImplementedError, '#crunch not implemented!'
27
+ end
34
28
 
29
+ # Calculates the average of a list of numbers.
30
+ #
31
+ # @param [Array<Numeric>] numlist list of numbers to be averaged.
32
+ # @return [Numeric] rounded, calculated average of numlist.
35
33
  def average(numlist)
36
34
  calc = numlist.inject { |sum, el| sum + el }.to_f / numlist.size
37
35
  calc.round
38
36
  end
39
37
 
38
+ # Calculates the total of a list of numbers.
39
+ #
40
+ # @param [Array<Numeric>] numlist list of numbers to be totaled.
41
+ # @return [Numeric] calculated total of numlist.
40
42
  def total(numlist)
41
43
  numlist.inject(0) { |sum, x| sum + x }
42
44
  end
@@ -46,22 +48,22 @@ module Jekyll
46
48
  end
47
49
  end
48
50
 
49
- # PostCountCruncher
50
- class PostCountCruncher < BaseCruncher
51
- def stats_key
52
- 'posts'
53
- end
51
+ # Post Count Generator
52
+ class PostCount < Jekyll::Generator
53
+ include Stats
54
+
55
+ KEY = 'posts'
54
56
 
55
57
  def crunch
56
58
  entries.count.pretty
57
59
  end
58
60
  end
59
61
 
60
- # WordCountCruncher
61
- class WordCountCruncher < BaseCruncher
62
- def stats_key
63
- 'words'
64
- end
62
+ # Word Count Generator
63
+ class Words < Jekyll::Generator
64
+ include Stats
65
+
66
+ KEY = 'words'
65
67
 
66
68
  def crunch
67
69
  total_counts = entries.collect(&:content).map { |c| number_of_words(c) }
@@ -72,11 +74,11 @@ module Jekyll
72
74
  end
73
75
  end
74
76
 
75
- # Streak Cruncher
76
- class StreakCruncher < BaseCruncher
77
- def stats_key
78
- 'days'
79
- end
77
+ # Streak Count Generator
78
+ class Streaks < Jekyll::Generator
79
+ include Stats
80
+
81
+ KEY = 'days'
80
82
 
81
83
  def crunch
82
84
  streaks.take(1).map do |count, dates|
@@ -95,7 +97,7 @@ module Jekyll
95
97
  entry_dates.slice_when do |prev, curr|
96
98
  curr != prev - 1
97
99
  end.each do |dates|
98
- first, last = dates.min, dates.max
100
+ first, last = dates.minmax
99
101
  _streaks << [(last - first).to_i, [first, last]]
100
102
  end
101
103
  _streaks
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Recker
5
+ module Mixins
6
+ # Descendants
7
+ module Descendants
8
+ def self.included(base)
9
+ base.extend(self)
10
+ end
11
+
12
+ def descendants
13
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
14
+ end
15
+ end
16
+
17
+ # Logging
18
+ module Logging
19
+ def self.included(base)
20
+ base.extend(self)
21
+ end
22
+
23
+ def logger
24
+ Jekyll::Recker.logger
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -9,7 +9,6 @@ module Jekyll
9
9
  class ShellCommandFailed < ReckerError; end
10
10
 
11
11
  def self.shell(cmd)
12
- Recker.debug("running shell command \`#{cmd}\`")
13
12
  out, err, status = Open3.capture3(cmd)
14
13
  return out if status.success?
15
14
 
@@ -7,6 +7,8 @@ module Jekyll
7
7
  module Recker
8
8
  # Slack
9
9
  class Slack
10
+ include Jekyll::Recker::Mixins::Logging
11
+
10
12
  def self.each_in_config(dry: false)
11
13
  Configuration.slack.map do |key, body|
12
14
  yield new(key, body, dry: dry)
@@ -33,8 +35,8 @@ module Jekyll
33
35
 
34
36
  def post_latest!
35
37
  if @dry
36
- Recker.info('postign in dry mode, printing message')
37
- Recker.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
38
+ logger.info('postign in dry mode, printing message')
39
+ logger.info("BEGIN MESSAGE\n#{message_body.strip}\nEND MESSAGE")
38
40
  else
39
41
  ::Slack::Notifier.new(
40
42
  @webhook.strip,
@@ -3,7 +3,7 @@
3
3
  module Jekyll
4
4
  module Recker
5
5
  module Tags
6
- # Version
6
+ # Returns the VERSION of the running jekyll-recker gem.
7
7
  class Version < Liquid::Tag
8
8
  def render(_context)
9
9
  VERSION
@@ -6,6 +6,8 @@ module Jekyll
6
6
  module Recker
7
7
  # Twitter Client
8
8
  class Twitter
9
+ include Mixins::Logging
10
+
9
11
  def initialize(dry: false)
10
12
  @dry = dry
11
13
  end
@@ -19,8 +21,8 @@ module Jekyll
19
21
 
20
22
  def post_latest!
21
23
  if @dry
22
- Recker.info('tweeting in dry mode, printing message')
23
- Recker.info("BEGIN TWEET\n#{tweet_body.strip}\nEND TWEET")
24
+ logger.info('tweeting in dry mode, printing message')
25
+ logger.info("BEGIN TWEET\n#{tweet_body.strip}\nEND TWEET")
24
26
  else
25
27
  @client.update(tweet_body)
26
28
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Recker
5
- VERSION = '1.2.0'
5
+ VERSION = '1.5.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,37 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-recker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.5.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-03-20 00:00:00.000000000 Z
11
+ date: 2020-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: jekyll
14
+ name: bump
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.8'
20
- type: :runtime
19
+ version: '0'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3.8'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: slack-notifier
28
+ name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
- type: :runtime
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
@@ -39,13 +39,13 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: twitter
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: bundler
56
+ name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -80,6 +80,62 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: jekyll
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.8'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.8'
111
+ - !ruby/object:Gem::Dependency
112
+ name: slack-notifier
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: twitter
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'
83
139
  description:
84
140
  email:
85
141
  - alex@reckerfamily.com
@@ -88,29 +144,31 @@ extensions: []
88
144
  extra_rdoc_files: []
89
145
  files:
90
146
  - LICENSE
91
- - README.org
147
+ - README.md
148
+ - _includes/figure.html
92
149
  - _includes/footer.html
150
+ - _includes/head.html
93
151
  - _includes/header.html
94
152
  - _includes/nav.html
95
- - _layouts/default.html
153
+ - _includes/pager.html
96
154
  - _layouts/home.html
97
155
  - _layouts/page.html
98
156
  - _layouts/post.html
99
- - assets/jekyll-recker.scss
100
157
  - lib/jekyll-recker.rb
101
- - lib/jekyll-recker/commands.rb
102
- - lib/jekyll-recker/configuration.rb
103
- - lib/jekyll-recker/error.rb
104
- - lib/jekyll-recker/generators.rb
105
- - lib/jekyll-recker/log.rb
106
- - lib/jekyll-recker/shell.rb
107
- - lib/jekyll-recker/slack.rb
108
- - lib/jekyll-recker/stats.rb
109
- - lib/jekyll-recker/tags.rb
110
- - lib/jekyll-recker/twitter.rb
111
- - lib/jekyll-recker/version.rb
112
- - lib/jekyll-recker/words.rb
113
- homepage: https://www.alexrecker.com/jekyll-recker.html
158
+ - lib/jekyll_recker/commands.rb
159
+ - lib/jekyll_recker/configuration.rb
160
+ - lib/jekyll_recker/error.rb
161
+ - lib/jekyll_recker/filters.rb
162
+ - lib/jekyll_recker/generators.rb
163
+ - lib/jekyll_recker/logger.rb
164
+ - lib/jekyll_recker/mixins.rb
165
+ - lib/jekyll_recker/shell.rb
166
+ - lib/jekyll_recker/slack.rb
167
+ - lib/jekyll_recker/tags.rb
168
+ - lib/jekyll_recker/twitter.rb
169
+ - lib/jekyll_recker/version.rb
170
+ - lib/jekyll_recker/words.rb
171
+ homepage: https://www.github.com/arecker/jekyll-recker/
114
172
  licenses:
115
173
  - GPLv3
116
174
  metadata: {}
@@ -132,5 +190,5 @@ requirements: []
132
190
  rubygems_version: 3.0.3
133
191
  signing_key:
134
192
  specification_version: 4
135
- summary: This is the jekyll theme for my personal website.
193
+ summary: The Greatest Jekyll Plugin in the World
136
194
  test_files: []
data/README.org DELETED
@@ -1,204 +0,0 @@
1
- #+TITLE: jekyll-recker
2
- #+SLUG: jekyll-recker.html
3
- #+PERMALINK: jekyll-recker.html
4
- #+STARTUP: showall
5
- #+DESCRIPTION: my website's custom jekyll plugin
6
-
7
- This is the jekyll plugin for my personal website.
8
-
9
- ** Installation
10
-
11
- Add =jekyll-recker= to the =jekyll_plugins= group of your =Gemfile=.
12
-
13
- #+BEGIN_SRC ruby
14
- group :jekyll_plugins do
15
- gem 'jekyll-recker'
16
- end
17
- #+END_SRC
18
-
19
- Add =jekyll-recker= to the list of plugins in jekyll's =_config.yml=.
20
-
21
- #+BEGIN_SRC yaml
22
- # _config.yaml
23
- plugins:
24
- - jekyll-recker
25
- #+END_SRC
26
-
27
- Set the theme.
28
-
29
- #+BEGIN_SRC yaml
30
- theme: jekyll-recker
31
- #+END_SRC
32
-
33
- Install and enjoy.
34
-
35
- #+BEGIN_SRC sh
36
- bundle install
37
- bundle exec jekyll serve
38
- #+END_SRC
39
-
40
- ** Usage
41
-
42
- *** Commands
43
-
44
- **** =slack=
45
-
46
- The =slack= command posts a slack message advertising the latest
47
- published jekyll blog post using a private incoming webhook.
48
-
49
- Configure _config.yml
50
-
51
- #+BEGIN_SRC yaml
52
- # _config.yml
53
- recker:
54
- slack:
55
- MyTeam:
56
- channel: '#blogs' # required!
57
- username: 'blogbot' # required!
58
- emoji: ':robot:' # required!
59
- #+END_SRC
60
-
61
- Multiple teams are supported too!
62
-
63
- #+BEGIN_SRC yaml
64
- # _config.yml
65
- recker:
66
- slack:
67
- MyTeamA:
68
- channel: '#blogs' # required!
69
- username: 'blogbot' # required!
70
- emoji: ':robot:' # required!
71
- MyTeamB:
72
- channel: '#blogs' # required!
73
- username: 'blogbot' # required!
74
- emoji: ':robot:' # required!
75
- MyTeamC:
76
- channel: '#blogs' # required!
77
- username: 'blogbot' # required!
78
- emoji: ':robot:' # required!
79
- #+END_SRC
80
-
81
-
82
- Supply the private webhook through an environment variable.
83
-
84
- #+BEGIN_SRC sh
85
- export SLACK_MYTEAM_WEBHOOK="https://..." # SLACK_ + <MyTeam.upcase> + _WEBHOOK
86
- #+END_SRC
87
-
88
- Alternatively, add the command with which to retrieve the webhook in
89
- _config.yml
90
-
91
- #+BEGIN_SRC yaml
92
- # _config.yml
93
- recker:
94
- slack:
95
- MyTeam:
96
- webhook_cmd: cat secrets/my-teams-secret-webhook.txt
97
- #+END_SRC
98
-
99
- Run =bundle exec jekyll slack= to let it rip!
100
-
101
- [[assets/images/example-slack.png]]
102
-
103
- Using the =--dry= flag, you can preview the message post without
104
- actually posting anything.
105
-
106
- #+BEGIN_EXAMPLE
107
- arecker@25732-arecker:~/src/blog$ be jekyll slack --dry
108
- Configuration file: /Users/arecker/src/blog/_config.yml
109
- jekyll-recker: reckerfamily: discovering webhook
110
- Configuration file: /Users/arecker/src/blog/_config.yml
111
- jekyll-recker: reckerfamily: posting drag racing, windshield wipers, and alex's painting tips
112
- jekyll-recker: postign in dry mode, printing message
113
- jekyll-recker: BEGIN MESSAGE
114
- Sunday, March 15 2020
115
- drag racing, windshield wipers, and alex's painting tips
116
- https://www.alexrecker.com/2020-03-15.html
117
- END MESSAGE
118
- #+END_EXAMPLE
119
-
120
- **** =tweet=
121
-
122
- The =tweet= command tweets a link to the latest published jekyll blog
123
- post.
124
-
125
- Ensure the following environment variables are set,.
126
-
127
- #+BEGIN_SRC sh
128
- export ACCESS_TOKEN_SECRET="..."
129
- export ACCESS_TOKEN="..."
130
- export CONSUMER_API_KEY="..."
131
- export CONSUMER_API_SECRET="..."
132
- #+END_SRC
133
-
134
- Alternatively, configure which commands to run to fetch the secrets.
135
-
136
- #+BEGIN_SRC yaml
137
- # _config.yml
138
- recker:
139
- twitter:
140
- access_token_secret_cmd: cat secrets/access-token-secret
141
- access_token_cmd: cat secrets/access-token
142
- consumer_api_key_cmd: cat secrets/consumer-api-key
143
- consumer_api_secret_cmd: cat secrets/consumer-api-secret-key
144
- #+END_SRC
145
-
146
- Run =bundle exec jekyll tweet= to let it rip!
147
-
148
- [[assets/images/example-tweet.png]]
149
-
150
- Using the =--dry= flag, you can test your configuration without
151
- actually tweeting anything.
152
-
153
- #+BEGIN_EXAMPLE
154
- arecker@25732-arecker:~/src/blog$ be jekyll tweet --dry
155
- jekyll-recker: discovering credentials
156
- Configuration file: /Users/arecker/src/blog/_config.yml
157
- Configuration file: /Users/arecker/src/blog/_config.yml
158
- jekyll-recker: tweeting drag racing, windshield wipers, and alex's painting tips
159
- jekyll-recker: tweeting in dry mode, printing message
160
- jekyll-recker: BEGIN TWEET
161
- Sunday, March 15 2020
162
- drag racing, windshield wipers, and alex's painting tips
163
- https://www.alexrecker.com/2020-03-15.html
164
- END TWEET
165
- #+END_EXAMPLE
166
-
167
- *** Generators
168
-
169
- **** =stats=
170
-
171
- On build time, =jekyll-recker= calculates and stores the following
172
- stats in the =site.data.stats= object
173
-
174
- | Field Name | Field Description |
175
- |-----------------+------------------------------------------------------|
176
- | =posts= | The total number of published posts. |
177
- | =words.total= | The total number of words from all published post. |
178
- | =words.average= | The average number of words for each published post. |
179
- | =days.days= | Current streak of daily, consecutive posts. |
180
- | =days.start= | First day of current streak. |
181
- | =days.end= | Last day of current streak. |
182
-
183
- Use these variables to render your own page of neat writing statistics!
184
-
185
- #+BEGIN_SRC html
186
- <table>
187
- <tr>
188
- <th>Total Posts</th>
189
- <th>Total Words</th>
190
- <th>Average Words per Post</th>
191
- <th>Current Streak</th>
192
- <th>First day of current streak</th>
193
- <th>Last day of current streak</th>
194
- </tr>
195
- <tr>
196
- <td>{{ site.data.stats.posts }}</td>
197
- <td>{{ site.data.stats.words.total }}</td>
198
- <td>{{ site.data.stats.words.average }}</td>
199
- <td>{{ site.data.stats.days.days }}</td>
200
- <td>{{ site.data.stats.days.start }}</td>
201
- <td>{{ site.data.stats.days.end }}</td>
202
- </tr>
203
- </table>
204
- #+END_SRC
@@ -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>
@@ -1,106 +0,0 @@
1
- ---
2
- ---
3
- // @import 'https://fonts.googleapis.com/css?family=Titillium+Web&display=swap';
4
- @import 'https://fonts.googleapis.com/css?family=Open+Sans&display=swap';
5
- @import 'https://fonts.googleapis.com/css?family=Inconsolata&display=swap';
6
-
7
- .float-right {
8
- float: right;
9
- }
10
-
11
- .clearfix::after {
12
- content: "";
13
- clear: both;
14
- display: block;
15
- }
16
-
17
- @media screen and (max-width: 600px) {
18
- .hide-on-mobile {
19
- display: none;
20
- }
21
- }
22
-
23
- ul.unstyled {
24
- list-style-type: none;
25
- margin: 0;
26
- padding: 0;
27
- }
28
-
29
- body {
30
- margin: 40px auto;
31
- max-width: 800px;
32
- line-height: 1.6;
33
- font-size: 18px;
34
- color: #444;
35
- padding: 0 10px;
36
- }
37
-
38
- h1, h2, h3 {
39
- line-height: 1.2;
40
- }
41
-
42
- header {
43
- h1 {
44
- margin-bottom: 9px;
45
- }
46
-
47
- p {
48
- margin-top: 9px;
49
- }
50
- }
51
-
52
- figure {
53
- img {
54
- display: block;
55
- margin-left: auto;
56
- margin-right: auto;
57
- vertical-align: top;
58
- height: auto;
59
- max-width: 100%;
60
- }
61
-
62
- figcaption {
63
- text-align: center;
64
- }
65
- }
66
-
67
- nav {
68
- a {
69
- margin-right: 10px;
70
- }
71
-
72
- a.active {
73
- color: black !important;
74
- }
75
-
76
- span {
77
- color: #6f7370;
78
- }
79
- }
80
-
81
- a {
82
- text-decoration: none !important;
83
- color: #008083 !important;
84
-
85
- :hover {
86
- text-decoration: underline !important;
87
- }
88
-
89
- :active {
90
- color: #6f7370 !important;
91
- }
92
- }
93
-
94
- * {
95
- // font-family: 'Titillium Web', sans-serif !important;
96
- font-family: 'Open Sans', 'sans-serif' !important;
97
- }
98
-
99
- code, pre, pre span {
100
- font-family: Inconsolata, monospace !important;
101
- }
102
-
103
- pre, pre span {
104
- font-size: 14px;
105
- }
106
-
@@ -1,52 +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
- class << self
9
- def init_with_program(prog)
10
- prog.command(:tweet) do |c|
11
- c.syntax 'tweet'
12
- c.description 'tweet latest post'
13
- c.option 'dry', '-d', '--dry', 'print message instead of tweeting'
14
- c.action do |_args, options|
15
- client = Jekyll::Recker::Twitter.new(dry: options['dry'])
16
- Recker.info 'discovering credentials'
17
- client.discover_credentials!
18
- Recker.info "tweeting #{client.latest.data['title']}"
19
- client.post_latest!
20
- rescue ReckerError => e
21
- Recker.abort_with e.message
22
- end
23
- end
24
- end
25
- end
26
- end
27
-
28
- # Slack
29
- class Slack < Jekyll::Command
30
- class << self
31
- def init_with_program(prog)
32
- prog.command(:slack) do |c|
33
- c.syntax 'slack'
34
- c.description 'slack latest post'
35
- c.option 'dry', '-d', '--dry', 'print message instead of posting'
36
- c.action do |_args, options|
37
- Recker::Slack.each_in_config(dry: options['dry']) do |client|
38
- Recker.info "#{client.key}: discovering webhook"
39
- client.discover_webhook!
40
- Recker.info "#{client.key}: posting #{client.latest.data['title']}"
41
- client.post_latest!
42
- end
43
- rescue ReckerError => e
44
- Recker.abort_with e.message
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,15 +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
- def generate(site)
9
- Recker.info 'generating site statistics'
10
- site.data['stats'] = Stats.crunch(site)
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- # Recker
5
- module Recker
6
- def self.debug(msg)
7
- Jekyll.logger.debug("jekyll-recker: #{msg}")
8
- end
9
-
10
- def self.info(msg)
11
- Jekyll.logger.info("jekyll-recker: #{msg}")
12
- end
13
-
14
- def self.error(msg)
15
- Jekyll.logger.error("jekyll-recker: #{msg}")
16
- end
17
-
18
- def self.abort_with(msg)
19
- Jekyll.logger.abort_with("jekyll-recker: #{msg}")
20
- end
21
- end
22
- end