nanoc 4.7.3 → 4.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +5 -5
  3. data/NEWS.md +7 -0
  4. data/lib/nanoc/base/entities.rb +1 -1
  5. data/lib/nanoc/base/entities/{rule_memory.rb → action_sequence.rb} +19 -1
  6. data/lib/nanoc/base/entities/outdatedness_reasons.rb +12 -4
  7. data/lib/nanoc/base/entities/outdatedness_status.rb +1 -1
  8. data/lib/nanoc/base/repos.rb +1 -1
  9. data/lib/nanoc/base/repos/{rule_memory_store.rb → action_sequence_store.rb} +12 -12
  10. data/lib/nanoc/base/repos/checksum_store.rb +3 -3
  11. data/lib/nanoc/base/services/action_provider.rb +1 -9
  12. data/lib/nanoc/base/services/checksummer.rb +4 -2
  13. data/lib/nanoc/base/services/compiler.rb +11 -11
  14. data/lib/nanoc/base/services/compiler/phases/recalculate.rb +3 -3
  15. data/lib/nanoc/base/services/compiler/stages/cleanup.rb +1 -1
  16. data/lib/nanoc/base/services/compiler/stages/compile_reps.rb +3 -3
  17. data/lib/nanoc/base/services/compiler/stages/determine_outdatedness.rb +7 -2
  18. data/lib/nanoc/base/services/compiler_loader.rb +3 -3
  19. data/lib/nanoc/base/services/item_rep_builder.rb +4 -2
  20. data/lib/nanoc/base/services/item_rep_router.rb +7 -2
  21. data/lib/nanoc/base/services/outdatedness_checker.rb +30 -7
  22. data/lib/nanoc/base/services/outdatedness_rule.rb +7 -4
  23. data/lib/nanoc/base/services/outdatedness_rules.rb +9 -161
  24. data/lib/nanoc/base/services/outdatedness_rules/attributes_modified.rb +34 -0
  25. data/lib/nanoc/base/services/outdatedness_rules/code_snippets_modified.rb +26 -0
  26. data/lib/nanoc/base/services/outdatedness_rules/configuration_modified.rb +23 -0
  27. data/lib/nanoc/base/services/outdatedness_rules/content_modified.rb +15 -0
  28. data/lib/nanoc/base/services/outdatedness_rules/not_written.rb +11 -0
  29. data/lib/nanoc/base/services/outdatedness_rules/paths_modified.rb +20 -0
  30. data/lib/nanoc/base/services/outdatedness_rules/rules_modified.rb +13 -0
  31. data/lib/nanoc/base/services/outdatedness_rules/uses_always_outdated_filter.rb +20 -0
  32. data/lib/nanoc/rule_dsl.rb +1 -1
  33. data/lib/nanoc/rule_dsl/action_provider.rb +7 -11
  34. data/lib/nanoc/rule_dsl/{rule_memory_calculator.rb → action_sequence_calculator.rb} +21 -39
  35. data/lib/nanoc/rule_dsl/recording_executor.rb +7 -7
  36. data/lib/nanoc/spec.rb +7 -7
  37. data/lib/nanoc/version.rb +1 -1
  38. data/spec/nanoc/base/checksummer_spec.rb +20 -0
  39. data/spec/nanoc/base/compiler_spec.rb +7 -10
  40. data/spec/nanoc/base/entities/action_sequence_spec.rb +278 -0
  41. data/spec/nanoc/base/repos/checksum_store_spec.rb +22 -2
  42. data/spec/nanoc/base/services/compiler/stages/cleanup_spec.rb +2 -2
  43. data/spec/nanoc/base/services/compiler/stages/compile_reps_spec.rb +5 -9
  44. data/spec/nanoc/base/services/executor_spec.rb +5 -5
  45. data/spec/nanoc/base/services/item_rep_router_spec.rb +36 -18
  46. data/spec/nanoc/base/services/outdatedness_checker_spec.rb +74 -30
  47. data/spec/nanoc/base/services/outdatedness_rules_spec.rb +78 -18
  48. data/spec/nanoc/helpers/rendering_spec.rb +4 -4
  49. data/spec/nanoc/rule_dsl/{rule_memory_calculator_spec.rb → action_sequence_calculator_spec.rb} +6 -61
  50. data/spec/nanoc/rule_dsl/recording_executor_spec.rb +45 -45
  51. data/test/base/test_outdatedness_checker.rb +1 -1
  52. data/test/rule_dsl/test_action_provider.rb +3 -3
  53. metadata +15 -7
  54. data/spec/nanoc/base/entities/rule_memory_spec.rb +0 -167
