nanoc 4.8.10 → 4.8.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/NEWS.md +7 -0
- data/lib/nanoc.rb +11 -6
- data/lib/nanoc/base.rb +1 -0
- data/lib/nanoc/base/changes_stream.rb +53 -0
- data/lib/nanoc/base/contracts_support.rb +0 -2
- data/lib/nanoc/base/feature.rb +3 -0
- data/lib/nanoc/base/memoization.rb +0 -2
- data/lib/nanoc/base/repos/aggregate_data_source.rb +8 -0
- data/lib/nanoc/base/repos/data_source.rb +12 -0
- data/lib/nanoc/base/repos/in_mem_data_source.rb +10 -1
- data/lib/nanoc/base/repos/prefixed_data_source.rb +8 -0
- data/lib/nanoc/base/repos/site_loader.rb +11 -7
- data/lib/nanoc/base/services/compiler.rb +2 -3
- data/lib/nanoc/base/services/compiler/stages/postprocess.rb +2 -3
- data/lib/nanoc/base/services/compiler/stages/preprocess.rb +1 -1
- data/lib/nanoc/base/services/pruner.rb +0 -2
- data/lib/nanoc/base/services/temp_filename_factory.rb +0 -2
- data/lib/nanoc/checking/checks/external_links.rb +0 -5
- data/lib/nanoc/checking/checks/internal_links.rb +0 -2
- data/lib/nanoc/checking/checks/stale.rb +0 -2
- data/lib/nanoc/cli.rb +7 -1
- data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +0 -3
- data/lib/nanoc/cli/commands/live.rb +30 -0
- data/lib/nanoc/cli/commands/view.rb +4 -5
- data/lib/nanoc/cli/error_handler.rb +52 -36
- data/lib/nanoc/cli/logger.rb +0 -2
- data/lib/nanoc/cli/stack_trace_writer.rb +50 -0
- data/lib/nanoc/data_sources/filesystem.rb +25 -0
- data/lib/nanoc/extra.rb +1 -0
- data/lib/nanoc/extra/jruby_nokogiri_warner.rb +0 -2
- data/lib/nanoc/extra/link_collector.rb +0 -2
- data/lib/nanoc/extra/live_recompiler.rb +131 -0
- data/lib/nanoc/extra/parallel_collection.rb +0 -2
- data/lib/nanoc/extra/piper.rb +0 -2
- data/lib/nanoc/filters/relativize_paths.rb +8 -7
- data/lib/nanoc/helpers/link_to.rb +0 -2
- data/lib/nanoc/rule_dsl/action_provider.rb +2 -2
- data/lib/nanoc/version.rb +1 -1
- data/nanoc.gemspec +15 -4
- data/nanoc.manifest +545 -0
- data/spec/manifest_spec.rb +22 -0
- data/spec/nanoc/base/changes_stream_spec.rb +45 -0
- data/spec/nanoc/base/checksummer_spec.rb +0 -2
- data/spec/nanoc/base/directed_graph_spec.rb +66 -0
- data/spec/nanoc/base/entities/code_snippet_spec.rb +9 -0
- data/spec/nanoc/base/entities/context_spec.rb +26 -0
- data/spec/nanoc/base/entities/identifiable_collection_spec.rb +53 -0
- data/spec/nanoc/base/repos/aggregate_data_source_spec.rb +87 -0
- data/spec/nanoc/base/repos/data_source_spec.rb +95 -0
- data/spec/nanoc/base/repos/in_mem_data_source_spec.rb +39 -0
- data/spec/nanoc/base/repos/prefixed_data_source_spec.rb +39 -0
- data/spec/nanoc/cli/error_handler_spec.rb +43 -0
- data/spec/nanoc/cli/stack_trace_writer_spec.rb +156 -0
- data/spec/nanoc/data_sources/filesystem_spec.rb +46 -0
- data/spec/nanoc/extra/live_recompiler_spec.rb +129 -0
- data/spec/nanoc/helpers/blogging_spec.rb +1 -1
- data/spec/spec_helper.rb +60 -0
- data/test/base/test_compiler.rb +11 -11
- data/test/cli/test_cli.rb +0 -1
- data/test/cli/test_error_handler.rb +4 -5
- data/test/filters/test_relativize_paths.rb +30 -0
- data/test/filters/test_sass.rb +3 -3
- data/test/rule_dsl/test_compiler_dsl.rb +2 -2
- metadata +39 -43
- data/.github/CONTRIBUTING.md +0 -17
- data/.github/ISSUE_TEMPLATE.md +0 -23
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -18
- data/.gitignore +0 -10
- data/.travis.yml +0 -27
- data/Gemfile +0 -73
- data/Guardfile +0 -5
- data/scripts/release +0 -95
- data/test/base/test_code_snippet.rb +0 -17
- data/test/base/test_context.rb +0 -35
- data/test/base/test_data_source.rb +0 -60
- data/test/base/test_directed_graph.rb +0 -56
- data/test/base/test_item_array.rb +0 -37
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'manifest', chdir: false do
|
4
|
+
let(:manifest_lines) do
|
5
|
+
File.readlines('nanoc.manifest').map(&:chomp).reject(&:empty?)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:gemspec_lines) do
|
9
|
+
gemspec = eval(File.read('nanoc.gemspec'), binding, 'nanoc.gemspec')
|
10
|
+
gemspec.files
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'contains all files in gemspec' do
|
14
|
+
missing_from_manifest = gemspec_lines - manifest_lines
|
15
|
+
expect(missing_from_manifest).to be_empty
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'contains no files not in gemspec' do
|
19
|
+
extra_in_manifest = manifest_lines - gemspec_lines
|
20
|
+
expect(extra_in_manifest).to be_empty
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::ChangesStream do
|
4
|
+
let(:simple_stream) do
|
5
|
+
described_class.new do |cl|
|
6
|
+
cl.unknown
|
7
|
+
sleep
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns a stream of events generated by the listener' do
|
12
|
+
buffered_stream = DDBuffer.new(1).call(simple_stream)
|
13
|
+
expect(buffered_stream.take(1).to_a).to eq([:unknown])
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#map' do
|
17
|
+
it 'returns a new maped enum' do
|
18
|
+
stream = simple_stream.map { |e| e.to_s.upcase }
|
19
|
+
buffered_stream = DDBuffer.new(1).call(stream)
|
20
|
+
expect(buffered_stream.take(1).to_a).to eq(['UNKNOWN'])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#to_enum' do
|
25
|
+
it 'returns an enumerator corresponding to itself' do
|
26
|
+
buffered_stream = DDBuffer.new(1).call(simple_stream.to_enum)
|
27
|
+
expect(buffered_stream.take(1).to_a).to eq([:unknown])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#stop' do
|
32
|
+
let(:simple_stream) do
|
33
|
+
described_class.new do |cl|
|
34
|
+
cl.to_stop { $changes_stream_stopped = true }
|
35
|
+
sleep
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
example do
|
40
|
+
DDBuffer.new(1).call(simple_stream)
|
41
|
+
sleep 0.1
|
42
|
+
expect { simple_stream.stop }.to change { $changes_stream_stopped }.from(nil).to(true)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -51,6 +51,37 @@ describe Nanoc::Int::DirectedGraph do
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
it 'has correct examples' do
|
55
|
+
expect('Nanoc::Int::DirectedGraph')
|
56
|
+
.to have_correct_yard_examples
|
57
|
+
.in_file('lib/nanoc/base/entities/directed_graph.rb')
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#vertices' do
|
61
|
+
subject { graph.vertices }
|
62
|
+
|
63
|
+
it { is_expected.to include('1') }
|
64
|
+
it { is_expected.not_to include('4') }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#add_edge' do
|
68
|
+
subject { graph.add_edge('1', '4') }
|
69
|
+
|
70
|
+
it 'adds vertex' do
|
71
|
+
expect { subject }
|
72
|
+
.to change { graph.vertices.include?('4') }
|
73
|
+
.from(false)
|
74
|
+
.to(true)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'changes direct predecessors' do
|
78
|
+
expect { subject }
|
79
|
+
.to change { graph.direct_predecessors_of('4') }
|
80
|
+
.from([])
|
81
|
+
.to(['1'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
54
85
|
describe '#props_for' do
|
55
86
|
subject { graph.props_for('1', '2') }
|
56
87
|
|
@@ -148,6 +179,41 @@ describe Nanoc::Int::DirectedGraph do
|
|
148
179
|
end
|
149
180
|
end
|
150
181
|
|
182
|
+
describe '#delete_edges_to' do
|
183
|
+
before do
|
184
|
+
graph.add_edge('1', '2')
|
185
|
+
graph.add_edge('2', '1')
|
186
|
+
graph.add_edge('2', '3')
|
187
|
+
graph.add_edge('3', '2')
|
188
|
+
graph.add_edge('1', '3')
|
189
|
+
graph.add_edge('3', '1')
|
190
|
+
end
|
191
|
+
|
192
|
+
subject { graph.delete_edges_to('1') }
|
193
|
+
|
194
|
+
it 'deletes edges to 1' do
|
195
|
+
expect { subject }
|
196
|
+
.to change { graph.direct_predecessors_of('1') }
|
197
|
+
.from(%w[2 3])
|
198
|
+
.to([])
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'keeps edges to 2' do
|
202
|
+
expect { subject }
|
203
|
+
.not_to change { graph.direct_predecessors_of('2') }
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'keeps edges to 3' do
|
207
|
+
expect { subject }
|
208
|
+
.not_to change { graph.direct_predecessors_of('3') }
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'keeps edges to 4' do
|
212
|
+
expect { subject }
|
213
|
+
.not_to change { graph.direct_predecessors_of('4') }
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
151
217
|
describe '#inspect' do
|
152
218
|
subject { graph.inspect }
|
153
219
|
|
@@ -47,5 +47,14 @@ describe Nanoc::Int::CodeSnippet do
|
|
47
47
|
.to([true, false])
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
it 'defines at top level' do
|
52
|
+
@foo = 'meow'
|
53
|
+
|
54
|
+
code_snippet = Nanoc::Int::CodeSnippet.new("@foo = 'woof'", 'dog.rb')
|
55
|
+
code_snippet.load
|
56
|
+
|
57
|
+
expect(@foo).to eq('meow')
|
58
|
+
end
|
50
59
|
end
|
51
60
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::Int::Context do
|
4
|
+
let(:context) do
|
5
|
+
Nanoc::Int::Context.new(foo: 'bar', baz: 'quux')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'provides instance variables' do
|
9
|
+
expect(eval('@foo', context.get_binding)).to eq('bar')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'provides instance methods' do
|
13
|
+
expect(eval('foo', context.get_binding)).to eq('bar')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'supports #include' do
|
17
|
+
eval('include Nanoc::Helpers::HTMLEscape', context.get_binding)
|
18
|
+
expect(eval('h("<>")', context.get_binding)).to eq('<>')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has correct examples' do
|
22
|
+
expect('Nanoc::Int::Context#initialize')
|
23
|
+
.to have_correct_yard_examples
|
24
|
+
.in_file('lib/nanoc/base/entities/context.rb')
|
25
|
+
end
|
26
|
+
end
|
@@ -142,6 +142,59 @@ describe Nanoc::Int::IdentifiableCollection do
|
|
142
142
|
subject { identifiable_collection.reference }
|
143
143
|
it { is_expected.to eql(expected_reference) }
|
144
144
|
end
|
145
|
+
|
146
|
+
describe 'changing identifiers' do
|
147
|
+
let(:objects) do
|
148
|
+
[
|
149
|
+
Nanoc::Int::Item.new('Foo', {}, '/foo'),
|
150
|
+
]
|
151
|
+
end
|
152
|
+
|
153
|
+
subject { objects[0].identifier = '/bar' }
|
154
|
+
|
155
|
+
it 'makes /foo nil' do
|
156
|
+
expect { subject }
|
157
|
+
.to change { identifiable_collection['/foo'] }
|
158
|
+
.from(objects[0])
|
159
|
+
.to(nil)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'makes /bar non-nil' do
|
163
|
+
expect { subject }
|
164
|
+
.to change { identifiable_collection['/bar'] }
|
165
|
+
.from(nil)
|
166
|
+
.to(objects[0])
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#each' do
|
171
|
+
let(:objects) do
|
172
|
+
[
|
173
|
+
Nanoc::Int::Item.new('Foo', {}, '/foo'),
|
174
|
+
Nanoc::Int::Item.new('Bar', {}, '/bar'),
|
175
|
+
]
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'loops' do
|
179
|
+
res = []
|
180
|
+
identifiable_collection.each { |i| res << i.identifier.to_s }
|
181
|
+
expect(res).to match_array(['/foo', '/bar'])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#map' do
|
186
|
+
let(:objects) do
|
187
|
+
[
|
188
|
+
Nanoc::Int::Item.new('Foo', {}, '/foo'),
|
189
|
+
Nanoc::Int::Item.new('Bar', {}, '/bar'),
|
190
|
+
]
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'loops' do
|
194
|
+
res = identifiable_collection.map { |i| i.identifier.to_s }
|
195
|
+
expect(res).to match_array(['/foo', '/bar'])
|
196
|
+
end
|
197
|
+
end
|
145
198
|
end
|
146
199
|
|
147
200
|
describe Nanoc::Int::ItemCollection do
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::Int::AggregateDataSource, stdio: true do
|
4
|
+
let(:klass_1) do
|
5
|
+
Class.new(Nanoc::DataSource) do
|
6
|
+
def items
|
7
|
+
[Nanoc::Int::Item.new('One', {}, '/one.md')]
|
8
|
+
end
|
9
|
+
|
10
|
+
def item_changes
|
11
|
+
%i[one_foo one_bar]
|
12
|
+
end
|
13
|
+
|
14
|
+
def layouts
|
15
|
+
[Nanoc::Int::Layout.new('One', {}, '/one.md')]
|
16
|
+
end
|
17
|
+
|
18
|
+
def layout_changes
|
19
|
+
%i[one_foo one_bar]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:klass_2) do
|
25
|
+
Class.new(Nanoc::DataSource) do
|
26
|
+
def items
|
27
|
+
[Nanoc::Int::Item.new('Two', {}, '/two.md')]
|
28
|
+
end
|
29
|
+
|
30
|
+
def item_changes
|
31
|
+
%i[two_foo two_bar]
|
32
|
+
end
|
33
|
+
|
34
|
+
def layouts
|
35
|
+
[Nanoc::Int::Layout.new('Two', {}, '/two.md')]
|
36
|
+
end
|
37
|
+
|
38
|
+
def layout_changes
|
39
|
+
%i[two_foo two_bar]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:data_source_1) do
|
45
|
+
klass_1.new({}, nil, nil, {})
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:data_source_2) do
|
49
|
+
klass_2.new({}, nil, nil, {})
|
50
|
+
end
|
51
|
+
|
52
|
+
subject(:data_source) do
|
53
|
+
described_class.new([data_source_1, data_source_2], {})
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#items' do
|
57
|
+
subject { data_source.items }
|
58
|
+
|
59
|
+
it 'contains all items' do
|
60
|
+
expect(subject).to match_array(data_source_1.items + data_source_2.items)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#layouts' do
|
65
|
+
subject { data_source.layouts }
|
66
|
+
|
67
|
+
it 'contains all layouts' do
|
68
|
+
expect(subject).to match_array(data_source_1.layouts + data_source_2.layouts)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#item_changes' do
|
73
|
+
subject { data_source.item_changes }
|
74
|
+
|
75
|
+
it 'yields changes from both' do
|
76
|
+
expect(subject).to match_array(data_source_1.item_changes + data_source_2.item_changes)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#layout_changes' do
|
81
|
+
subject { data_source.layout_changes }
|
82
|
+
|
83
|
+
it 'yields changes from both' do
|
84
|
+
expect(subject).to match_array(data_source_1.layout_changes + data_source_2.layout_changes)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe Nanoc::DataSource, stdio: true do
|
4
|
+
subject(:data_source) do
|
5
|
+
described_class.new({}, nil, nil, {})
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'has an empty #up implementation' do
|
9
|
+
data_source.up
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'has an empty #down implementation' do
|
13
|
+
data_source.down
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns empty #items' do
|
17
|
+
expect(data_source.items).to be_empty
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns empty #layouts' do
|
21
|
+
expect(data_source.layouts).to be_empty
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#new_item' do
|
25
|
+
it 'supports checksum data' do
|
26
|
+
item = data_source.new_item('stuff', { title: 'Stuff!' }, '/asdf', checksum_data: 'abcdef')
|
27
|
+
|
28
|
+
expect(item.content.string).to eql('stuff')
|
29
|
+
expect(item.attributes[:title]).to eql('Stuff!')
|
30
|
+
expect(item.identifier).to eql(Nanoc::Identifier.new('/asdf'))
|
31
|
+
expect(item.checksum_data).to eql('abcdef')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'supports content/attributes checksum data' do
|
35
|
+
item = data_source.new_item('stuff', { title: 'Stuff!' }, '/asdf', content_checksum_data: 'con-cs', attributes_checksum_data: 'attr-cs')
|
36
|
+
|
37
|
+
expect(item.content.string).to eql('stuff')
|
38
|
+
expect(item.attributes[:title]).to eql('Stuff!')
|
39
|
+
expect(item.identifier).to eql(Nanoc::Identifier.new('/asdf'))
|
40
|
+
expect(item.content_checksum_data).to eql('con-cs')
|
41
|
+
expect(item.attributes_checksum_data).to eql('attr-cs')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#new_layout' do
|
46
|
+
it 'supports checksum data' do
|
47
|
+
layout = data_source.new_layout('stuff', { title: 'Stuff!' }, '/asdf', checksum_data: 'abcdef')
|
48
|
+
|
49
|
+
expect(layout.content.string).to eql('stuff')
|
50
|
+
expect(layout.attributes[:title]).to eql('Stuff!')
|
51
|
+
expect(layout.identifier).to eql(Nanoc::Identifier.new('/asdf'))
|
52
|
+
expect(layout.checksum_data).to eql('abcdef')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'supports content/attributes checksum data' do
|
56
|
+
layout = data_source.new_layout('stuff', { title: 'Stuff!' }, '/asdf', content_checksum_data: 'con-cs', attributes_checksum_data: 'attr-cs')
|
57
|
+
|
58
|
+
expect(layout.content.string).to eql('stuff')
|
59
|
+
expect(layout.attributes[:title]).to eql('Stuff!')
|
60
|
+
expect(layout.identifier).to eql(Nanoc::Identifier.new('/asdf'))
|
61
|
+
expect(layout.content_checksum_data).to eql('con-cs')
|
62
|
+
expect(layout.attributes_checksum_data).to eql('attr-cs')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#item_changes' do
|
67
|
+
subject { data_source.item_changes }
|
68
|
+
|
69
|
+
it 'warns' do
|
70
|
+
expect { subject }.to output("Caution: Data source nil does not implement #item_changes; live compilation will not pick up changes in this data source.\n").to_stderr
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'never yields anything' do
|
74
|
+
q = SizedQueue.new(1)
|
75
|
+
Thread.new { subject.each { |c| q << c } }
|
76
|
+
sleep 0.1
|
77
|
+
expect { q.pop(true) }.to raise_error(ThreadError)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#layout_changes' do
|
82
|
+
subject { data_source.layout_changes }
|
83
|
+
|
84
|
+
it 'warns' do
|
85
|
+
expect { subject }.to output("Caution: Data source nil does not implement #layout_changes; live compilation will not pick up changes in this data source.\n").to_stderr
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'never yields anything' do
|
89
|
+
q = SizedQueue.new(1)
|
90
|
+
Thread.new { subject.each { |c| q << c } }
|
91
|
+
sleep 0.1
|
92
|
+
expect { q.pop(true) }.to raise_error(ThreadError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|