nanoc 4.7.3 → 4.7.4

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.
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