@@ -0,0 +1,13 @@
1
+ module Nanoc::Int::OutdatednessRules
2
+ class RulesModified < Nanoc::Int::OutdatednessRule
3
+ affects_props :compiled_content, :path
4
+
5
+ def apply(obj, outdatedness_checker)
6
+ mem_old = outdatedness_checker.action_sequence_store[obj]
7
+ mem_new = outdatedness_checker.action_sequence_for(obj).serialize
8
+ unless mem_old.eql?(mem_new)
9
+ Nanoc::Int::OutdatednessReasons::RulesModified
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Nanoc::Int::OutdatednessRules
2
+ class UsesAlwaysOutdatedFilter < Nanoc::Int::OutdatednessRule
3
+ affects_props :raw_content, :attributes, :path
4
+
5
+ def apply(obj, outdatedness_checker)
6
+ mem = outdatedness_checker.action_sequence_for(obj)
7
+ if any_always_outdated?(mem)
8
+ Nanoc::Int::OutdatednessReasons::UsesAlwaysOutdatedFilter
9
+ end
10
+ end
11
+
12
+ def any_always_outdated?(mem)
13
+ mem
14
+ .select { |a| a.is_a?(Nanoc::Int::ProcessingActions::Filter) }
15
+ .map { |a| Nanoc::Filter.named(a.filter_name) }
16
+ .compact
17
+ .any?(&:always_outdated?)
18
+ end
19
+ end
20
+ end
@@ -2,7 +2,7 @@ require_relative 'rule_dsl/compiler_dsl'
2
2
  require_relative 'rule_dsl/action_provider'
3
3
  require_relative 'rule_dsl/recording_executor'
4
4
  require_relative 'rule_dsl/rule_context'
5
- require_relative 'rule_dsl/rule_memory_calculator'
5
+ require_relative 'rule_dsl/action_sequence_calculator'
6
6
  require_relative 'rule_dsl/rule'
7
7
  require_relative 'rule_dsl/rules_collection'
8
8
  require_relative 'rule_dsl/rules_loader'
@@ -8,21 +8,21 @@ module Nanoc::RuleDSL
8
8
  def self.for(site)
9
9
  rules_collection = Nanoc::RuleDSL::RulesCollection.new
10
10
 
