diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ebaac44
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+Gemfile.lock
+_site
+.byebug_history
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..c99d2e7
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+--require spec_helper
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6a8e36f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,5 @@
+sudo: false
+language: ruby
+rvm:
+ - 2.5.0
+before_install: gem install bundler -v 1.16.1
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..fa75df1
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gemspec
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..b9c0953
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,23 @@
+(c) 2018 Rob Watson
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5331c4d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+## jekyll-stealthy-share
+
+[![Build Status](https://travis-ci.org/rfwatson/jekyll-stealthy-share.svg?branch=master)](https://travis-ci.org/rfwatson/jekyll-stealthy-share)
+
+This is a [Jekyll](https://jekyllrb.com/) plugin that adds a Liquid tag to inject share buttons into your blog.
+
+The share buttons are HTML-only and trigger no JavaScript, so they won't track your blog's on behalf of Facebook, Twitter, Reddit or whoever else.
+
+The injected HTML and CSS is simple and easy to customize or extend.
+
+See it in action on https://netflux.io.
+
+## Installation
+
+Add `jekyll-stealthy-share` to your blog's Gemfile:
+
+```ruby
+group :jekyll_plugins do
+ gem 'jekyll-stealthy-share', git: 'https://github.com/rfwatson/jekyll-stealthy-share.git'
+end
+```
+
+And add it to your `_config.yml`:
+
+```yaml
+plugins:
+ - jekyll-stealthy-share
+```
+
+## Usage
+
+Somewhere in your layout (for example `_includes/head.html`), include the share button CSS:
+
+```html
+{% stealthy_share_assets %}
+```
+
+To inject the share buttons into your post, use this tag:
+
+```html
+{% stealthy_share_buttons %}
+```
+
+## Customizing/adding/removing buttons
+
+To re-order or remove buttons, you can pass arguments to the liquid tag. For example:
+
+```html
+{% stealthy_share_buttons: facebook, twitter, reddit %}
+```
+
+It's also possible to add new templates of your own. If a directory `_includes/share_buttons` exists in your site's root folder, `jekyll-stealthy-share` will read templates from this location instead.
+
+See the [`_includes` directory](https://github.com/rfwatson/jekyll-stealthy-share/tree/master/_includes) for an idea of the expected layout of each template. Additionally, you could choose to not include `{% stealthy_share_assets %}` and write your own custom CSS.
+
+## TODO
+
+* Add more share button options
+* Make customization of buttons easier (YAML file format to define?)
+* Improve default styling
+* Write unit tests
+
+## Contributions
+
+Welcome.
+
+## Credits
+
+The share button SVG templates, colours and some styling are all from http://sharingbuttons.io/.
+
+## License
+
+MIT
+
+## Contact
+
+rfwatson via GitHub
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..5d1930e
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+require "bundler/gem_tasks"
+require 'rspec/core/rake_task'
+
+task default: :spec
+
+RSpec::Core::RakeTask.new
diff --git a/_includes/_container.html b/_includes/_container.html
new file mode 100644
index 0000000..808a4fb
--- /dev/null
+++ b/_includes/_container.html
@@ -0,0 +1,7 @@
+
+
Share this post
+
If you enjoyed reading this post, please consider sharing it with your network.
+
+ {{ content }}
+
+
diff --git a/_includes/facebook.html b/_includes/facebook.html
new file mode 100644
index 0000000..66c7dc3
--- /dev/null
+++ b/_includes/facebook.html
@@ -0,0 +1,10 @@
+
diff --git a/assets/share.css b/assets/share.css
new file mode 100644
index 0000000..3871085
--- /dev/null
+++ b/assets/share.css
@@ -0,0 +1,93 @@
+.share_buttons {
+ margin: 30px auto;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ padding: 15px 0px;
+}
+
+.share_buttons > ul {
+ margin-left: 0px;
+ margin-bottom: 0px;
+}
+
+.share_buttons > ul > li {
+ list-style-type: none;
+ display: inline-block;
+}
+
+.share_buttons > ul > li > a, .icon {
+ display: inline-block;
+}
+
+.share_buttons > ul > li > a {
+ text-decoration: none;
+ color: #fff;
+ margin: 0.5em 0px;
+ line-height: 1.5em;
+}
+
+.share_buttons > ul > li > a > .button {
+ border-radius: 5px;
+ transition: 25ms ease-out;
+ padding: 0.5em 0.75em;
+ font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
+ text-align: center;
+ min-width: 120px;
+}
+
+.share_buttons > ul > li > a > .button > .icon {
+ fill: #fff;
+ stroke: none;
+ position: relative;
+ top: -1px;
+ left: 1px;
+}
+
+.share_buttons > ul > li > a > .button > .icon > svg {
+ width: 1em;
+ height: 1em;
+ margin-right: 0.4em;
+ line-height: 1em;
+}
+
+.share_buttons > ul > li > a > .button > .icon > svg > path {
+ fill: #fff;
+}
+
+.share_buttons > ul > li[data-service="facebook"] > a > .button {
+ background-color: #3b5998;
+ border-color: #3b5998;
+}
+
+.share_buttons > ul > li[data-service="facebook"] > a:active > .button,
+ .share_buttons > ul > li[data-service="facebook"] > a:hover > .button {
+ background-color: #2d4373;
+ border-color: #2d4373;
+}
+
+.share_buttons > ul > li[data-service="twitter"] > a > .button {
+ background-color: #55acee;
+}
+
+.share_buttons > ul > li[data-service="twitter"] > a:active > .button,
+ .share_buttons > ul > li[data-service="twitter"] > a:hover > .button {
+ background-color: #2795e9;
+}
+
+.share_buttons > ul > li[data-service="reddit"] > a > .button {
+ background-color: #5f99cf;
+}
+
+.share_buttons > ul > li[data-service="reddit"] > a:active > .button,
+ .share_buttons > ul > li[data-service="reddit"] > a:hover > .button {
+ background-color: #3a80c1;
+}
+
+.share_buttons > ul > li[data-service="hacker_news"] > a > .button {
+ background-color: #ff6600;
+}
+
+.share_buttons > ul > li[data-service="hacker_news"] > a:active > .button,
+ .share_buttons > ul > li[data-service="hacker_news"] > a:hover > .button {
+ background-color: #fb6200;
+}
diff --git a/jekyll-stealthy-share.gemspec b/jekyll-stealthy-share.gemspec
new file mode 100644
index 0000000..e0d3f67
--- /dev/null
+++ b/jekyll-stealthy-share.gemspec
@@ -0,0 +1,27 @@
+# encoding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'jekyll/stealthy_share/version'
+
+Gem::Specification.new do |spec|
+ spec.name = "jekyll-stealthy-share"
+ spec.version = Jekyll::StealthyShare::VERSION
+ spec.authors = ["Rob Watson"]
+ spec.email = ["hello@netflux.io"]
+ spec.description = %q{Privacy-conscious share buttons for Jekyll}
+ spec.summary = spec.description
+ spec.homepage = "https://github.com/rfwatson"
+ spec.license = "MIT"
+
+ spec.files = `git ls-files`.split($/)
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
+ spec.require_paths = ["lib"]
+
+ spec.add_development_dependency "bundler", "~> 1.16"
+ spec.add_development_dependency "rake"
+ spec.add_development_dependency "jekyll"
+ spec.add_development_dependency "rspec"
+ spec.add_development_dependency 'capybara'
+ spec.add_development_dependency 'byebug'
+end
diff --git a/lib/jekyll-stealthy-share.rb b/lib/jekyll-stealthy-share.rb
new file mode 100644
index 0000000..1769ba1
--- /dev/null
+++ b/lib/jekyll-stealthy-share.rb
@@ -0,0 +1,5 @@
+require 'jekyll'
+require 'jekyll/stealthy_share'
+
+Liquid::Template.register_tag('stealthy_share_buttons', Jekyll::StealthyShare::Tag)
+Liquid::Template.register_tag('stealthy_share_assets', Jekyll::StealthyShare::AssetTag)
diff --git a/lib/jekyll/stealthy_share.rb b/lib/jekyll/stealthy_share.rb
new file mode 100644
index 0000000..61e7904
--- /dev/null
+++ b/lib/jekyll/stealthy_share.rb
@@ -0,0 +1,33 @@
+require 'jekyll/stealthy_share/version'
+require 'jekyll/stealthy_share/template'
+require 'jekyll/stealthy_share/tag'
+require 'jekyll/stealthy_share/asset_tag'
+require 'jekyll/stealthy_share/generator'
+
+module Jekyll
+ module StealthyShare
+ class << self
+ attr_accessor :site
+
+ def base_path
+ File.join(File.dirname(__FILE__), '../..')
+ end
+
+ def templates_path
+ return source_templates_path if File.directory?(source_templates_path)
+
+ default_templates_path
+ end
+
+ private
+
+ def default_templates_path
+ File.join(base_path, '_includes')
+ end
+
+ def source_templates_path
+ File.join(site.source, '_includes', 'share_buttons')
+ end
+ end
+ end
+end
diff --git a/lib/jekyll/stealthy_share/asset_tag.rb b/lib/jekyll/stealthy_share/asset_tag.rb
new file mode 100644
index 0000000..1b25b3f
--- /dev/null
+++ b/lib/jekyll/stealthy_share/asset_tag.rb
@@ -0,0 +1,9 @@
+module Jekyll
+ module StealthyShare
+ class AssetTag < Liquid::Tag
+ def render(context)
+ %Q{}
+ end
+ end
+ end
+end
diff --git a/lib/jekyll/stealthy_share/generator.rb b/lib/jekyll/stealthy_share/generator.rb
new file mode 100644
index 0000000..3c4541c
--- /dev/null
+++ b/lib/jekyll/stealthy_share/generator.rb
@@ -0,0 +1,18 @@
+require 'jekyll/generator'
+
+module Jekyll
+ module StealthyShare
+ class Generator < Jekyll::Generator
+ def generate(site)
+ StealthyShare.site = site
+
+ site.static_files << StaticFile.new(
+ site,
+ StealthyShare.base_path,
+ 'assets',
+ 'share.css'
+ )
+ end
+ end
+ end
+end
diff --git a/lib/jekyll/stealthy_share/tag.rb b/lib/jekyll/stealthy_share/tag.rb
new file mode 100644
index 0000000..06c6786
--- /dev/null
+++ b/lib/jekyll/stealthy_share/tag.rb
@@ -0,0 +1,61 @@
+require 'liquid'
+
+module Jekyll
+ module StealthyShare
+ class Tag < Liquid::Tag
+ HTML = '.html'.freeze
+
+ def initialize(tag_name, text, tokens)
+ @text = text
+ end
+
+ def render(context)
+ permalink = page(context)['url']
+ title = page(context)['title']
+ url = URI.join(base_url(context), permalink)
+
+ buttons = templates.map do |template|
+ liquid_template = Liquid::Template.parse(template)
+ liquid_template.render(
+ 'url' => url.to_s,
+ 'title' => title.to_s
+ )
+ end
+
+ container = Template.read('_container.html').first
+ render_template(container, 'content' => buttons.join)
+ end
+
+ private
+
+ def render_template(template, data)
+ t = Liquid::Template.parse(template)
+ t.render(data)
+ end
+
+ def templates
+ basenames = @text.scan(/\w+/)
+ basenames = Template.basenames if basenames.empty?
+
+ basenames.map! do |basename|
+ basename.end_with?(HTML) ? basename : basename + HTML
+ end
+
+ missing = basenames - Template.basenames
+ if missing.any?
+ raise "Unknown share button templates: #{missing.inspect}."
+ end
+
+ Template.read(*basenames)
+ end
+
+ def page(context)
+ context.environments.first.page
+ end
+
+ def base_url(context)
+ context.registers[:site].config['url']
+ end
+ end
+ end
+end
diff --git a/lib/jekyll/stealthy_share/template.rb b/lib/jekyll/stealthy_share/template.rb
new file mode 100644
index 0000000..98f213e
--- /dev/null
+++ b/lib/jekyll/stealthy_share/template.rb
@@ -0,0 +1,26 @@
+module Jekyll
+ module StealthyShare
+ class Template
+ class << self
+ extend Forwardable
+ def_delegator StealthyShare, :templates_path
+
+ def basenames
+ all.map(&File.public_method(:basename)).sort
+ end
+
+ def read(*basenames)
+ basenames.map do |basename|
+ File.read(File.join(templates_path, basename))
+ end
+ end
+
+ private
+
+ def all
+ Dir.glob(File.join(templates_path, '[!_]*.html'))
+ end
+ end
+ end
+ end
+end
diff --git a/lib/jekyll/stealthy_share/version.rb b/lib/jekyll/stealthy_share/version.rb
new file mode 100644
index 0000000..956a5ab
--- /dev/null
+++ b/lib/jekyll/stealthy_share/version.rb
@@ -0,0 +1,5 @@
+module Jekyll
+ module StealthyShare
+ VERSION = '0.1.0'
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..9e9acfe
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,109 @@
+ENV['JEKYLL_LOG_LEVEL'] = 'warn'
+
+require 'jekyll'
+require 'byebug'
+require 'capybara/rspec'
+require_relative 'support/helpers'
+
+# This file was generated by the `rspec --init` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
+ # have no way to turn it off -- the option exists only for backwards
+ # compatibility in RSpec 3). It causes shared context metadata to be
+ # inherited by the metadata hash of host groups and examples, rather than
+ # triggering implicit auto-inclusion in groups with matching metadata.
+ config.shared_context_metadata_behavior = :apply_to_host_groups
+
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+ # This allows you to limit a spec run to individual examples or groups
+ # you care about by tagging them with `:focus` metadata. When nothing
+ # is tagged with `:focus`, all examples get run. RSpec also provides
+ # aliases for `it`, `describe`, and `context` that include `:focus`
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
+ config.filter_run_when_matching :focus
+
+ # Allows RSpec to persist some state between runs in order to support
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # you configure your source control system to ignore this file.
+ config.example_status_persistence_file_path = "spec/examples.txt"
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
+ config.disable_monkey_patching!
+
+ # This setting enables warnings. It's recommended, but in some cases may
+ # be too noisy due to issues in dependencies.
+ config.warnings = true
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = "doc"
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+=end
+
+ config.include Helpers
+end
diff --git a/spec/stealthy_share_spec.rb b/spec/stealthy_share_spec.rb
new file mode 100644
index 0000000..8f78098
--- /dev/null
+++ b/spec/stealthy_share_spec.rb
@@ -0,0 +1,60 @@
+require 'jekyll/stealthy_share'
+
+RSpec.describe Jekyll::StealthyShare, type: :feature do
+ subject { page }
+
+ context 'on a basic site' do
+ include_context 'basic site'
+
+ context 'a page with share buttons injected' do
+ before do
+ visit '/2018/01/01/buttons.html'
+ end
+
+ it { is_expected.to have_css('.share_buttons') }
+ it { is_expected.to have_content('Share this post') }
+
+ it 'injects all buttons' do
+ count = page.all('.share_buttons li').size
+ expect(count).to eq 4
+ end
+ end
+
+ context 'a page with no share buttons injected' do
+ before do
+ visit '/2018/01/02/no-buttons.html'
+ end
+
+ it { is_expected.not_to have_css('.share_buttons') }
+ it { is_expected.not_to have_content('Share this:') }
+ end
+ end
+
+ context 'a site with overrides' do
+ include_context 'a site with overrides'
+
+ context 'a page with share buttons injected' do
+ before do
+ visit '/2018/01/01/buttons.html'
+ end
+
+ it { is_expected.to have_css('.share_buttons') }
+ it { is_expected.to have_content('Share this:') }
+ it { is_expected.to have_content('Test button') }
+
+ it 'injects all buttons' do
+ count = page.all('.share_buttons li').size
+ expect(count).to eq 1
+ end
+ end
+
+ context 'a page with no share buttons injected' do
+ before do
+ visit '/2018/01/02/no-buttons.html'
+ end
+
+ it { is_expected.not_to have_css('.share_buttons') }
+ it { is_expected.not_to have_content('Share this:') }
+ end
+ end
+end
diff --git a/spec/support/fixtures/basic/_config.yml b/spec/support/fixtures/basic/_config.yml
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/fixtures/basic/_posts/2018-01-01-buttons.md b/spec/support/fixtures/basic/_posts/2018-01-01-buttons.md
new file mode 100644
index 0000000..ffe3618
--- /dev/null
+++ b/spec/support/fixtures/basic/_posts/2018-01-01-buttons.md
@@ -0,0 +1,7 @@
+---
+title: hello
+---
+
+Hello world
+
+{% stealthy_share_buttons %}
diff --git a/spec/support/fixtures/basic/_posts/2018-01-02-no-buttons.md b/spec/support/fixtures/basic/_posts/2018-01-02-no-buttons.md
new file mode 100644
index 0000000..b5b3f8f
--- /dev/null
+++ b/spec/support/fixtures/basic/_posts/2018-01-02-no-buttons.md
@@ -0,0 +1,5 @@
+---
+title: hello
+---
+
+Hello world
diff --git a/spec/support/fixtures/overrides/_config.yml b/spec/support/fixtures/overrides/_config.yml
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/fixtures/overrides/_includes/share_buttons/_container.html b/spec/support/fixtures/overrides/_includes/share_buttons/_container.html
new file mode 100644
index 0000000..cc89cd1
--- /dev/null
+++ b/spec/support/fixtures/overrides/_includes/share_buttons/_container.html
@@ -0,0 +1,6 @@
+
+
Share this:
+
+ {{ content }}
+
+
diff --git a/spec/support/fixtures/overrides/_includes/share_buttons/button.html b/spec/support/fixtures/overrides/_includes/share_buttons/button.html
new file mode 100644
index 0000000..c224dbb
--- /dev/null
+++ b/spec/support/fixtures/overrides/_includes/share_buttons/button.html
@@ -0,0 +1 @@
+
Test button
diff --git a/spec/support/fixtures/overrides/_posts/2018-01-01-buttons.md b/spec/support/fixtures/overrides/_posts/2018-01-01-buttons.md
new file mode 100644
index 0000000..ffe3618
--- /dev/null
+++ b/spec/support/fixtures/overrides/_posts/2018-01-01-buttons.md
@@ -0,0 +1,7 @@
+---
+title: hello
+---
+
+Hello world
+
+{% stealthy_share_buttons %}
diff --git a/spec/support/fixtures/overrides/_posts/2018-01-02-no-buttons.md b/spec/support/fixtures/overrides/_posts/2018-01-02-no-buttons.md
new file mode 100644
index 0000000..b5b3f8f
--- /dev/null
+++ b/spec/support/fixtures/overrides/_posts/2018-01-02-no-buttons.md
@@ -0,0 +1,5 @@
+---
+title: hello
+---
+
+Hello world
diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb
new file mode 100644
index 0000000..8d9c93b
--- /dev/null
+++ b/spec/support/helpers.rb
@@ -0,0 +1,34 @@
+module Helpers
+ shared_context 'shared' do
+ let(:config) do
+ Jekyll.configuration(
+ 'source' => source,
+ 'destination' => File.expand_path('_site'),
+ 'url' => 'http://www.example.com',
+ 'name' => 'Test site',
+ 'plugins' => ['jekyll-stealthy-share']
+ )
+ end
+
+ let(:site) do
+ Jekyll::Site.new(config)
+ end
+
+ before do
+ site.process
+ Capybara.app = Rack::File.new(site.dest)
+ end
+ end
+
+ shared_context 'basic site' do
+ include_context 'shared'
+
+ let(:source) { File.expand_path('spec/support/fixtures/basic') }
+ end
+
+ shared_context 'a site with overrides' do
+ include_context 'shared'
+
+ let(:source) { File.expand_path('spec/support/fixtures/overrides') }
+ end
+end