├── .github └── dependabot.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .ruby-version ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.md ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── jekyll-test.gemspec ├── lib └── jekyll │ ├── test.rb │ └── test │ ├── jekyll.rake │ ├── tasks.rb │ ├── travis.rake │ └── version.rb └── spec ├── jekyll └── test_spec.rb └── spec_helper.rb /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | allow: 9 | - dependency-type: direct 10 | - dependency-type: indirect 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | 11 | # rspec failure tracking 12 | .rspec_status 13 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | AllCops: 4 | TargetRubyVersion: 2.5 5 | 6 | Style/StringLiterals: 7 | EnforcedStyle: double_quotes 8 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2018-10-30 21:18:33 +0100 using RuboCop version 0.60.0. 4 | # The point is for the user to remove these configuration records 5 | # one by one as the offenses are removed from the code base. 6 | # Note that changes in the inspected code, or installation of new 7 | # versions of RuboCop, may require this file to be generated again. 8 | 9 | # Offense count: 4 10 | # Configuration parameters: CountComments, ExcludedMethods. 11 | # ExcludedMethods: refine 12 | Metrics/BlockLength: 13 | Max: 28 14 | 15 | # Offense count: 1 16 | Style/Documentation: 17 | Exclude: 18 | - 'lib/jekyll/test.rb' 19 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.0.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: ruby 3 | cache: bundler 4 | rvm: 5 | - 2.5.8 6 | - 2.6.6 7 | - 2.7.2 8 | - 3.0.0 9 | before_install: 10 | - gem update --system 11 | - gem install bundler 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.5.0 4 | 5 | * Support Ruby 3 6 | * Update travis configurator to use Ruby 3 7 | 8 | ## 1.4.0 9 | 10 | * Support Jekyll 4 in gem dependencies 11 | * Upgrade bundler and use Ruby 2.6.4 on Travis builds 12 | ## 1.3.2 13 | 14 | * Remove hard dependency on travis gem - if you want to configure travis, you'll need to install the gem in your own project. 15 | 16 | ## 1.3.1 17 | 18 | * Drop support for Ruby < 2.5 19 | * Use bundler 2.0 20 | 21 | ## 1.3.0 22 | 23 | * Run travis builds on 2.6.3 24 | 25 | Rerun `rake jekyll:configure:travis` to get the new configuration. 26 | 27 | ## 1.2.0 28 | 29 | * Check SRI tags by default 30 | * Automatically handle sites with non-empty baseurl 31 | * Run travis builds on 2.5.3 32 | 33 | Rerun `rake jekyll:configure:travis` to get the new configuration. 34 | 35 | ## 1.1.1 36 | 37 | * Support Ruby 2.5.0 38 | * Update travis builds to run on Ruby 2.4.3 (travis currently has issues with 2.5.0) 39 | 40 | Rerun `rake jekyll:configure:travis` to get the new configuration. 41 | 42 | ## 1.1.0 43 | 44 | * Update travis configuration to fix SSL check errors. 45 | * Update travis builds to run on Ruby 2.4.2 46 | 47 | Rerun `rake jekyll:configure:travis` to get the new configuration. 48 | 49 | ## 1.0.0 50 | 51 | * Added `jekyll:configure:travis` task to automatically configure travis matrix builds. 52 | * Added jekyll itself as a dependency 53 | * Use correct destination directory for builds and tests 54 | 55 | ## 0.2.0 56 | 57 | * Add Rake tasks to check validity and links. 58 | 59 | ## 0.1.0 60 | 61 | * initial release, pulls in required dependencies for testing. 62 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at james@floppy.org.uk. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } 6 | 7 | # Specify your gem's dependencies in jekyll-test.gemspec 8 | gemspec 9 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2017 jekyll-test contributors 2 | 3 | # MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jekyll-Test 2 | 3 | `jekyll-test` is a highly opinionated test configuration for Jekyll sites to let you create well-formed sites with minimal configuration, built on top of [html-proofer](https://github.com/gjtorikian/html-proofer). 4 | 5 | It provides two rake tasks: 6 | 7 | `jekyll:check` will test your site for HTML validity, internal link correctness, alt tags, OpenGraph validity, https usage, and a load more. It will complain about as much as it can. You want this to pass. 8 | 9 | `jekyll:check_external_links` will check all outgoing links as well. This is a separate task as this often fails due to network errors, etc, and you don't want to depend on it passing. Use it for information only. 10 | 11 | ## Requirements 12 | 13 | * Ruby 2.5 or higher (`ruby -v` to check version) 14 | * Bundler (`gem install bundler` if it's not there) 15 | 16 | ## Usage 17 | 18 | Add `jekyll-test` to your site's `Gemfile` (or just create the file with the following content if it doesn't exist) and run `bundle`: 19 | 20 | ```ruby 21 | source "https://rubygems.org" 22 | 23 | gem 'rake' 24 | gem 'github-pages' 25 | 26 | group :test do 27 | gem 'jekyll-test' 28 | end 29 | ``` 30 | 31 | Then add this to `Rakefile` (or create a file with just this in it if you don't have one): 32 | 33 | ```ruby 34 | require 'jekyll/test/tasks' 35 | ``` 36 | 37 | We suggest making `jekyll:check` your default task by adding this line to `Rakefile` as well: 38 | 39 | ```rake 40 | task default: "jekyll:check" 41 | ``` 42 | 43 | You can then run `rake` and bingo, your site will be tested with `html-proofer`. 44 | 45 | ### Travis configuration 46 | 47 | To configure a travis build to run these tests, run: 48 | 49 | ``` 50 | gem install travis 51 | rake jekyll:configure:travis 52 | ``` 53 | 54 | This will initialise your repo for use on travis, if necessary, then write a multi-build configuration which will run both checks together. The link check is allowed to fail, so it will not impact your CI success / failure. 55 | 56 | WARNING: This will aggressively overwrite bits of `.travis.yml`, so if you already have one, make sure it's committed or backed up so you can check the changes. 57 | 58 | It's a good idea to run the task with each new release of this gem to get the latest configuration. 59 | 60 | ## Coming soon 61 | 62 | * spellchecking 63 | 64 | ## Contributing 65 | 66 | Bug reports and pull requests are welcome on GitHub at https://github.com/Floppy/jekyll-test. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 67 | 68 | ## Code of Conduct 69 | 70 | Everyone interacting in the Jekyll::Test project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/jekyll-test/blob/master/CODE_OF_CONDUCT.md). 71 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/gem_tasks" 4 | require "rspec/core/rake_task" 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | task default: :spec 9 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "jekyll/test" 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require "irb" 15 | IRB.start(__FILE__) 16 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /jekyll-test.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path("lib", __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require "jekyll/test/version" 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = "jekyll-test" 9 | spec.version = Jekyll::Test::VERSION 10 | spec.licenses = ["MIT"] 11 | spec.authors = ["James Smith"] 12 | spec.email = ["james@floppy.org.uk"] 13 | 14 | spec.summary = "A highly opinionated test configuration for Jekyll sites." 15 | spec.homepage = "https://github.com/Floppy/jekyll-test" 16 | 17 | if spec.respond_to?(:metadata) 18 | spec.metadata["allowed_push_host"] = "https://rubygems.org" 19 | else 20 | raise "RubyGems 2.0 or newer is required to protect against " \ 21 | "public gem pushes." 22 | end 23 | 24 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 25 | f.match(%r{^(test|spec|features)/}) 26 | end 27 | spec.bindir = "exe" 28 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 29 | spec.require_paths = ["lib"] 30 | 31 | spec.required_ruby_version = [">= 2.5", "< 4.0"] 32 | 33 | spec.add_dependency "html-proofer", "~> 3.11" 34 | spec.add_dependency "jekyll", ">= 3.0", "< 5.0" 35 | spec.add_dependency "rake", ">= 12", "< 14" 36 | spec.add_dependency "rspec", "~> 3.0" 37 | spec.add_dependency "rspec-html-matchers", "~> 0.9" 38 | 39 | spec.add_development_dependency "bundler", "~> 2.0" 40 | spec.add_development_dependency "rubocop", "~> 1.0" 41 | end 42 | -------------------------------------------------------------------------------- /lib/jekyll/test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "jekyll/test/version" 4 | 5 | module Jekyll 6 | module Test 7 | # Your code goes here... 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/jekyll/test/jekyll.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "html-proofer" 4 | 5 | def default_options 6 | { 7 | assume_extension: ".html", 8 | typhoeus: { 9 | ssl_verifypeer: false, 10 | ssl_verifyhost: 0, 11 | timeout: 3 12 | } 13 | } 14 | end 15 | 16 | def check_site(options = {}) 17 | HTMLProofer.check_directory( 18 | jekyll_site_directory, 19 | default_options.merge(options) 20 | ).run 21 | end 22 | 23 | def jekyll_config 24 | File.exist?("_config.yml") ? YAML.load_file("_config.yml") : {} 25 | end 26 | 27 | def jekyll_site_directory 28 | jekyll_config["destination"] || "./_site" 29 | end 30 | 31 | def baseurl 32 | jekyll_config["baseurl"] || "" 33 | end 34 | 35 | namespace :jekyll do 36 | task :rebuild do 37 | sh "rm -rf #{jekyll_site_directory}" 38 | sh "bundle exec jekyll build" 39 | end 40 | 41 | task check: :rebuild do 42 | check_site( 43 | check_html: true, 44 | check_favicon: true, 45 | check_sri: true, 46 | check_img_http: true, 47 | check_opengraph: true, 48 | disable_external: true, 49 | url_swap: { 50 | /^#{baseurl}/ => "" 51 | } 52 | ) 53 | end 54 | 55 | task check_external_links: :rebuild do 56 | check_site( 57 | url_ignore: [], 58 | check_external_hash: true 59 | ) 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/jekyll/test/tasks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $VERBOSE = nil 4 | Dir["#{File.dirname(__FILE__)}/*.rake"].each { |ext| load ext } 5 | -------------------------------------------------------------------------------- /lib/jekyll/test/travis.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | namespace :jekyll do 4 | namespace :configure do 5 | task :travis do 6 | # Initialise travis 7 | sh "bundle exec travis init" unless File.exist?(".travis.yml") 8 | # Load existing configuration 9 | travis = YAML.load_file(".travis.yml") 10 | # Update configuration 11 | travis["rvm"] = "3.0.0" 12 | travis["sudo"] = false 13 | travis["cache"] = "bundler" 14 | travis["addons"] = { 15 | "apt" => { 16 | "packages" => [ 17 | "libcurl4-openssl-dev" 18 | ] 19 | } 20 | } 21 | travis["env"] = [ 22 | %(TASK='jekyll:check'), 23 | %(TASK='jekyll:check_external_links') 24 | ] 25 | travis["matrix"] = { 26 | "fast_finish" => true, 27 | "allow_failures" => [{ 28 | "env" => %(TASK='jekyll:check_external_links') 29 | }] 30 | } 31 | travis["script"] = "bundle exec rake $TASK" 32 | travis["before_install"] = [ 33 | "gem update --system", 34 | "gem install bundler" 35 | ] 36 | # Output 37 | File.write(".travis.yml", travis.to_yaml) 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/jekyll/test/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Jekyll 4 | module Test 5 | VERSION = "1.5.0" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/jekyll/test_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | RSpec.describe Jekyll::Test do 6 | it "has a version number" do 7 | expect(Jekyll::Test::VERSION).not_to be nil 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/setup" 4 | require "jekyll/test" 5 | 6 | RSpec.configure do |config| 7 | # Enable flags like --only-failures and --next-failure 8 | config.example_status_persistence_file_path = ".rspec_status" 9 | 10 | # Disable RSpec exposing methods globally on `Module` and `main` 11 | config.disable_monkey_patching! 12 | 13 | config.expect_with :rspec do |c| 14 | c.syntax = :expect 15 | end 16 | end 17 | --------------------------------------------------------------------------------