11
- rule_memory_calculator =
12
- Nanoc::RuleDSL::RuleMemoryCalculator.new(
11
+ action_sequence_calculator =
12
+ Nanoc::RuleDSL::ActionSequenceCalculator.new(
13
13
  rules_collection: rules_collection, site: site,
14
14
  )
15
15
 
16
- action_provider = new(rules_collection, rule_memory_calculator)
16
+ action_provider = new(rules_collection, action_sequence_calculator)
17
17
 
18
18
  Nanoc::RuleDSL::RulesLoader.new(site.config, rules_collection).load
19
19
 
20
20
  action_provider
21
21
  end
22
22
 
23
- def initialize(rules_collection, rule_memory_calculator)
23
+ def initialize(rules_collection, action_sequence_calculator)
24
24
  @rules_collection = rules_collection
25
- @rule_memory_calculator = rule_memory_calculator
25
+ @action_sequence_calculator = action_sequence_calculator
26
26
  end
27
27
 
28
28
  def rep_names_for(item)
@@ -32,12 +32,8 @@ module Nanoc::RuleDSL
32
32
  matching_rules.map(&:rep_name).uniq
33
33
  end
34
34
 
35
- def memory_for(rep)
36
- @rule_memory_calculator[rep]
37
- end
38
-
39
- def snapshots_defs_for(rep)
40
- @rule_memory_calculator.snapshots_defs_for(rep)
35
+ def action_sequence_for(rep)
36
+ @action_sequence_calculator[rep]
41
37
  end
42
38
 
43
39
  def need_preprocessing?
@@ -1,24 +1,24 @@
1
1
  module Nanoc::RuleDSL
2
- # Calculates rule memories for objects that can be run through a rule (item
2
+ # Calculates action sequences for objects that can be run through a rule (item
3
3
  # representations and layouts).
4
4
  #
5
5
  # @api private
6
- class RuleMemoryCalculator
6
+ class ActionSequenceCalculator
7
7
  extend Nanoc::Int::Memoization
8
8
 
9
9
  class UnsupportedObjectTypeException < ::Nanoc::Error
10
10
  def initialize(obj)
11
- super("Do not know how to calculate the rule memory for #{obj.inspect}")
11
+ super("Do not know how to calculate the action sequence for #{obj.inspect}")
12
12
  end
13
13
  end
14
14
 
15
- class NoRuleMemoryForLayoutException < ::Nanoc::Error
15
+ class NoActionSequenceForLayoutException < ::Nanoc::Error
16
16
  def initialize(layout)
17
17
  super("There is no layout rule specified for #{layout.inspect}")
18
18
  end
19
19
  end
20
20
 
21
- class NoRuleMemoryForItemRepException < ::Nanoc::Error
21
+ class NoActionSequenceForItemRepException < ::Nanoc::Error
22
22
  def initialize(item)
23
23
  super("There is no compilation rule specified for #{item.inspect}")
24
24
  end
@@ -42,78 +42,60 @@ module Nanoc::RuleDSL
42
42
 
43
43
  # @param [#reference] obj
44
44
  #
45
- # @return [Nanoc::Int::RuleMemory]
45
+ # @return [Nanoc::Int::ActionSequence]
46
46
  def [](obj)
47
47
  case obj
48
48
  when Nanoc::Int::ItemRep
49
- new_rule_memory_for_rep(obj)
49
+ new_action_sequence_for_rep(obj)
50
50
  when Nanoc::Int::Layout
51
- new_rule_memory_for_layout(obj)
51
+ new_action_sequence_for_layout(obj)
52
52
  else
53
53
  raise UnsupportedObjectTypeException.new(obj)
54
54
  end
55
55
  end
56
56
 
57
- def snapshots_defs_for(rep)
58
- is_binary = rep.item.content.binary?
59
- snapshot_defs = []
60
-
61
- self[rep].each do |action|
62
- case action
63
- when Nanoc::Int::ProcessingActions::Snapshot
64
- action.snapshot_names.each do |snapshot_name|
65
- snapshot_defs << Nanoc::Int::SnapshotDef.new(snapshot_name, binary: is_binary)
66
- end
67
- when Nanoc::Int::ProcessingActions::Filter
68
- is_binary = Nanoc::Filter.named!(action.filter_name).to_binary?
69
- end
70
- end
71
-
72
- snapshot_defs
73
- end
74
-
75
57
  # @param [Nanoc::Int::ItemRep] rep The item representation to get the rule
76
58
  # memory for
77
59
  #
78
- # @return [Nanoc::Int::RuleMemory]
79
- def new_rule_memory_for_rep(rep)
60
+ # @return [Nanoc::Int::ActionSequence]
61
+ def new_action_sequence_for_rep(rep)
80
62
  dependency_tracker = Nanoc::Int::DependencyTracker::Null.new
81
63
  view_context = @site.compiler.compilation_context.create_view_context(dependency_tracker)
82
64
 
83
- rule_memory = Nanoc::Int::RuleMemory.new(rep)
84
- executor = Nanoc::RuleDSL::RecordingExecutor.new(rule_memory)
65
+ action_sequence = Nanoc::Int::ActionSequence.new(rep)
66
+ executor = Nanoc::RuleDSL::RecordingExecutor.new(action_sequence)
85
67
  rule = @rules_collection.compilation_rule_for(rep)
86
68
 
87
69
  unless rule
88
- raise NoRuleMemoryForItemRepException.new(rep)
70
+ raise NoActionSequenceForItemRepException.new(rep)
89
71
  end
90
72
 
91
73
  executor.snapshot(:raw)
92
74
  rule.apply_to(rep, executor: executor, site: @site, view_context: view_context)
93
- if rule_memory.any_layouts?
75
+ if action_sequence.any_layouts?
94
76
  executor.snapshot(:post)
95
77
  end
96
- unless rule_memory.snapshot_actions.any? { |sa| sa.snapshot_names.include?(:last) }
78
+ unless action_sequence.snapshot_actions.any? { |sa| sa.snapshot_names.include?(:last) }
97
79
  executor.snapshot(:last)
98
80
  end
99
- unless rule_memory.snapshot_actions.any? { |sa| sa.snapshot_names.include?(:pre) }
81
+ unless action_sequence.snapshot_actions.any? { |sa| sa.snapshot_names.include?(:pre) }
100
82
  executor.snapshot(:pre)
101
83
  end
102
84
 
103
- copy_paths_from_routing_rules(rule_memory.compact_snapshots, rep: rep)
85
+ copy_paths_from_routing_rules(action_sequence.compact_snapshots, rep: rep)
104
86
  end
105
87
 
106
88
  # @param [Nanoc::Int::Layout] layout
107
89
  #
108
- # @return [Nanoc::Int::RuleMemory]
109
- def new_rule_memory_for_layout(layout)
90
+ # @return [Nanoc::Int::ActionSequence]
91
+ def new_action_sequence_for_layout(layout)
110
92
  res = @rules_collection.filter_for_layout(layout)
111
93
 
112
94
  unless res
113
- raise NoRuleMemoryForLayoutException.new(layout)
95
+ raise NoActionSequenceForLayoutException.new(layout)
114
96
  end
115
97
 
116
- Nanoc::Int::RuleMemory.new(layout).tap do |rm|
98
+ Nanoc::Int::ActionSequence.new(layout).tap do |rm|
117
99
  rm.add_filter(res[0], res[1])
118
100
  end
119
101
  end
@@ -3,12 +3,12 @@ module Nanoc
3
3
  class RecordingExecutor
4
4
  include Nanoc::Int::ContractsSupport
5
5
 
6
- def initialize(rule_memory)
7
- @rule_memory = rule_memory
6
+ def initialize(action_sequence)
7
+ @action_sequence = action_sequence
8
8
  end
9
9
 
10
10
  def filter(filter_name, filter_args = {})
11
- @rule_memory.add_filter(filter_name, filter_args)
11
+ @action_sequence.add_filter(filter_name, filter_args)
12
12
  end
13
13
 
14
14
  def layout(layout_identifier, extra_filter_args = {})
@@ -16,17 +16,17 @@ module Nanoc
16
16
  raise ArgumentError.new('The layout passed to #layout must be a string')
17
17
  end
18
18
 
19
- unless @rule_memory.any_layouts?
20
- @rule_memory.add_snapshot(:pre, nil)
19
+ unless @action_sequence.any_layouts?
20
+ @action_sequence.add_snapshot(:pre, nil)
21
21
  end
22
22
 
23
- @rule_memory.add_layout(layout_identifier, extra_filter_args)
23
+ @action_sequence.add_layout(layout_identifier, extra_filter_args)
24
24
  end
25
25
 
26
26
  Pathlike = C::Maybe[C::Or[String, Nanoc::Identifier]]
27
27
  contract Symbol, C::KeywordArgs[path: C::Optional[Pathlike]] => nil
28
28
  def snapshot(snapshot_name, path: nil)
29
- @rule_memory.add_snapshot(snapshot_name, path && path.to_s)
29
+ @action_sequence.add_snapshot(snapshot_name, path && path.to_s)
30
30
  nil
31
31
  end
32
32
  end
data/lib/nanoc/spec.rb CHANGED
@@ -12,7 +12,7 @@ module Nanoc
12
12
  @mod = mod
13
13
 
14
14
  @erbout = ''
15
- @rule_memory = {}
15
+ @action_sequence = {}
16
16
  @config = Nanoc::Int::Configuration.new.with_defaults
17
17
  @reps = Nanoc::Int::ItemRepRepo.new
18
18
  @items = Nanoc::Int::IdentifiableCollection.new(@config)
@@ -103,12 +103,12 @@ module Nanoc
103
103
  assigns[:layouts]
104
104
  end
105
105
 
106
- def rule_memory_for(obj)
107
- @rule_memory.fetch(obj, [])
106
+ def action_sequence_for(obj)
107
+ @action_sequence.fetch(obj, [])
108
108
  end
109
109
 
110
- def update_rule_memory(obj, memory)
111
- @rule_memory[obj] = memory
110
+ def update_action_sequence(obj, memory)
111
+ @action_sequence[obj] = memory
112
112
  end
113
113
 
114
114
  def snapshot_repo
@@ -141,8 +141,8 @@ module Nanoc
141
141
  [:default]
142
142
  end
143
143
 
144
- def memory_for(obj)
145
- @context.rule_memory_for(obj)
144
+ def action_sequence_for(obj)
145
+ @context.action_sequence_for(obj)
146
146
  end
147
147
 
148
148
  def snapshots_defs_for(_rep)
data/lib/nanoc/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Nanoc
2
2
  # The current Nanoc version.
3
- VERSION = '4.7.3'.freeze
3
+ VERSION = '4.7.4'.freeze
4
4
  end
@@ -23,6 +23,26 @@ end
23
23
  describe Nanoc::Int::Checksummer do
24
24
  subject { described_class.calc(obj, Nanoc::Int::Checksummer::VerboseDigest) }
25
25
 
26
+ describe '.calc_for_each_attribute_of' do
27
+ let(:obj) { Nanoc::Int::Item.new('asdf', { 'foo' => 'bar' }, '/foo.md') }
28
+
29
+ context 'compact' do
30
+ subject do
31
+ described_class.calc_for_each_attribute_of(obj)
32
+ end
33
+
34
+ it { is_expected.to have_key(:foo) }
35
+ end
36
+
37
+ context 'verbose' do
38
+ subject do
39
+ described_class.calc_for_each_attribute_of(obj, Nanoc::Int::Checksummer::VerboseDigest)
40
+ end
41
+
42
+ it { is_expected.to eq(foo: 'String<bar>') }
43
+ end
44
+ end
45
+
26
46
  context 'String' do
27
47
  let(:obj) { 'hello' }
28
48
  it { is_expected.to eql('String<hello>') }
@@ -4,7 +4,7 @@ describe Nanoc::Int::Compiler do
4
4
  site,
5
5
  compiled_content_cache: compiled_content_cache,
6
6
  checksum_store: checksum_store,
7
- rule_memory_store: rule_memory_store,
7
+ action_sequence_store: action_sequence_store,
8
8
  action_provider: action_provider,
9
9
  dependency_store: dependency_store,
10
10
  outdatedness_checker: outdatedness_checker,
@@ -13,8 +13,8 @@ describe Nanoc::Int::Compiler do
13
13
  )
