jekyll-git-authors 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73738a3355402aebd9970f7e614524d0ce9a966f9f9589051f9cc95cbec334b9
4
- data.tar.gz: 16431182d8bda9f840291c0b8545e7ea247b20b17f7252fbc3d45d497e1488d3
3
+ metadata.gz: 5d79ac6675cf9272be647f7c39270514d4e29f4405302d72b60a9f96704267a4
4
+ data.tar.gz: fc858a9204cb0ff846422b75f84df532b6c46c5ccf1eaefde0277873f3e8cd61
5
5
  SHA512:
6
- metadata.gz: f8a0275a90429c8f5136689dbfc3ecf112de4967ffddb2bc2783992487c9794b31e1c5c4070589f1bfd807f850740cf9496d281a43a79131886a919b7487fbe7
7
- data.tar.gz: 18c332e37a3308d65a172705b5949dba8351b33da4dd6550fb628a772628b2f7e85a5ff37d05e85cf67ff803a3266e771e4035835da197358fb7cbc4d242a506
6
+ metadata.gz: 8e394c23ab9d5f9a523f7da65e111e24c50879a472c20115abf614ace6f673f794c2dde0beebf728c9ce88ecb4ecf5c7b59004ca23b27f8d6d48aac78d302ddd
7
+ data.tar.gz: 200b1990014d53dca919c14dd6987514040dab36363606267abad1bc1c7371f1daa70f04a2b996d8a2c1027e994904bd4e33e762c03b19c358ef556bef32805e
@@ -0,0 +1,42 @@
1
+ Layout/MultilineMethodCallIndentation:
2
+ EnforcedStyle: indented
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'jekyll-git-authors.gemspec'
7
+
8
+ Metrics/MethodLength:
9
+ Max: 15
10
+
11
+ Metrics/LineLength:
12
+ Max: 110
13
+ Exclude:
14
+ - 'features/**/*'
15
+
16
+ Naming/BinaryOperatorParameterName:
17
+ Enabled: false
18
+
19
+ Naming/FileName:
20
+ Enabled: false
21
+
22
+ Style/BarePercentLiterals:
23
+ EnforcedStyle: percent_q
24
+
25
+ Style/Documentation:
26
+ Enabled: false
27
+
28
+ Style/HashSyntax:
29
+ EnforcedStyle: hash_rockets
30
+
31
+ Style/ParallelAssignment:
32
+ Enabled: false
33
+
34
+ Style/PercentLiteralDelimiters:
35
+ PreferredDelimiters:
36
+ default: '||'
37
+
38
+ Style/RegexpLiteral:
39
+ Enabled: false
40
+
41
+ Style/SymbolArray:
42
+ EnforcedStyle: brackets
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  git_source(:gitlab) { |repo_name| "https://gitlab.com/#{repo_name}" }
4
4
 
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018 jackorp
3
+ Copyright (c) 2018 Jaroslav Prokop
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/Rakefile CHANGED
@@ -1,13 +1,16 @@
1
1
  require 'rake/testtask'
2
2
  require 'cucumber/rake/task'
3
+ require 'rubocop/rake_task'
3
4
 
4
- desc "Run tests by default"
5
- task :default => [:test]
5
+ desc 'Run tests by default'
6
+ task :default => [:test, :rubocop]
6
7
 
7
8
  Rake::TestTask.new(:test) do |t|
8
- t.libs = ["lib"]
9
+ t.libs = ['lib']
9
10
  t.verbose = true
10
11
  t.test_files = FileList['test/*_test.rb']
11
12
  end
12
13
 
13
14
  Cucumber::Rake::Task.new(:test)
15
+
16
+ RuboCop::RakeTask.new(:rubocop)
@@ -0,0 +1,36 @@
1
+ Feature: Jekyll-git-authors uses options specified by user
2
+
3
+ Background:
4
+ Given There is a fixture named "page.md" and it is in a subdirectory named "subdir"
5
+
6
+ Scenario: User wants to have different number of max authors
7
+ Given There is 8 commits on the "subdir/page.md"
8
+ And There is "_config.yml" with "max_authors" set to "7"
9
+ When Jekyll generates authors with set option
10
+ Then There should be 7 authors on the "subdir/page.md"
11
+
12
+ Scenario: User sets multiple options at once
13
+ Given There are 2 commits on the "subdir/page.md"
14
+ And There is "_config.yml" with following configuration:
15
+ """
16
+ git_authors:
17
+ center: false
18
+ thematic_break: false
19
+ prefix: 'Contributors:'
20
+ """
21
+ When Jekyll generates authors with set option
22
+ Then Authors should not be centered
23
+ And Authors should not have thematic break
24
+ And Authors should have "Contributors:" prefix
25
+
26
+ Scenario Outline: Setting one option
27
+ Given There are 2 commits on the "subdir/page.md"
28
+ And There is "_config.yml" with "<option>" set to "<value>"
29
+ When Jekyll generates authors with set option
30
+ Then Authors should <result>
31
+
32
+ Examples:
33
+ | option | value | result |
34
+ | center | false | not be centered |
35
+ | thematic_break | false | not have thematic break |
36
+ | prefix | 'Contributors:' | have "Contributors:" prefix |
@@ -2,11 +2,9 @@ Feature: Jekyll renders output of jekyll-git-authors
2
2
 
3
3
  Background:
4
4
  Given There is a fixture named "page.md" and it is in a subdirectory named "subdir"
5
- And Git is intialized
6
5
 
7
6
  Scenario: Authors are generated correctly
8
7
  Given There are 6 commits on the "subdir/page.md"
9
- And All commits on "subdir/page.md" have different authors
10
8
  When Jekyll-git-authors generates authors
11
9
  Then There should be 5 authors on the "subdir/page.md"
12
10
 
