jekyll-recker 1.2.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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