14
14
  end
15
15
 
16
- let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: items) }
17
- let(:rule_memory_store) { Nanoc::Int::RuleMemoryStore.new }
16
+ let(:checksum_store) { Nanoc::Int::ChecksumStore.new(objects: items) }
17
+ let(:action_sequence_store) { Nanoc::Int::ActionSequenceStore.new }
18
18
 
19
19
  let(:dependency_store) { Nanoc::Int::DependencyStore.new(items.to_a) }
20
20
  let(:reps) { Nanoc::Int::ItemRepRepo.new }
@@ -54,7 +54,7 @@ describe Nanoc::Int::Compiler do
54
54
  Nanoc::Int::ProcessingActions::Snapshot.new([:last], []),
55
55
  ]
56
56
 
57
- Nanoc::Int::RuleMemory.new(nil, actions: actions)
57
+ Nanoc::Int::ActionSequence.new(nil, actions: actions)
58
58
  end
59
59
 
60
60
  before do
@@ -68,8 +68,9 @@ describe Nanoc::Int::Compiler do
68
68
  allow(outdatedness_checker).to receive(:outdated?).with(rep).and_return(true)
69
69
  allow(outdatedness_checker).to receive(:outdated?).with(other_rep).and_return(true)
70
70
 
71
- allow(action_provider).to receive(:memory_for).with(rep).and_return(memory)
72
- allow(action_provider).to receive(:memory_for).with(other_rep).and_return(memory)
71
+ # FIXME: eww
72
+ action_sequences = { rep => memory, other_rep => memory }
73
+ compiler.instance_variable_set(:@action_sequences, action_sequences)
73
74
 
