guard-jekyll-plus 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/.rubocop.yml +10 -0
- data/.rubocop_todo.yml +32 -0
- data/.ruby-gemset +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +6 -2
- data/Gemfile +12 -2
- data/Guardfile +30 -0
- data/README.md +5 -5
- data/Rakefile +9 -1
- data/guard-jekyll-plus.gemspec +20 -15
- data/lib/guard/jekyll_plus.rb +54 -0
- data/lib/guard/jekyll_plus/builder.rb +46 -0
- data/lib/guard/jekyll_plus/builder/action.rb +126 -0
- data/lib/guard/jekyll_plus/builder/adder.rb +23 -0
- data/lib/guard/jekyll_plus/builder/modifier.rb +23 -0
- data/lib/guard/jekyll_plus/builder/rebuilder.rb +37 -0
- data/lib/guard/jekyll_plus/builder/remover.rb +24 -0
- data/lib/guard/jekyll_plus/config.rb +131 -0
- data/lib/guard/jekyll_plus/server.rb +111 -0
- data/lib/guard/jekyll_plus/templates/Guardfile +4 -0
- data/lib/guard/{jekyll-plus → jekyll_plus}/version.rb +1 -1
- data/spec/lib/guard/jekyll-plus/builder/adder_spec.rb +94 -0
- data/spec/lib/guard/jekyll-plus/builder/modifier_spec.rb +113 -0
- data/spec/lib/guard/jekyll-plus/builder/rebuilder_spec.rb +76 -0
- data/spec/lib/guard/jekyll-plus/builder/remover_spec.rb +97 -0
- data/spec/lib/guard/jekyll-plus/builder_spec.rb +57 -0
- data/spec/lib/guard/jekyll-plus/config_spec.rb +138 -0
- data/spec/lib/guard/jekyll-plus/server_spec.rb +79 -0
- data/spec/lib/guard/jekyll-plus_spec.rb +114 -0
- data/spec/spec_helper.rb +44 -0
- data/test/Guardfile +3 -4
- metadata +70 -14
- data/lib/guard/jekyll-plus.rb +0 -300
- data/lib/guard/jekyll-plus/templates/Guardfile +0 -5
- data/test/Gemfile +0 -3
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'guard/jekyll_plus/builder/modifier'
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
RSpec.describe JekyllPlus::Builder::Modifier do
|
5
|
+
let(:site) { instance_double(Jekyll::Site) }
|
6
|
+
let(:config) { instance_double(JekyllPlus::Config) }
|
7
|
+
subject { described_class.new(config, site) }
|
8
|
+
|
9
|
+
describe '#update' do
|
10
|
+
let(:extensions) { /\.haml$/i }
|
11
|
+
|
12
|
+
before do
|
13
|
+
# for build
|
14
|
+
allow(config).to receive(:info)
|
15
|
+
allow(config).to receive(:source)
|
16
|
+
allow(config).to receive(:destination)
|
17
|
+
|
18
|
+
allow(config).to receive(:extensions).and_return(extensions)
|
19
|
+
allow(FileUtils).to receive(:mkdir_p)
|
20
|
+
allow(FileUtils).to receive(:cp)
|
21
|
+
allow($stdout).to receive(:puts)
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when source files change' do
|
25
|
+
it 'builds' do
|
26
|
+
expect(site).to receive(:process)
|
27
|
+
subject.update(%w(foo.haml))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when assets change' do
|
32
|
+
before do
|
33
|
+
allow(config).to receive(:destination).and_return('bar/')
|
34
|
+
allow(config).to receive(:excluded?).with('foo.jpg').and_return(false)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'copies files' do
|
38
|
+
expect(FileUtils).to receive(:cp).with('foo.jpg', 'bar/foo.jpg')
|
39
|
+
subject.update(%w(foo.jpg))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when excluded file changes' do
|
44
|
+
before do
|
45
|
+
allow(config).to receive(:destination).and_return('bar/')
|
46
|
+
allow(config).to receive(:excluded?).with('foo.jpg').and_return(true)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does not copy anything' do
|
50
|
+
expect(FileUtils).to_not receive(:cp)
|
51
|
+
subject.update(%w(foo.jpg))
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'shows which files were excluded' do
|
55
|
+
expect($stdout).to receive(:puts)
|
56
|
+
.with(/Ignoring excluded file: foo\.jpg/)
|
57
|
+
subject.update(%w(foo.jpg))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# NOTE: Jekyll just shows a message and passes the plugin,
|
62
|
+
# so it can fail with almost any possible exception.
|
63
|
+
#
|
64
|
+
# We catch StandardError to at least be somewhat reasonable
|
65
|
+
context 'when an Jekyll conversion error happens' do
|
66
|
+
before do
|
67
|
+
allow(site).to receive(:process)
|
68
|
+
.and_raise(NoMethodError, 'error evaluating Haml file')
|
69
|
+
|
70
|
+
allow(config).to receive(:error)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'shows an error' do
|
74
|
+
expect(config).to receive(:error).with('build has failed')
|
75
|
+
expect(config).to receive(:error).with(/error evaluating Haml file/)
|
76
|
+
|
77
|
+
catch(:task_has_failed) do
|
78
|
+
subject.update(%w(foo.haml))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'throws task_has_failed symbol' do
|
83
|
+
expect do
|
84
|
+
subject.update(%w(foo.haml))
|
85
|
+
end.to throw_symbol(:task_has_failed)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when an error happens' do
|
90
|
+
before do
|
91
|
+
allow(config).to receive(:destination).and_return('bar/')
|
92
|
+
allow(FileUtils).to receive(:cp).and_raise(Errno::ENOENT, 'foo')
|
93
|
+
allow(config).to receive(:error)
|
94
|
+
allow(config).to receive(:excluded?).with('foo').and_return(false)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'shows an error' do
|
98
|
+
expect(config).to receive(:error).with('update has failed')
|
99
|
+
expect(config).to receive(:error).with(/No such file.* - foo/)
|
100
|
+
catch(:task_has_failed) do
|
101
|
+
subject.update(%w(foo))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'throws task_has_failed symbol' do
|
106
|
+
expect do
|
107
|
+
subject.update(%w(foo))
|
108
|
+
end.to throw_symbol(:task_has_failed)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'guard/jekyll_plus/builder/rebuilder'
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
RSpec.describe JekyllPlus::Builder::Rebuilder do
|
5
|
+
let(:site) { instance_double(Jekyll::Site) }
|
6
|
+
let(:config) { instance_double(JekyllPlus::Config) }
|
7
|
+
subject { described_class.new(config, site) }
|
8
|
+
|
9
|
+
describe '#update' do
|
10
|
+
before do
|
11
|
+
allow(site).to receive(:process)
|
12
|
+
allow($stdout).to receive(:puts)
|
13
|
+
allow(config).to receive(:info)
|
14
|
+
allow(config).to receive(:source)
|
15
|
+
allow(config).to receive(:destination)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'processes all the files' do
|
19
|
+
expect(site).to receive(:process)
|
20
|
+
subject.update
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'shows header' do
|
24
|
+
expect(config).to receive(:info).with(/building\.\.\./)
|
25
|
+
subject.update
|
26
|
+
end
|
27
|
+
|
28
|
+
# NOTE: Jekyll just shows a message and passes the plugin,
|
29
|
+
# so it can fail with almost any possible exception.
|
30
|
+
#
|
31
|
+
# We catch StandardError to at least be somewhat reasonable
|
32
|
+
context 'when an Jekyll conversion error happens' do
|
33
|
+
before do
|
34
|
+
allow(config).to receive(:error)
|
35
|
+
allow(site).to receive(:process)
|
36
|
+
.and_raise(NoMethodError, 'something in Haml template failed')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'shows an error' do
|
40
|
+
expect(config).to receive(:error).with('build has failed')
|
41
|
+
expect(config).to receive(:error).with(/something in Haml template/)
|
42
|
+
catch(:task_has_failed) do
|
43
|
+
subject.update
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'throws task_has_failed symbol' do
|
48
|
+
expect do
|
49
|
+
subject.update
|
50
|
+
end.to throw_symbol(:task_has_failed)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when a system error happens' do
|
55
|
+
before do
|
56
|
+
allow(config).to receive(:error)
|
57
|
+
allow(site).to receive(:process).and_raise(RuntimeError, 'big error')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'shows an error' do
|
61
|
+
expect(config).to receive(:error).with('build has failed')
|
62
|
+
expect(config).to receive(:error).with(/big error/)
|
63
|
+
catch(:task_has_failed) do
|
64
|
+
subject.update
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'throws task_has_failed symbol' do
|
69
|
+
expect do
|
70
|
+
subject.update
|
71
|
+
end.to throw_symbol(:task_has_failed)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'guard/jekyll_plus/builder/remover'
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
RSpec.describe JekyllPlus::Builder::Remover do
|
5
|
+
let(:site) { instance_double(Jekyll::Site) }
|
6
|
+
let(:config) { instance_double(JekyllPlus::Config) }
|
7
|
+
subject { described_class.new(config, site) }
|
8
|
+
|
9
|
+
describe '#update' do
|
10
|
+
let(:extensions) { /\.haml$/i }
|
11
|
+
|
12
|
+
before do
|
13
|
+
allow(config).to receive(:extensions).and_return(extensions)
|
14
|
+
|
15
|
+
# for build
|
16
|
+
allow(config).to receive(:info)
|
17
|
+
allow(config).to receive(:source)
|
18
|
+
allow(config).to receive(:destination)
|
19
|
+
|
20
|
+
allow($stdout).to receive(:puts)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when asset files are deleted' do
|
24
|
+
before do
|
25
|
+
allow(config).to receive(:destination).and_return('bar/')
|
26
|
+
|
27
|
+
# non existing src file
|
28
|
+
allow(File).to receive(:exist?).with('foo.jpg').and_return(false)
|
29
|
+
|
30
|
+
# Make one file exist so removing dst files can happen.
|
31
|
+
# I'm not sure why this is necessary
|
32
|
+
allow(File).to receive(:exist?).with('logo.png').and_return(true)
|
33
|
+
|
34
|
+
# existing destination file
|
35
|
+
allow(File).to receive(:exist?).with('bar/foo.jpg').and_return(true)
|
36
|
+
|
37
|
+
# the removing of the file
|
38
|
+
allow(FileUtils).to receive(:rm).with('bar/foo.jpg')
|
39
|
+
allow(FileUtils).to receive(:rm).with('bar/logo.png')
|
40
|
+
|
41
|
+
# checking for empty dirs to clear
|
42
|
+
allow(Dir).to receive(:[]).with('bar/*').and_return(%w(logo.png))
|
43
|
+
allow(File).to receive(:exist?).with('bar/logo.png').and_return(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'removes delete files from destination' do
|
47
|
+
expect(FileUtils).to receive(:rm).with('bar/foo.jpg')
|
48
|
+
subject.update(%w(foo.jpg logo.png))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when sources files are removed' do
|
53
|
+
it 'builds' do
|
54
|
+
expect(site).to receive(:process)
|
55
|
+
subject.update(%w(foo.haml))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when an error happens' do
|
60
|
+
before do
|
61
|
+
allow(config).to receive(:destination).and_return('bar/')
|
62
|
+
allow(config).to receive(:error)
|
63
|
+
allow(File).to receive(:exist?).with('foo').and_return(false)
|
64
|
+
|
65
|
+
# just so the removing is triggered (don't know why)
|
66
|
+
allow(File).to receive(:exist?).with('baz').and_return(true)
|
67
|
+
|
68
|
+
# file to be deleted
|
69
|
+
allow(File).to receive(:exist?).with('bar/foo').and_return(true)
|
70
|
+
|
71
|
+
# file we don't care about
|
72
|
+
allow(File).to receive(:exist?).with('bar/baz').and_return(false)
|
73
|
+
|
74
|
+
allow(Dir).to receive(:[]).with('bar/*').and_return(%w(logo.png))
|
75
|
+
|
76
|
+
# simulate failure
|
77
|
+
allow(FileUtils).to receive(:rm).with('bar/foo')
|
78
|
+
.and_raise(Errno::ENOENT, 'foo')
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'shows an error' do
|
82
|
+
expect(config).to receive(:error).with('remove has failed')
|
83
|
+
expect(config).to receive(:error).with(/No such file.* - foo/)
|
84
|
+
catch(:task_has_failed) do
|
85
|
+
subject.update(%w(foo baz))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'throws task_has_failed symbol' do
|
90
|
+
expect do
|
91
|
+
subject.update(%w(foo baz))
|
92
|
+
end.to throw_symbol(:task_has_failed)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'guard/compat/test/helper'
|
2
|
+
|
3
|
+
require 'guard/jekyll_plus/builder'
|
4
|
+
|
5
|
+
module Guard
|
6
|
+
RSpec.describe JekyllPlus::Builder do
|
7
|
+
let(:config) { instance_double(JekyllPlus::Config) }
|
8
|
+
let(:site) { instance_double(Jekyll::Site) }
|
9
|
+
let(:rebuilder) { instance_double(JekyllPlus::Builder::Rebuilder) }
|
10
|
+
let(:modifier) { instance_double(JekyllPlus::Builder::Modifier) }
|
11
|
+
let(:adder) { instance_double(JekyllPlus::Builder::Adder) }
|
12
|
+
let(:remover) { instance_double(JekyllPlus::Builder::Remover) }
|
13
|
+
|
14
|
+
subject { described_class.new(config) }
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(Jekyll::Site).to receive(:new).and_return(site)
|
18
|
+
|
19
|
+
allow(JekyllPlus::Config).to receive(:new).and_return(config)
|
20
|
+
allow(config).to receive(:jekyll_config)
|
21
|
+
|
22
|
+
allow(JekyllPlus::Builder::Adder).to receive(:new).and_return(adder)
|
23
|
+
allow(JekyllPlus::Builder::Remover).to receive(:new).and_return(remover)
|
24
|
+
allow(JekyllPlus::Builder::Modifier).to receive(:new).and_return(modifier)
|
25
|
+
allow(JekyllPlus::Builder::Rebuilder).to receive(:new)
|
26
|
+
.and_return(rebuilder)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#build' do
|
30
|
+
it 'rebuilds the site' do
|
31
|
+
expect(rebuilder).to receive(:update)
|
32
|
+
subject.build
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#added' do
|
37
|
+
it 'builds if needed' do
|
38
|
+
expect(adder).to receive(:update)
|
39
|
+
subject.added(%w(foo))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#modified' do
|
44
|
+
it 'builds if needed' do
|
45
|
+
expect(modifier).to receive(:update)
|
46
|
+
subject.modified(%w(foo))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#removed' do
|
51
|
+
it 'builds if needed' do
|
52
|
+
expect(remover).to receive(:update)
|
53
|
+
subject.removed(%w(foo))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'guard/compat/test/helper'
|
2
|
+
|
3
|
+
require 'guard/jekyll_plus/config'
|
4
|
+
|
5
|
+
RSpec.describe Guard::JekyllPlus::Config do
|
6
|
+
let(:options) { {} }
|
7
|
+
subject { described_class.new(options) }
|
8
|
+
|
9
|
+
let(:valid_jekyll_options) do
|
10
|
+
{
|
11
|
+
'source' => 'foo',
|
12
|
+
'destination' => 'bar'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:jekyll_config) { valid_jekyll_options }
|
17
|
+
|
18
|
+
before do
|
19
|
+
allow(Jekyll).to receive(:configuration).and_return(jekyll_config)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#source' do
|
23
|
+
context 'with a relative path' do
|
24
|
+
let(:jekyll_config) { valid_jekyll_options.merge('source' => 'foo') }
|
25
|
+
|
26
|
+
it 'returns source from Jekyll config' do
|
27
|
+
expect(subject.source).to eq('foo')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#serve?' do
|
33
|
+
context 'when option is not configured' do
|
34
|
+
let(:options) { {} }
|
35
|
+
it { is_expected.to_not be_serve }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when configured as false' do
|
39
|
+
let(:options) { { serve: false } }
|
40
|
+
it { is_expected.to_not be_serve }
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when configuerd as true' do
|
44
|
+
let(:options) { { serve: true } }
|
45
|
+
it { is_expected.to be_serve }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
%w(host baseurl port).each do |option|
|
50
|
+
describe "#{option}" do
|
51
|
+
let(:value) { double('value') }
|
52
|
+
let(:jekyll_config) { valid_jekyll_options.merge(option.to_s => value) }
|
53
|
+
|
54
|
+
it 'returns value from Jekyll config' do
|
55
|
+
expect(subject.send(option)).to be(value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#jekyll_serve_options' do
|
61
|
+
it 'returns all jekyll options'do
|
62
|
+
expect(subject.jekyll_serve_options).to be(jekyll_config)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#server_root' do
|
67
|
+
let(:path) { File.join(Dir.pwd, 'foo') }
|
68
|
+
let(:jekyll_config) { valid_jekyll_options.merge('destination' => path) }
|
69
|
+
|
70
|
+
it 'returns destination dir'do
|
71
|
+
expect(subject.server_root).to eq('foo')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#rack_config' do
|
76
|
+
context 'when option is not configured' do
|
77
|
+
let(:options) { {} }
|
78
|
+
it 'returns nil' do
|
79
|
+
expect(subject.rack_config).to be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when configured' do
|
84
|
+
let(:rack_options) { double('rack options') }
|
85
|
+
let(:options) { { rack_config: rack_options } }
|
86
|
+
|
87
|
+
it 'returns value from options' do
|
88
|
+
expect(subject.rack_config).to be(rack_options)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#extensions' do
|
94
|
+
let(:options) { { extensions: %w(foo) } }
|
95
|
+
let(:exts) do
|
96
|
+
'foo|md|mkd|mkdn|markdown|textile|html|haml|slim|xml|yml|sass|scss'
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'returns configured extensions' do
|
100
|
+
expect(subject.extensions).to eq(/\.(?:#{exts})$/i)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'matches .slim files' do
|
104
|
+
expect(subject.extensions).to match('foo.slim')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# We need this basically to turn off logging
|
109
|
+
describe '#rack_environment' do
|
110
|
+
context 'when silent is true' do
|
111
|
+
let(:options) { { silent: true } }
|
112
|
+
it 'uses nil to prevent loading Rack default middleware' do
|
113
|
+
expect(subject.rack_environment).to eq(nil)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'when silent is false' do
|
118
|
+
let(:options) { { silent: false } }
|
119
|
+
it 'uses development for full Rack default middleware' do
|
120
|
+
expect(subject.rack_environment).to eq('development')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#excluded?' do
|
126
|
+
context 'with excludes in Jekyll' do
|
127
|
+
let(:jekyll_config) do
|
128
|
+
valid_jekyll_options.merge('exclude' => ['f*', 'b*z'])
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'matches files excluded in Jekyll' do
|
132
|
+
expect(subject.excluded?('foo')).to be_truthy
|
133
|
+
expect(subject.excluded?('bar')).to be_falsey
|
134
|
+
expect(subject.excluded?('baz')).to be_truthy
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|