jekyll-recker 1.2.1 → 1.6.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +105 -0
  3. data/_includes/figure.html +14 -0
  4. data/_includes/footer.html +10 -1
  5. data/_includes/head.html +21 -0
  6. data/_includes/nav.html +3 -6
  7. data/_includes/pager.html +13 -0
  8. data/_layouts/home.html +13 -9
  9. data/_layouts/page.html +13 -8
  10. data/_layouts/post.html +20 -28
  11. data/lib/jekyll-recker.rb +14 -13
  12. data/lib/jekyll_recker/commands.rb +35 -0
  13. data/lib/{jekyll-recker → jekyll_recker}/configuration.rb +6 -0
  14. data/lib/{jekyll-recker → jekyll_recker}/error.rb +0 -0
  15. data/lib/jekyll_recker/facebook.rb +97 -0
  16. data/lib/jekyll_recker/filters.rb +15 -0
  17. data/lib/{jekyll-recker/stats.rb → jekyll_recker/generators.rb} +42 -39
  18. data/lib/{jekyll-recker → jekyll_recker}/logger.rb +0 -0
  19. data/lib/jekyll_recker/mixins.rb +29 -0
  20. data/lib/{jekyll-recker → jekyll_recker}/shell.rb +0 -0
  21. data/lib/{jekyll-recker → jekyll_recker}/slack.rb +10 -1
  22. data/lib/{jekyll-recker → jekyll_recker}/tags.rb +1 -1
  23. data/lib/{jekyll-recker → jekyll_recker}/twitter.rb +10 -2
  24. data/lib/{jekyll-recker → jekyll_recker}/version.rb +1 -1
  25. data/lib/{jekyll-recker → jekyll_recker}/words.rb +0 -0
  26. metadata +104 -35
  27. data/README.org +0 -204
  28. data/_layouts/default.html +0 -14
  29. data/assets/jekyll-recker.scss +0 -110
  30. data/lib/jekyll-recker/commands.rb +0 -12
  31. data/lib/jekyll-recker/commands/share.rb +0 -25
  32. data/lib/jekyll-recker/commands/slack.rb +0 -30
  33. data/lib/jekyll-recker/commands/tweet.rb +0 -31
  34. data/lib/jekyll-recker/generators.rb +0 -17
  35. data/lib/jekyll-recker/mixins.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57baf95903827025064b936a07c83984779e201d632d62343c2c3dc046135e90
4
- data.tar.gz: eb5f5afa3612fff8cd5f75b24aa976c7806ced88abfeb09b3f0951af15f34940
3
+ metadata.gz: 3e0cc3d6cafa2518fb5819ad8cc4a6db7ecf88e214b0e998468f521d0ec19a37
4
+ data.tar.gz: e623e1c53b62d3ccf0a55ac572ef0fc4257e03cdf7faf543baa1f5ce7d0a40ed
5
5
  SHA512:
6
- metadata.gz: a6a6c5f66c0028be4371fac2125c6965a81b36e4e26fda36dcf9d822cb4446b710f959614e20db2cd7614e36f7bbebe4d8d7ffdfdaefb1b872b270cc6aebc50d
7
- data.tar.gz: c840806dbd64b1f64fe891a8eec5326a09bb1be8f2c7e6130772da17616717186e9da58956d04f5c68a9cf423e8e86cd0ff476b31729a79e3905750046615a42
6
+ metadata.gz: b45d3daae8d8af21c963a412d8430dce81bafaff270a35ca94444b01e74a7d4bd25e422a3ac9afb958bb3693cd7359d4bab70a07776d1da7c3637a38d633eed7
7
+ data.tar.gz: 4f6aadcd49f0b0d71232ab67c361d3aac1e5a91887272d39e826e3300afa8e0cf872b2154f6e5371dda74a5fd8ea9ac928bd7a2acc6b98357be2e87b75d25903
@@ -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 TWITTER_ACCESS_TOKEN_SECRET="..."
99
+ export TWITTER_ACCESS_TOKEN="..."
100
+ export TWITTER_CONSUMER_API_KEY="..."
101
+ export TWITTER_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
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,8 +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 projects.html %}" class="{% if page.active == 'projects' %}active{% endif %}">projects</a>
6
- <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>
7
4
  <span class="float-right hide-on-mobile">{{ page.slug }}</span>
8
- </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,28 +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
- {%- if page.image -%}
10
- <br/>
11
- <figure>
12
- <img alt="page.image" src="{{ site.baseurl }}assets/images/{{ page.image }}"/>
13
- </figure>
14
- <br/>
15
- {%- endif -%}
16
- {{ content }}
17
- <nav class="clearfix">
18
- {%- if page.next -%}
19
- <a href="{{ page.next.url }}">
20
- ⟵ {{ page.next.slug }}
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>
@@ -5,19 +5,20 @@ require 'jekyll'
5
5
  module Jekyll
6
6
  # Recker
7
7
  module Recker
8
- require 'jekyll-recker/logger.rb'
9
- require 'jekyll-recker/mixins.rb'
8
+ require 'jekyll_recker/logger.rb'
9
+ require 'jekyll_recker/mixins.rb'
10
10
 