74
75
  allow(Nanoc::Int::NotificationCenter).to receive(:post)
75
76
  end
@@ -100,10 +101,6 @@ describe Nanoc::Int::Compiler do
100
101
  context 'interrupted compilation' do
101
102
  let(:item) { Nanoc::Int::Item.new('other=<%= @items["/other.*"].compiled_content %>', {}, '/hi.md') }
102
103
 
103
- before do
104
- expect(action_provider).to receive(:memory_for).with(other_rep).and_return(memory)
105
- end
106
-
107
104
  it 'generates expected output' do
108
105
  expect(compiler.snapshot_repo.get(rep, :last)).to be_nil
109
106
 
@@ -0,0 +1,278 @@
1
+ describe Nanoc::Int::ActionSequence do
2
+ let(:action_sequence) { described_class.new(rep) }
3
+ let(:rep) { double(:rep) }
4
+
5
+ describe '#size' do
6
+ subject { action_sequence.size }
7
+
8
+ context 'no actions' do
9
+ it { is_expected.to eql(0) }
10
+ end
11
+
12
+ context 'some actions' do
13
+ before do
14
+ action_sequence.add_filter(:foo, {})
15
+ end
16
+
17
+ it { is_expected.to eql(1) }
18
+ end
19
+ end
20
+
21
+ describe '#[]' do
22
+ subject { action_sequence[index] }
23
+ let(:index) { 0 }
24
+
25
+ context 'no actions' do
26
+ it { is_expected.to be_nil }
27
+ end
28
+
29
+ context 'some actions' do
30
+ before do
31
+ action_sequence.add_filter(:foo, {})
32
+ end
33
+
34
+ it { is_expected.to be_a(Nanoc::Int::ProcessingActions::Filter) }
35
+ end
36
+ end
37
+
38
+ describe '#add_filter' do
39
+ example do
40
+ action_sequence.add_filter(:foo, donkey: 123)
41
+
42
+ expect(action_sequence.size).to eql(1)
43
+ expect(action_sequence[0]).to be_a(Nanoc::Int::ProcessingActions::Filter)
44
+ expect(action_sequence[0].filter_name).to eql(:foo)
45
+ expect(action_sequence[0].params).to eql(donkey: 123)
46
+ end
47
+ end
48
+
49
+ describe '#add_layout' do
50
+ example do
51
+ action_sequence.add_layout('/foo.*', donkey: 123)
52
+
53
+ expect(action_sequence.size).to eql(1)
54
+ expect(action_sequence[0]).to be_a(Nanoc::Int::ProcessingActions::Layout)
55
+ expect(action_sequence[0].layout_identifier).to eql('/foo.*')
56
+ expect(action_sequence[0].params).to eql(donkey: 123)
57
+ end
58
+ end
59
+
60
+ describe '#add_snapshot' do
61
+ context 'snapshot does not yet exist' do
62
+ example do
63
+ action_sequence.add_snapshot(:before_layout, '/foo.md')
64
+
65
+ expect(action_sequence.size).to eql(1)
66
+ expect(action_sequence[0]).to be_a(Nanoc::Int::ProcessingActions::Snapshot)
67
+ expect(action_sequence[0].snapshot_names).to eql([:before_layout])
68
+ expect(action_sequence[0].paths).to eql(['/foo.md'])
69
+ end
70
+ end
71
+
72
+ context 'snapshot already exist' do
73
+ before do
74
+ action_sequence.add_snapshot(:before_layout, '/bar.md')
75
+ end
76
+
77
+ it 'raises' do
78
+ expect { action_sequence.add_snapshot(:before_layout, '/foo.md') }
79
+ .to raise_error(Nanoc::Int::Errors::CannotCreateMultipleSnapshotsWithSameName)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#each' do
85
+ before do
86
+ action_sequence.add_filter(:erb, awesomeness: 'high')
87
+ action_sequence.add_snapshot(:bar, '/foo.md')
88
+ action_sequence.add_layout('/default.erb', somelayoutparam: 'yes')
89
+ end
90
+
91
+ example do
92
+ actions = []
93
+ action_sequence.each { |a| actions << a }
94
+ expect(actions.size).to eq(3)
95
+ end
96
+ end
97
+
98
+ describe '#map' do
99
+ before do
100
+ action_sequence.add_filter(:erb, awesomeness: 'high')
101
+ action_sequence.add_snapshot(:bar, '/foo.md')
102
+ action_sequence.add_layout('/default.erb', somelayoutparam: 'yes')
103
+ end
104
+
105
+ example do
106
+ res = action_sequence.map { Nanoc::Int::ProcessingActions::Filter.new(:donkey, {}) }
107
+ expect(res.to_a.size).to eq(3)
108
+ expect(res.to_a).to all(be_a(Nanoc::Int::ProcessingActions::Filter))
109
+ end
110
+ end
111
+
112
+ describe '#serialize' do
113
+ subject { action_sequence.serialize }
114
+
115
+ before do
116
+ action_sequence.add_filter(:erb, awesomeness: 'high')
117
+ action_sequence.add_snapshot(:bar, '/foo.md')
118
+ action_sequence.add_layout('/default.erb', somelayoutparam: 'yes')
119
+ end
120
+
121
+ example do
122
+ expect(subject).to eql(
123
+ [
124
+ [:filter, :erb, 'PeWUm2PtXYtqeHJdTqnY7kkwAow='],
125
+ [:snapshot, [:bar], true, ['/foo.md']],
126
+ [:layout, '/default.erb', '97LAe1pYTLKczxBsu+x4MmvqdkU='],
127
+ ],
128
+ )
129
+ end
130
+ end
131
+
132
+ describe '#compact_snapshots' do
133
+ subject { action_sequence.compact_snapshots }
134
+
135
+ before do
136
+ action_sequence.add_snapshot(:a1, nil)
137
+ action_sequence.add_snapshot(:a2, '/a2.md')
138
+ action_sequence.add_snapshot(:a3, nil)
139
+ action_sequence.add_filter(:erb, awesomeness: 'high')
140
+ action_sequence.add_snapshot(:b1, '/b1.md')
141
+ action_sequence.add_snapshot(:b2, nil)
142
+ action_sequence.add_snapshot(:b3, '/b3.md')
143
+ action_sequence.add_filter(:erb, awesomeness: 'high')
144
+ action_sequence.add_snapshot(:c, nil)
145
+ end
146
+
147
+ example do
148
+ expect(subject[0]).to be_a(Nanoc::Int::ProcessingActions::Snapshot)
149
+ expect(subject[0].snapshot_names).to eql(%i(a1 a2 a3))
150
+ expect(subject[0].paths).to eql(['/a2.md'])
151
+
152
+ expect(subject[1]).to be_a(Nanoc::Int::ProcessingActions::Filter)
153
+
154
+ expect(subject[2]).to be_a(Nanoc::Int::ProcessingActions::Snapshot)
155
+ expect(subject[2].snapshot_names).to eql(%i(b1 b2 b3))
156
+ expect(subject[2].paths).to eql(['/b1.md', '/b3.md'])
157
+
158
+ expect(subject[3]).to be_a(Nanoc::Int::ProcessingActions::Filter)
159
+
160
+ expect(subject[4]).to be_a(Nanoc::Int::ProcessingActions::Snapshot)
161
+ expect(subject[4].snapshot_names).to eql([:c])
162
+ expect(subject[4].paths).to be_empty
163
+
164
+ expect(subject.size).to eql(5)
165
+ end
166
+ end
167
+
168
+ describe '#snapshots_defs' do
169
+ subject { action_sequence.snapshots_defs }
170
+
171
+ let(:item) { Nanoc::Int::Item.new('asdf', {}, '/foo.md') }
172
+ let(:rep) { Nanoc::Int::ItemRep.new(item, :default) }
173
+
174
+ Class.new(Nanoc::Filter) do
175
+ identifier :RuleMemSpec_filter_b2b
176
+ type :binary => :binary # rubocop:disable Style/HashSyntax
177
+
178
+ def run(content, params = {}); end
179
+ end
180
+
181
+ Class.new(Nanoc::Filter) do
182
+ identifier :RuleMemSpec_filter_b2t
183
+ type :binary => :text # rubocop:disable Style/HashSyntax
184
+
185
+ def run(content, params = {}); end
186
+ end
187
+
188
+ Class.new(Nanoc::Filter) do
189
+ identifier :RuleMemSpec_filter_t2t
190
+ type :text => :text # rubocop:disable Style/HashSyntax
191
+
192
+ def run(content, params = {}); end
193
+ end
194
+
195
+ Class.new(Nanoc::Filter) do
196
+ identifier :RuleMemSpec_filter_t2b
197
+ type :text => :binary # rubocop:disable Style/HashSyntax
198
+
199
+ def run(content, params = {}); end
200
+ end
201
+
202
+ it 'has no snapshot defs by default' do
203
+ expect(subject).to be_empty
204
+ end
205
+
206
+ context 'textual item' do
207
+ let(:item) { Nanoc::Int::Item.new('asdf', {}, '/foo.md') }
208
+
209
+ it 'generates initial textual snapshot def' do
210
+ action_sequence.add_snapshot(:giraffe, nil)
211
+
212
+ expect(subject.size).to eq(1)
213
+ expect(subject[0].name).to eq(:giraffe)
214
+ expect(subject[0]).not_to be_binary
215
+ end
216
+
217
+ it 'generated follow-up textual snapshot def if previous filter is textual' do
218
+ action_sequence.add_snapshot(:giraffe, nil)
219
+ action_sequence.add_filter(:RuleMemSpec_filter_t2t, arguments: 'irrelevant')
220
+ action_sequence.add_snapshot(:zebra, nil)
221
+
222
+ expect(subject.size).to eq(2)
223
+ expect(subject[0].name).to eq(:giraffe)
224
+ expect(subject[0]).not_to be_binary
225
+ expect(subject[1].name).to eq(:zebra)
226
+ expect(subject[1]).not_to be_binary
227
+ end
228
+
229
+ it 'generated follow-up binary snapshot def if previous filter is text-to-bianry' do
230
+ action_sequence.add_snapshot(:giraffe, nil)
231
+ action_sequence.add_filter(:RuleMemSpec_filter_t2b, arguments: 'irrelevant')
232
+ action_sequence.add_snapshot(:zebra, nil)
233
+
234
+ expect(subject.size).to eq(2)
235
+ expect(subject[0].name).to eq(:giraffe)
236
+ expect(subject[0]).not_to be_binary
237
+ expect(subject[1].name).to eq(:zebra)
238
+ expect(subject[1]).to be_binary
239
+ end
240
+ end
241
+
242
+ context 'binary item' do
243
+ let(:item) { Nanoc::Int::Item.new(Nanoc::Int::BinaryContent.new('/asdf.dat'), {}, '/foo.md') }
244
+
245
+ it 'generates initial binary snapshot def' do
246
+ action_sequence.add_snapshot(:giraffe, nil)
247
+
248
+ expect(subject.size).to eq(1)
249
+ expect(subject[0].name).to eq(:giraffe)
250
+ expect(subject[0]).to be_binary
251
+ end
252
+
253
+ it 'generated follow-up binary snapshot def if previous filter is binary' do
254
+ action_sequence.add_snapshot(:giraffe, nil)
255
+ action_sequence.add_filter(:RuleMemSpec_filter_b2b, arguments: 'irrelevant')
256
+ action_sequence.add_snapshot(:zebra, nil)
257
+
258
+ expect(subject.size).to eq(2)
259
+ expect(subject[0].name).to eq(:giraffe)
260
+ expect(subject[0]).to be_binary
261
+ expect(subject[1].name).to eq(:zebra)
262
+ expect(subject[1]).to be_binary
263
+ end
264
+
265
+ it 'generated follow-up textual snapshot def if previous filter is binary-to-text' do
266
+ action_sequence.add_snapshot(:giraffe, nil)
267
+ action_sequence.add_filter(:RuleMemSpec_filter_b2t, arguments: 'irrelevant')
268
+ action_sequence.add_snapshot(:zebra, nil)
269
+
270
+ expect(subject.size).to eq(2)
271
+ expect(subject[0].name).to eq(:giraffe)
272
+ expect(subject[0]).to be_binary
273
+ expect(subject[1].name).to eq(:zebra)
274
+ expect(subject[1]).not_to be_binary
275
+ end
276
+ end
277
+ end
278
+ end