jekyll-recker 1.2.0 → 1.5.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 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