11
- require 'jekyll-recker/commands.rb'
12
- require 'jekyll-recker/configuration.rb'
13
- require 'jekyll-recker/error.rb'
14
- require 'jekyll-recker/generators.rb'
15
- require 'jekyll-recker/shell.rb'
16
- require 'jekyll-recker/slack.rb'
17
- require 'jekyll-recker/stats.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'
11
+ require 'jekyll_recker/commands.rb'
12
+ require 'jekyll_recker/configuration.rb'
13
+ require 'jekyll_recker/error.rb'
14
+ require 'jekyll_recker/facebook.rb'
15
+ require 'jekyll_recker/filters.rb'
16
+ require 'jekyll_recker/generators.rb'
17
+ require 'jekyll_recker/shell.rb'
18
+ require 'jekyll_recker/slack.rb'
19
+ require 'jekyll_recker/tags.rb'
20
+ require 'jekyll_recker/twitter.rb'
21
+ require 'jekyll_recker/version.rb'
22
+ require 'jekyll_recker/words.rb'
22
23
  end
23
24
  end
@@ -0,0 +1,35 @@
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 { |args, opts| action(args, opts) }
17
+ end
18
+ end
19
+
20
+ def self.action(args, options)
21
+ if args.empty? || args.include?('slack')
22
+ Recker::Slack.share(dry: options['dry'])
23
+ elsif args.empty? || args.include?('twitter')
24
+ Recker::Twitter.share(dry: options['dry'])
25
+ # elsif args.empty? || args.include?('facebook')
26
+ # Recker::Facebook.share(dry: options['dry'])
27
+ end
28
+ rescue ReckerError => e
29
+ logger.error e.message
30
+ exit 1
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jekyll
2
4
  module Recker
3
5
  # Configuration
@@ -10,6 +12,10 @@ module Jekyll
10
12
  jekyll.fetch('recker', {})
11
13
  end
12
14
 
15
+ def self.facebook
16
+ recker.fetch('facebook', {})
17
+ end
18
+
13
19
  def self.twitter
14
20
  recker.fetch('twitter', {})
15
21
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'koala'
4
+
5
+ module Jekyll
6
+ module Recker
7
+ # Facebook Client
8
+ class Facebook
9
+ include Mixins::Logging
10
+
11
+ def self.share(dry: false)
12
+ client = new(dry: dry)
13
+ logger.info 'discovering credentials'
14
+ client.discover_credentials!
15
+ logger.info "sharing #{client.latest.data['title']}"
16
+ client.post_latest!
17
+ end
18
+
19
+ def initialize(dry: false)
20
+ @dry = dry
21
+ end
22
+
23
+ def discover_credentials!
24
+ @creds = extract_from_env || extract_from_config
25
+ raise ReckerError, 'cannot find facebook credentials!' if @creds.nil?
26
+
27
+ set_credentials!
28
+ end
29
+
30
+ def post_latest!
31
+ if @dry
32
+ logger.info('posting in dry mode, printing message')
33
+ logger.info("BEGIN POST\n#{post_body.strip}\nEND POST")
34
+ else
35
+ @graph.put_connections("me", "feed", message: "I am writing on my wall!")
36
+ end
37
+ end
38
+
39
+ def latest
40
+ Configuration.latest_post
41
+ end
42
+
43
+ private
44
+
45
+ def post_body
46
+ url = File.join Configuration.jekyll['url'], latest.url
47
+ <<~POST
48
+ #{latest.data['date'].strftime('%A, %B %-d %Y')}
49
+ #{latest.data['title']}
50
+ #{url}
51
+ POST
52
+ end
53
+
54
+ def set_credentials!
55
+ Koala.configure do |config|
56
+ config.access_token = @creds['access_token']
57
+ # config.app_access_token = @creds['app_access_token']
58
+ config.app_id = @creds['app_id']
59
+ config.app_secret = @creds['app_secret']
60
+ end
61
+ @client = Koala::Facebook::API.new(@creds['access_token'])
62
+ end
63
+
64
+ def extract_from_env
65
+ values = cred_fieldnames.map { |k| ENV["FACEBOOK_#{k.upcase}"] }
66
+
67
+ return nil if values.any? { |v| v.nil? || v.empty? }
68
+
69
+ Hash[cred_fieldnames.zip(values)]
70
+ end
71
+
72
+ def extract_from_config
73
+ values = cred_fieldnames.map do |k|
74
+ cmd = Configuration.facebook.fetch("#{k}_cmd", '').strip
75
+ if cmd.empty?
76
+ nil
77
+ else
78
+ Recker.shell(Configuration.facebook["#{k}_cmd"]).strip
79
+ end
80
+ end
81
+
82
+ return nil if values.any? { |v| v.nil? || v.empty? }
83
+
84
+ Hash[cred_fieldnames.zip(values)]
85
+ end
86
+
87
+ def cred_fieldnames
88
+ # app_access_token
89
+ %w[
90
+ access_token
91
+ app_id
92
+ app_secret
93
+ ]
94
+ end
95
+ end
96
+ end
97
+ end