@@ -17,3 +15,21 @@ Feature: Jekyll renders output of jekyll-git-authors
17
15
  When Jekyll-git-authors generates authors
18
16
  Then There should be 0 authors on the "page.md"
19
17
  But There should be 1 author on the "subdir/page.md"
18
+
19
+ Scenario Outline: Generating authors when there are multiple commits from same author
20
+ Given There is a fixture "subdir/page.md"
21
+ And There are <different> commits from different authors on the "subdir/page.md"
22
+ And There are <same> commits from the same author on the "subdir/page.md"
23
+ When Jekyll-git-authors generates authors
24
+ Then There should be <authors> authors on the "subdir/page.md"
25
+
26
+ Examples:
27
+ | same | different | authors |
28
+ | 2 | 1 | 2 |
29
+ | 5 | 5 | 5 |
30
+ | 3 | 2 | 3 |
31
+ | 0 | 10 | 5 |
32
+ | 10 | 0 | 1 |
33
+ | 1 | 1 | 2 |
34
+ | 10 | 1 | 2 |
35
+ | 1 | 10 | 5 |
@@ -0,0 +1,51 @@
1
+ Given('There is {string} with {string} set to {string}') do |config_yml, option, value|
2
+ File.open(config_yml, 'w') do |file|
3
+ file.write("git_authors:\n #{option}: #{value}")
4
+ end
5
+ jekyll_configuration = Jekyll::Configuration.new
6
+ config = jekyll_configuration.read_config_file(config_yml)
7
+ @site_config = Jekyll::Configuration.from config
8
+ end
9
+
10
+ Given('There is {string} with following configuration:') do |config_yml, options|
11
+ File.open('_config.yml', 'w') { |file| file.write(options) }
12
+ jekyll_configuration = Jekyll::Configuration.new
13
+ config = jekyll_configuration.read_config_file(config_yml)
14
+ @site_config = Jekyll::Configuration.from config
15
+ end
16
+
17
+ When('Jekyll generates authors with set option') do
18
+ @site_config['source'] = @dir
19
+ @site_config['destination'] = File.join(@dir, '_site')
20
+ # Suppress jekyll log output.
21
+ Jekyll.logger.log_level = :error
22
+
23
+ @site = Jekyll::Site.new(@site_config)
24
+ authors_generator = Jekyll::AuthorsGenerator.new(@site.config)
25
+ @site.generators = Array(authors_generator)
26
+
27
+ # Make jekyll generate every page found and add them into site.pages variable.
28
+ files = Dir.glob File.join('**', '*.md')
29
+ files.each do |file|
30
+ @page = Jekyll::Page.new(@site, File.expand_path(Dir.pwd), '', file)
31
+ @site.pages << @page
32
+ end
33
+ @site.generate
34
+ end
35
+
36
+ Then('Authors should not be centered') do
37
+ center = %r|\{:center: style="text-align: center"\}\n[^\n]*\n\{:center\}|
38
+ page = @site.pages.find { |p| p.path == 'subdir/page.md' }
39
+ expect(page.content).to_not match(center)
40
+ end
41
+
42
+ Then('Authors should not have thematic break') do
43
+ thematic_break = %r|\n_ _ _ _\n{: #authors-rule}|
44
+ page = @site.pages.find { |p| p.path == 'subdir/page.md' }
45
+ expect(page.content).to_not match(thematic_break)
46
+ end
47
+
48
+ Then('Authors should have {string} prefix') do |prefix|
49
+ page = @site.pages.find { |p| p.path == 'subdir/page.md' }
50
+ expect(page.content).to match(prefix)
51
+ end
@@ -1,37 +1,34 @@
1
- Given("There is a fixture named {string} and it is in a subdirectory named {string}") do |file, subdir|
1
+ Given('There is a fixture named {string} and it is in a subdirectory named {string}') do |file, subdir|
2
2
  FileUtils.cp "#{@original_dir}/features/fixtures/#{file}", File.join(@dir, subdir)
3
3
  expect(File).to exist(File.join(subdir, file))
4
4
  end
5
5
 
6
- Given("Git is intialized") do
7
- GitHelper.init_repo
8
- end
9
-
10
- Given("There is a fixture {string}") do |file|
6
+ Given('There is a fixture {string}') do |file|
11
7
  FileUtils.cp "#{@original_dir}/features/fixtures/page.md", @dir
12
8
  expect(File).to exist(file)
13
9
  end
14
10
 
15
- Given("All commits on {string} have different authors") do |file|
16
- log = Git.log(file).author_email
11
+ Given('There is/are {int} commit(s)( from different authors) on the {string}') do |int, file|
12
+ next if int.zero?
17
13
 
18
- expect(log).to be_a_kind_of(Hash)
14
+ GitHelper.add_commits_different_authors file, int
19
15
  end
20
16
 
21
- Given("There is/are {int} commit(s) on the {string}") do |int, file|
22
- GitHelper.add_commit int, file
17
+ Given('There are {int} commits from the same author on the {string}') do |int, file|
18
+ next if int.zero?
23
19
 
24
- log = Git.execute("log --oneline #{file}").split("\n")
25
- expect(log.size).to eq(int)
20
+ GitHelper.add_commits_same_authors file, int
26
21
  end
27
22
 
28
- When("Jekyll-git-authors generates authors") do
23
+ When('Jekyll-git-authors generates authors') do
29
24
  # Jekyll::Site does not load directory properly if
30
25
  # defaults are being loaded more than once.
31
26
  # Workaround is copying it into variable and override directories.
32
27
  site_config = Jekyll::Configuration::DEFAULTS.dup
33
28
  site_config['source'] = @dir
34
29
  site_config['destination'] = File.join(@dir, '_site')
30
+ # Suppress jekyll log output.
31
+ Jekyll.logger.log_level = :error
35
32
 
36
33
  @site = Jekyll::Site.new(site_config)
37
34
  authors_generator = Jekyll::AuthorsGenerator.new(@site.config)
@@ -46,10 +43,10 @@ When("Jekyll-git-authors generates authors") do
46
43
  @site.generate
47
44
  end
48
45
 
49
- Then("There should be {int} author(s) on the {string}") do |int, file|
46
+ Then('There should be {int} author(s) on the {string}') do |int, file|
50
47
  page = @site.pages.find { |p| p.path == file }
51
48
  expression = /\[[^\]]+\]\(mailto:\{\{ '[^']*' \| encode_email \}\}\)/
52
- matched_authors = (page.content.scan(expression)).size
49
+ matched_authors = page.content.scan(expression).size
53
50
 
54
51
  expect(matched_authors).to eq(int)
55
52
  end
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __dir__)
2
2
  require 'tmpdir'
3
3
  require 'fileutils'
4
4
  require 'jekyll'
@@ -18,6 +18,9 @@ Before do
18
18
  Dir.mkdir @subdir
19
19
 
20
20
  Dir.chdir @dir
21
+
22
+ # Initialize git
23
+ GitHelper.init_repo
21
24
  end
22
25
 
23
26
  After do
@@ -1,27 +1,49 @@
1
1
  module GitHelper
2
2
  # Initialize git environment in current directory.
3
+ # @commit_count is used to track how many times was the author changed.
3
4
  def self.init_repo
4
- Git.execute 'init'
5
+ JekyllGitAuthors::Git.execute 'init'
5
6
 
6
- change_author('')
7
+ @commit_count = 0
7
8
  end
8
9
 
9
10
  # Change the author name and email by adding additional_info provided when the function gets called.
10
11
  def self.change_author(additional_info)
11
- Git.execute "config user.email 'you#{additional_info}@example.com'"
12
- Git.execute "config user.name 'Your Name #{additional_info}'"
12
+ JekyllGitAuthors::Git.execute "config user.email 'you#{additional_info}@example.com'"
13
+ JekyllGitAuthors::Git.execute "config user.name 'Your Name #{additional_info}'"
13
14
  end
14
15
 
15
16
  # Write "Commit #'number'" into the file and then commit the change
16
- # The authors will have name "Your name 'number'" and email "you'number'@example.com"
17
- def self.add_commit(number, file)
18
- number.times do |num|
19
- open(file, 'a') do |f|
20
- f << "\nCommit #" + "#{num}"
21
- end
22
- change_author num
23
- Git.execute "add #{file}"
24
- Git.execute 'commit -m "Commit #' + "#{num}" + '."'
17
+ def self.add_commit(file)
18
+ File.open(file, 'a') do |f|
19
+ f << "\nCommit ##{@commit_count}"
20
+ end
21
+
22
+ JekyllGitAuthors::Git.execute "add #{file}"
23
+ JekyllGitAuthors::Git.execute %Q|commit -m "Commit ##{@commit_count}."|
24
+ end
25
+
26
+ # Add multiple commits from same author.
27
+ #
28
+ # First increment commit_count then n times commit
29
+ def self.add_commits_same_authors(file, number = 1)
30
+ @commit_count += 1
31
+ change_author @commit_count
32
+
33
+ number.times do
34
+ add_commit file
35
+ end
36
+ end
37
+
38
+ # Commit multiple times with different authors.
39
+ #
40
+ # N times increment commit_count and then commit.
41
+ def self.add_commits_different_authors(file, number = 1)
42
+ number.times do
43
+ @commit_count += 1
44
+ change_author @commit_count
45
+
46
+ add_commit file
25
47
  end
26
48
  end
27
49
  end
@@ -1,38 +1,40 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "jekyll-git-authors/version"
3
+ require 'jekyll-git-authors/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "jekyll-git-authors"
6
+ spec.name = 'jekyll-git-authors'
7
7
  spec.version = JekyllGitAuthors::VERSION
8
- spec.authors = ["Jaroslav Prokop"]
9
- spec.email = ["jar.prokop@volny.cz"]
8
+ spec.authors = ['Jaroslav Prokop']
9
+ spec.email = ['jar.prokop@volny.cz']
10
10
 
11
- spec.summary = %q{Jekyll plugin that adds git authors into your page.}
12
- spec.description = %q{Jekyll plugin that adds git authors and their obfuscated email address into page using markdown and liquid.}
13
- spec.homepage = "https://gitlab.com/jackorp/jekyll-git-authors"
14
- spec.license = "MIT"
11
+ spec.summary = 'Jekyll plugin that adds git authors into your page.'
12
+ spec.description = 'Jekyll plugin that adds git authors and their obfuscated email address' \
13
+ 'into page using markdown and liquid.'
14
+ spec.homepage = 'https://gitlab.com/jackorp/jekyll-git-authors'
15
+ spec.license = 'MIT'
15
16
 
16
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
18
  # to allow pushing to a single host or delete this section to allow pushing to any host.
18
19
  if spec.respond_to?(:metadata)
19
- spec.metadata["allowed_push_host"] = 'https://rubygems.org'
20
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
20
21
  else
21
- raise "RubyGems 2.0 or newer is required to protect against " \
22
- "public gem pushes."
22
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
23
+ 'public gem pushes.'
23
24
  end
24
25
 
25
26
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
27
  spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
- spec.require_paths = ["lib"]
28
+ spec.require_paths = ['lib']
28
29
 
29
- spec.add_dependency "jekyll"
30
- spec.add_dependency "jekyll-email-protect"
30
+ spec.add_dependency 'jekyll'
31
+ spec.add_dependency 'jekyll-email-protect'
31
32
 
32
- spec.add_development_dependency "simplecov"
33
- spec.add_development_dependency "bundler", "~> 1.16"
34
- spec.add_development_dependency "rake", "~> 10.0"
35
- spec.add_development_dependency "minitest"
36
- spec.add_development_dependency "cucumber"
37
- spec.add_development_dependency "rspec"
33
+ spec.add_development_dependency 'bundler', '~> 1.16'
34
+ spec.add_development_dependency 'cucumber'
35
+ spec.add_development_dependency 'minitest'
36
+ spec.add_development_dependency 'rake', '~> 12'
37
+ spec.add_development_dependency 'rspec'
38
+ spec.add_development_dependency 'rubocop'
39
+ spec.add_development_dependency 'simplecov'
38
40
  end
@@ -1,50 +1,67 @@
1
1
  require 'jekyll-git-authors/version'
2
2
  require 'jekyll-git-authors/markdown'
3
3
  require 'jekyll-git-authors/git'
4
+ require 'jekyll-git-authors/author'
4
5
 
5
6
  require 'jekyll'
6
7
 
7
- # This script gets last 5 authors of a file and writes them at the end of the file.
8
-
9
8
  module Jekyll
10
9
  class AuthorsGenerator < Generator
11
10
  safe true
12
11
  priority :high
13
12
 
13
+ def initialize(config = {})
14
+ super(config)
15
+
16
+ @options = {
17
+ 'max_authors' => 5,
18
+ 'center' => true,
19
+ 'thematic_break' => true,
20
+ 'prefix' => 'Authors:'
21
+ }.merge(config['git_authors'] || {})
22
+ end
23
+
14
24
  # iterate through pages then pick those which are
15
25
  # are markdown file then call Git#log on the page
16
26
  # and add authors into its content
17
- def generate(site)
18
- puts "\nGenerating authors"
27
+ def generate(site) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
28
+ Jekyll.logger.info 'Git authors:', 'Generating authors...'
19
29
 
20
- # Find every .md file that is in subdirectory,
21
- # then go into directory where page is located.
22
- # Git finds authors for us if we call Git#log in directory
23
- # where the file is located.
24
30
  site.pages.each do |page|
25
- file = page.path
31
+ page_path = page.path
26
32
  # If file ends with md and if it is subdir.
27
- # Jekyll does not add "./" into pages paths,
28
- # so we can use this approach.
29
- if file =~ /\.md/ and file =~ /\//
30
- Dir.chdir File.dirname(file) do |path|
31
- output = authors File.basename(file)
33
+ # Jekyll does not add "./" into pages paths, so we can use this approach.
34
+ next unless page_path =~ /\.md/ && page_path =~ /\//
32
35
 
33
- page.content += output
36
+ Dir.chdir File.dirname(page_path) do
37
+ begin
38
+ output = authors File.basename(page_path)
39
+ rescue JekyllGitAuthors::Git::ExecutionError => e
40
+ Jekyll.logger.error 'Error:', "Git authors: #{page_path} is not in git, cannot generate authors."
41
+ Jekyll.logger.error 'Git authors failed,', " Command: '#{e.command}', Git: '#{e.stderr}'"
42
+ break
34
43
  end
44
+
45
+ Jekyll.logger.debug 'Git authors:', 'Generating authors for ' + page_path.to_s
46
+
47
+ page.content += output
35
48
  end
36
49
  end
37
50
  end
38
51
 
39
52
  # Gets the authors and then adds required formatting.
40
53
  def authors(file)
41
- author_md = Git.log(file).author_email
54
+ author_md = JekyllGitAuthors::Git.log(file, @options['max_authors']).authors
42
55
  author_md = author_md.sort
43
- author_md = author_md.map { |a, e| Markdown.mailto(a, e) }
56
+ format author_md
57
+ end
44
58
 
45
- output = author_md.join ', '
46
- output = "Authors: #{output}"
47
- Markdown.center output
59
+ def format(authors)
60
+ markdown = JekyllGitAuthors::Markdown.new authors.map(&:to_markdown).join(', ')
61
+ markdown = markdown.prefix(@options['prefix'])
62
+ markdown = markdown.center if @options['center']
63
+ markdown = markdown.thematic_break if @options['thematic_break']
64
+ markdown.to_s
48
65
  end
49
66
  end
50
67
  end
@@ -0,0 +1,13 @@
1
+ require_relative 'markdown'
2
+
3
+ module JekyllGitAuthors
4
+ Author = Struct.new(:name, :email) do
5
+ def <=>(author)
6
+ name <=> author.name
7
+ end
8
+
9
+ def to_markdown
10
+ JekyllGitAuthors::Markdown.new("[#{name}](mailto:{{ '#{email}' | encode_email }})")
11
+ end
12
+ end
13
+ end
@@ -1,55 +1,76 @@
1
- module Git
2
- # Git::Log parses output passed from Git#log and creates a hash with author as a key and email as value
3
- class Log
4
- # We are expecting output from "git log" command
5
- def initialize(log)
6
- @log = log
1
+ require 'open3'
2
+ require_relative 'author'
3
+
4
+ module JekyllGitAuthors
5
+ module Git
6
+ # Git::Log parses output passed from Git#log and creates a hash with author as a key and email as value
7
+ class Log
8
+ # We are expecting output from "git log" command
9
+ # max_authors_count - maximum number of unique authors to return
10
+ def initialize(log, max_authors_count = 5)
11
+ @log = log.force_encoding(Encoding::UTF_8)
12
+ @max_authors_count = max_authors_count
13
+
14
+ raise InvalidEncoding unless @log.valid_encoding?
15
+ end
16
+
17
+ # Create array of unique authors and return maximum specified by @max_authors_count.
18
+ def authors
19
+ @log.each_line
20
+ .map { |author| author.strip.split(';') }
21
+ .map { |name, email| JekyllGitAuthors::Author.new name, email }
22
+ .uniq { |author| author[:name] }
23
+ .take @max_authors_count
24
+ end
25
+
26
+ # To ensure log will be text when we want
27
+ def to_s
28
+ @log
29
+ end
7
30
  end
8
31
 
9
- # Iterate through each line in the log
10
- # filter out whitespace characters, split the line by semicolon
11
- # assign the returned pair (i.e. author and email) to author and email variables
12
- # then create hash with author as key and email as value and return it.
13
- # Return from function if we have 5 authors
14
- def author_email
15
- author_email = Hash.new
16
- @log.each_line do |line|
17
- author, mail = line.strip.split(';')
32
+ class ExecutionError < StandardError
33
+ attr_reader :command, :stdout, :stderr
18
34
 
19
- author_email[author] = mail unless author_email.key?(author)
35
+ def initialize(command, stdout, stderr)
36
+ @command = command
37
+ @stdout = stdout
38
+ @stderr = stderr
20
39
 
21
- return author_email if author_email.size == 5
40
+ super "Git command failed: '#{@command}', Git error message: #{@stderr}"
22
41
  end
23
- author_email
24
42
  end
25
43
 
26
- # To ensure log will be text when we want
27
- def to_s
28
- @log
44
+ # Custom exception to raise when Git::Log receives invalid log.
45
+ class InvalidEncoding < StandardError
46
+ def initialize(msg = 'Git log contains invalid UTF-8 bytes.')
47
+ super
48
+ end
29
49
  end
30
- end
31
50
 
32
- # Take a git command and execute
33
- # Abort if command didn't execute successfully
34
- # then return output of the command.
35
- # Print custom message if required.
36
- def self.execute(command, msg = '')
37
- output = `git #{command}`
51
+ # Take a git command and execute
52
+ # Raise Git::ExecutionError if command didn't execute successfully
53
+ # then return output of the command.
54
+ # Print custom message if required.
55
+ def self.execute(command)
56
+ stdout, stderr, status = Open3.capture3("git #{command}")
38
57
 
39
- abort "Git command failed: '#{command}'" + " #{msg}" unless $?.success?
58
+ raise Git::ExecutionError.new(command, stdout, stderr) unless status.success?
40
59
 
41
- return output
42
- end
60
+ stdout
61
+ end
43
62
 
44
- # Check if file is tracked with git.
45
- # If it is not, exit status 1 will be returned by git.
46
- # so it will be aborted by execute method.
47
- #
48
- # Create instance of Git::Log and pass it output from git log command
49
- # return 5 last authors of a particular file
50
- # %an returns author, semicolon for effortless parsing, %ae return email of author
51
- def self.log(file)
52
- Git.execute("ls-files --error-unmatch #{file}", "File is not added in git: #{file}")
53
- Log.new(execute("log --pretty=format:'%an;%ae' #{file}"))
63
+ # Check if file is tracked with git.
64
+ # If it is not, exit status 1 will be returned by git.
65
+ # so it will be aborted by execute method.
66
+ # max_authors_count - maximum of returned authors
67
+ #
68
+ # Create instance of Git::Log and pass it output from git log command
69
+ # return 5 last authors of a particular file
70
+ # %an returns author, semicolon for effortless parsing, %ae return email of author
71
+ def self.log(file, max_authors_count = 5)
72
+ Git.execute("ls-files --error-unmatch #{file}")
73
+ Log.new(execute("log --pretty=format:'%an;%ae' #{file}"), max_authors_count)
74
+ end
54
75
  end
55
76
  end
@@ -1,9 +1,36 @@
1
- module Markdown
2
- def self.mailto(a, e)
3
- "[#{a}](mailto:{{ '#{e}' | encode_email }})"
4
- end
1
+ module JekyllGitAuthors
2
+ class Markdown
3
+ # @param [String] text - string that will be edited.
4
+ def initialize(text)
5
+ @text = text
6
+ end
7
+
8
+ # Center @text.
9
+ # @return [Markdown]
10
+ def center
11
+ text = %Q|{:center: style="text-align: center"}\n#{@text}\n{:center}|
12
+ self.class.new text
13
+ end
14
+
15
+ # Insert horizontal rule with ID 'authors-rule' above '@text'.
16
+ # @return [Markdown]
17
+ def thematic_break
18
+ text = "\n_ _ _ _\n{: #authors-rule}" + "\n#{@text}"
19
+ self.class.new text
20
+ end
21
+
22
+ # Insert prefix before '@text'.
23
+ # e.g. +markdown.prefix('Authors:')+ generates 'Authors: foo, bar'
24
+ # @return [Markdown]
25
+ def prefix(prefix)
26
+ text = "#{prefix} #{@text}"
27
+ self.class.new text
28
+ end
5
29
 
6
- def self.center(text)
7
- '{:center: style="text-align: center"}' + "\n#{text}\n{:center}"
30
+ # Return @text.
31
+ # @return [String]
32
+ def to_s
33
+ @text
34
+ end
8
35
  end
9
36
  end
@@ -1,3 +1,3 @@
1
1
  module JekyllGitAuthors
2
- VERSION = "0.2.1"
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -0,0 +1,23 @@
1
+ require_relative 'test_helper'
2
+
3
+ class TestAuthor < Minitest::Test
4
+ def test_spaceship_operator
5
+ authors = []
6
+ 3.downto(0) do |num|
7
+ name, email = "you#{num}", "you#{num}@example.com"
8
+ author = JekyllGitAuthors::Author.new name, email
9
+ authors << author
10
+ end
11
+
12
+ assert_equal authors.last, authors.min
13
+ assert_equal authors.first, authors.max
14
+ end
15
+
16
+ def test_to_markdown
17
+ name, email = 'John Doe', 'john@doe.com'
18
+ author = JekyllGitAuthors::Author.new name, email
19
+
20
+ assert_equal "[#{name}](mailto:{{ '#{email}' | encode_email }})", author.to_markdown.to_s
21
+ assert_kind_of JekyllGitAuthors::Markdown, author.to_markdown
22
+ end
23
+ end
@@ -1,7 +1,5 @@
1
- require "fileutils"
2
-
1
+ require 'fileutils'
3
2
  require_relative './test_helper.rb'
4
- require 'jekyll-git-authors.rb'
5
3
 
6
4
  class TestGit < Minitest::Test
7
5
  def setup
@@ -16,14 +14,13 @@ class TestGit < Minitest::Test
16
14
 
17
15
  Dir.chdir @dir
18
16
 
17
+ JekyllGitAuthors::Git.execute 'init'
19
18
 
20
- Git.execute 'init'
21
-
22
- Git.execute 'config user.email "you@example.com"'
23
- Git.execute 'config user.name "Your Name"'
19
+ JekyllGitAuthors::Git.execute 'config user.email "you@example.com"'
20
+ JekyllGitAuthors::Git.execute 'config user.name "Your Name"'
24
21
 
25
- Git.execute 'add .'
26
- Git.execute 'commit -m "Initial commit"'
22
+ JekyllGitAuthors::Git.execute 'add .'
23
+ JekyllGitAuthors::Git.execute 'commit -m "Initial commit"'
27
24
  end
28
25
 
29
26
  def teardown
@@ -32,64 +29,118 @@ class TestGit < Minitest::Test
32
29
  end
33
30
 
34
31
  def test_that_git_executes_basic_commands
35
- assert_match /^git version /, Git.execute('--version')
32
+ assert_match(/^git version /, JekyllGitAuthors::Git.execute('--version'))
36
33
  end
37
34
 
38
- def test_that_git_aborts_on_invalid_command
35
+ def test_that_git_raises_execution_error_on_invalid_command
39
36
  invalid_command = 'patses'
40
- assert_output('', /^Git command failed: '#{invalid_command}' /) do
41
- assert_raises(SystemExit) do
42
- Git.execute invalid_command
43
- end
37
+ err_message = "Git command failed: '#{invalid_command}', "
38
+
39
+ exception = assert_raises(JekyllGitAuthors::Git::ExecutionError) do
40
+ JekyllGitAuthors::Git.execute invalid_command
44
41
  end
42
+ assert_match err_message, exception.message
43
+ end
44
+
45
+ def test_git_log
46
+ method_output = JekyllGitAuthors::Git.log File.join(@subdir, 'README.md')
47
+ assert_equal 'Your Name;you@example.com', method_output.to_s
45
48
  end
46
49
 
47
- def test_that_git_aborts_with_custom_message
48
- invalid_command = 'burger order'
49
- err_message = "We do not serve burgers"
50
+ def test_that_git_log_raises_exception_with_message_when_file_is_not_tracked_in_git
51
+ FileUtils.cp "#{@original_dir}/test/fixtures/README.md", @dir
52
+ file = './README.md'
53
+ err_message = "Git command failed: 'ls-files --error-unmatch ./README.md'"
50
54
 
51
- assert_output('', /^Git command failed: '#{invalid_command}' #{err_message}/) do
52
- assert_raises(SystemExit)do
53
- Git.execute invalid_command, err_message
54
- end
55
+ exception = assert_raises(JekyllGitAuthors::Git::ExecutionError) do
56
+ JekyllGitAuthors::Git.log(file)
55
57
  end
58
+ assert_match err_message, exception.message
56
59
  end
57
60
 
58
- def test_git_log
59
- method_output = Git.log File.join(@subdir, 'README.md')
60
- assert_equal "Your Name;you@example.com", "#{method_output}"
61
+ def test_log_called_when_there_is_no_git_repository
62
+ FileUtils.rm_rf "#{@dir}/.git"
63
+ err_message = "Git command failed: 'ls-files"
64
+
65
+ exception = assert_raises(JekyllGitAuthors::Git::ExecutionError) do
66
+ JekyllGitAuthors::Git.log File.join(@subdir, 'README.md')
67
+ end
68
+ assert_match err_message, exception.message
69
+ end
70
+ end
71
+
72
+ class TestGitExecutionError < Minitest::Test
73
+ def test_execution_error_has_redeable_executed_command_stdout_and_stderr
74
+ command, stdout, stderr = 'add .', 'foo', 'bar'
75
+
76
+ exception = assert_raises(JekyllGitAuthors::Git::ExecutionError) do
77
+ raise JekyllGitAuthors::Git::ExecutionError.new(command, stdout, stderr)
78
+ end
79
+
80
+ assert_equal command, exception.command
81
+ assert_equal stdout, exception.stdout
82
+ assert_equal stderr, exception.stderr
61
83
  end
62
84
 
63
- def test_latest_author_email_is_used
85
+ def test_execution_error_has_default_message
86
+ command = 'ckommnd'
87
+ err_message = "Git command failed: '#{command}', Git error message: "
88
+
89
+ exception = assert_raises(JekyllGitAuthors::Git::ExecutionError) do
90
+ raise JekyllGitAuthors::Git::ExecutionError.new command, nil, nil
91
+ end
92
+
93
+ assert_match err_message, exception.message
94
+ end
95
+ end
96
+
97
+ class TestGitInvalidEncoding < Minitest::Test
98
+ def test_invalid_encoding_has_default_message
99
+ err_message = 'Git log contains invalid UTF-8 bytes.'
100
+
101
+ exception = assert_raises(JekyllGitAuthors::Git::InvalidEncoding) do
102
+ raise JekyllGitAuthors::Git::InvalidEncoding
103
+ end
104
+
105
+ assert_match err_message, exception.message
106
+ end
107
+ end
108
+
109
+ class TestGitLog < Minitest::Test
110
+ def author
111
+ JekyllGitAuthors::Author.new('Your Name', 'you@example.com')
112
+ end
113
+
114
+ def test_latest_email_is_used
64
115
  output = "Your Name;you@example.com\nYour Name;me@example.com"
65
- git_log = Git::Log.new output
66
- assert_equal({"Your Name"=>"you@example.com"}, git_log.author_email)
116
+ git_log = JekyllGitAuthors::Git::Log.new output
117
+ assert_equal [author], git_log.authors
67
118
  end
68
119
 
69
120
  def test_that_it_logs_single_author_once_if_author_has_multiple_commits
70
121
  output = "Your Name;you@example.com\nYour Name;you@example.com"
71
- git_log = Git::Log.new output
72
- assert_equal({"Your Name"=>"you@example.com"}, git_log.author_email)
122
+ git_log = JekyllGitAuthors::Git::Log.new output
123
+ assert_equal [author], git_log.authors
73
124
  end
74
125
 
75
126
  def test_that_it_logs_multiple_authors
76
127
  output = "Your Name;you@example.com\nMy Name;me@example.org"
77
- git_log = Git::Log.new output
78
- assert_equal({"Your Name"=>"you@example.com", "My Name"=>"me@example.org"}, git_log.author_email)
128
+ git_log = JekyllGitAuthors::Git::Log.new output
129
+ assert_equal [author, JekyllGitAuthors::Author.new('My Name', 'me@example.org')], git_log.authors
79
130
  end
80
131
 
81
- def test_method_author_email_stops_at_5_authors
82
- authors = ""
83
- 6.times do |num|
132
+ def test_method_authors_stops_when_max_authors_count_is_specified
133
+ authors = ''
134
+ 9.times do |num|
84
135
  authors << "Your Name#{num};you#{num}@example.com\n"
85
136
  end
86
- git_log = Git::Log.new authors
137
+ git_log = JekyllGitAuthors::Git::Log.new authors, 7
87
138
 
88
- assert_equal 5, git_log.author_email.size
139
+ assert_equal 7, git_log.authors.size
89
140
  end
90
141
 
91
- def test_method_author_email_iterates_through_authors
92
- authors = ""
142
+ def test_method_authors_iterates_through_authors
143
+ authors = ''
93
144
  3.times do
94
145
  authors << "Your Name0;you0@example.com\n"
95
146
  end
@@ -100,29 +151,29 @@ class TestGit < Minitest::Test
100
151
  authors << "Your Name#{num};you#{num}@example.com\n"
101
152
  end
102
153
 
103
- git_log = Git::Log.new authors
154
+ git_log = JekyllGitAuthors::Git::Log.new authors
104
155
 
105
- assert_includes git_log.author_email, 'Your Name4'
106
- assert_equal 5, git_log.author_email.size
156
+ assert_equal JekyllGitAuthors::Author.new('Your Name4', 'you4@example.com'), git_log.authors.last
157
+ assert_equal 5, git_log.authors.size
107
158
  end
108
159
 
109
- def test_that_git_log_aborts_with_custom_message_when_file_is_not_tracked_in_git
110
- FileUtils.cp "#{@original_dir}/test/fixtures/README.md", @dir
111
- file = './README.md'
112
- err_message = "Git command failed: 'ls-files --error-unmatch ./README.md' File is not added in git: ./README.md"
160
+ def test_git_log_parses_valid_utf8_bytes_and_outputs_authors
161
+ valid_bytes = "\xC4\x9B\xC5\xA1\xC4\x8D\xC5\x99;foo@bar.com".force_encoding('ASCII-8BIT')
162
+ git_log = JekyllGitAuthors::Git::Log.new valid_bytes
113
163
 
114
- assert_output('', /^#{err_message}/) do
115
- assert_raises(SystemExit) do
116
- Git.log(file)
117
- end
118
- end
164
+ assert_equal [JekyllGitAuthors::Author.new('ěščř', 'foo@bar.com')], git_log.authors
119
165
  end
120
166
 
121
- def test_log_called_when_there_is_no_git_repository
122
- FileUtils.rm_rf "#{@dir}/.git"
167
+ def test_that_git_log_raises_custom_exception_with_message_if_log_contains_invalid_utf8_bytes
168
+ # The sequence has randomly erased bytes.
169
+ invalid_bytes = "\xE3\xD3\x8B\xE3\x83\xBC\x83\xE3\x83\xE3\x82\xB3\xA3\x82\x99" \
170
+ "\xE3\x83\xB3\xE3\x83\x8F\xE3\x82\x9A\xC3\xBD;foo@bar.com"
171
+ msg = 'Git log contains invalid UTF-8 bytes.'
123
172
 
124
- assert_raises(SystemExit) do
125
- Git.log File.join(@subdir, 'README.md')
173
+ exception = assert_raises(JekyllGitAuthors::Git::InvalidEncoding) do
174
+ JekyllGitAuthors::Git::Log.new invalid_bytes
126
175
  end
176
+
177
+ assert_match msg, exception.message
127
178
  end
128
179
  end
@@ -14,14 +14,13 @@ class TestJekyllGitAuthors < Minitest::Test
14
14
 
15
15
  Dir.chdir @dir
16
16
 
17
+ JekyllGitAuthors::Git.execute 'init'
17
18
 
18
- Git.execute 'init'
19
+ JekyllGitAuthors::Git.execute 'config user.email "you@example.com"'
20
+ JekyllGitAuthors::Git.execute 'config user.name "Your Name"'
19
21
 
20
- Git.execute 'config user.email "you@example.com"'
21
- Git.execute 'config user.name "Your Name"'
22
-
23
- Git.execute 'add .'
24
- Git.execute 'commit -m "Initial commit"'
22
+ JekyllGitAuthors::Git.execute 'add .'
23
+ JekyllGitAuthors::Git.execute 'commit -m "Initial commit"'
25
24
  end
26
25
 
27
26
  def teardown
@@ -30,9 +29,23 @@ class TestJekyllGitAuthors < Minitest::Test
30
29
  end
31
30
 
32
31
  def test_that_authors_method_formats_correctly
33
- expected ="{:center: style=\"text-align: center\"}\nAuthors: [Your Name](mailto:{{ 'you@example.com' | encode_email }})\n{:center}"
32
+ expected = "\n_ _ _ _\n{: #authors-rule}\n{:center: style=\"text-align: center\"}" \
33
+ "\nAuthors: [Your Name](mailto:{{ 'you@example.com' | encode_email }})\n{:center}"
34
+
34
35
  authors_generator = Jekyll::AuthorsGenerator.new
35
36
  actual = authors_generator.authors 'subdir/README.md'
37
+
38
+ assert_equal expected, actual
39
+ end
40
+
41
+ def test_format
42
+ authors = [JekyllGitAuthors::Author.new('Your Name', 'you@example.com')]
43
+ expected = "\n_ _ _ _\n{: #authors-rule}\n{:center: style=\"text-align: center\"}\n" \
44
+ "Authors: [Your Name](mailto:{{ 'you@example.com' | encode_email }})\n{:center}"
45
+
46
+ authors_generator = Jekyll::AuthorsGenerator.new
47
+ actual = authors_generator.format authors
48
+
36
49
  assert_equal expected, actual
37
50
  end
38
51
  end
@@ -2,13 +2,25 @@ require_relative './test_helper'
2
2
  require 'jekyll-git-authors/markdown'
3
3
 
4
4
  class TestMarkdown < Minitest::Test
5
- def test_markdown_mailto
6
- author, email = "Your Name", "you@example.com"
7
- assert_match "[#{author}](mailto:{{ '#{email}' | encode_email }})", Markdown.mailto(author, email)
5
+ def setup
6
+ @author, @email = 'you', 'you@example.com'
7
+ @author_email = [JekyllGitAuthors::Author.new(@author, @email)]
8
+ @text = 'foobar'
9
+ end
10
+
11
+ def markdown(text)
12
+ JekyllGitAuthors::Markdown.new(text)
8
13
  end
9
14
 
10
15
  def test_markdown_center
11
- text = 'foo'
12
- assert_match %Q|{:center: style="text-align: center"}\n#{text}\n{:center}|, Markdown.center(text)
16
+ assert_match %Q|{:center: style="text-align: center"}\n#{@text}\n{:center}|, markdown(@text).center.to_s
17
+ end
18
+
19
+ def test_markdown_thematic_break
20
+ assert_match "\n_ _ _ _\n{: #authors-rule}\n#{@text}", markdown(@text).thematic_break.to_s
21
+ end
22
+
23
+ def test_prefix
24
+ assert_match "Authors: #{@text}", markdown(@text).prefix('Authors:').to_s
13
25
  end
14
26
  end
@@ -1,4 +1,4 @@
1
- $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
2
 
3
3
  if ENV['CODE_COV']
4
4
  require 'simplecov'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-git-authors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaroslav Prokop
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-29 00:00:00.000000000 Z
11
+ date: 2019-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -39,7 +39,21 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: simplecov
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.16'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cucumber
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -53,35 +67,35 @@ dependencies:
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: bundler
70
+ name: minitest
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - "~>"
73
+ - - ">="
60
74
  - !ruby/object:Gem::Version
61
- version: '1.16'
75
+ version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '1.16'
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '10.0'
89
+ version: '12'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '10.0'
96
+ version: '12'
83
97
  - !ruby/object:Gem::Dependency
84
- name: minitest
98
+ name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - ">="
@@ -95,7 +109,7 @@ dependencies:
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
- name: cucumber
112
+ name: rubocop
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - ">="
@@ -109,7 +123,7 @@ dependencies:
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
- name: rspec
126
+ name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
@@ -122,8 +136,8 @@ dependencies:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
- description: Jekyll plugin that adds git authors and their obfuscated email address
126
- into page using markdown and liquid.
139
+ description: Jekyll plugin that adds git authors and their obfuscated email addressinto
140
+ page using markdown and liquid.
127
141
  email:
128
142
  - jar.prokop@volny.cz
129
143
  executables: []
@@ -132,20 +146,25 @@ extra_rdoc_files: []
132
146
  files:
133
147
  - ".gitignore"
134
148
  - ".gitlab-ci.yml"
149
+ - ".rubocop.yml"
135
150
  - Gemfile
136
151
  - LICENSE.txt
137
152
  - README.md
138
153
  - Rakefile
139
154
  - features/fixtures/page.md
155
+ - features/options.feature
140
156
  - features/render_output.feature
157
+ - features/step_definitions/options.rb
141
158
  - features/step_definitions/render_output.rb
142
159
  - features/support/env.rb
143
160
  - features/support/helper.rb
144
161
  - jekyll-git-authors.gemspec
145
162
  - lib/jekyll-git-authors.rb
163
+ - lib/jekyll-git-authors/author.rb
146
164
  - lib/jekyll-git-authors/git.rb
147
165
  - lib/jekyll-git-authors/markdown.rb
148
166
  - lib/jekyll-git-authors/version.rb
167
+ - test/author_test.rb
149
168
  - test/fixtures/README.md
150
169
  - test/git_test.rb
151
170
  - test/jekyll-git-authors_test.rb
@@ -178,10 +197,13 @@ specification_version: 4
178
197
  summary: Jekyll plugin that adds git authors into your page.
179
198
  test_files:
180
199
  - features/fixtures/page.md
200
+ - features/options.feature
181
201
  - features/render_output.feature
202
+ - features/step_definitions/options.rb
182
203
  - features/step_definitions/render_output.rb
183
204
  - features/support/env.rb
184
205
  - features/support/helper.rb
206
+ - test/author_test.rb
185
207
  - test/fixtures/README.md
186
208
  - test/git_test.rb
187
209
  - test/jekyll-git-authors_test.rb