nanoc-core 4.12.8 → 4.12.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a29a2064140d04c44df1122dc537ca800a3ed7c20bfb740c4009f3b976067ebb
4
- data.tar.gz: 6fc3869373babe4c16671b15747d0d3da4b291e4f6434cf1af6e5fbe05c99799
3
+ metadata.gz: 835f6e4a74f07183143caa0c2d27f304fa5a712c3231dddc2dd28974f714b117
4
+ data.tar.gz: 71331c08284b2f0da1b6410c8a5c17230efa1606640c1ca7e8724fb97e037951
5
5
  SHA512:
6
- metadata.gz: bd1fd013b69ae47c40b8a1c5558729314603ceadabdadf3eb7b117b810988a7f7d777d5f3d6dba9f3e4f899763064c073ddd1e808f7d1e0f8aae8d52dc0c1e43
7
- data.tar.gz: a11a2202ed08c519e151f097aee47ee16e189a969169fb09ca29162acb99436531007c8c943b6dea892be702454e518376a16253dc9f181069625305e1f09554
6
+ metadata.gz: 1c3b6430105aab73a5e9efff550b3519bd3e19cf99cb9b70f7a3b42916fd48becc091ea7325740673936373650e0d2950f986e507128aa1a7156f0e95bbb1520
7
+ data.tar.gz: 24ef14012f2ed47f9dd77f885601c395b58fb4d50fb61afa2196fedeecac2571d3702ad87f0e7d80d8806a07b6712364774cf6012650595f4a0cae072e85353e
@@ -81,7 +81,8 @@ module Nanoc
81
81
  # NOTE: Other behaviors are registered elsewhere
82
82
  # (search for `define_behavior`).
83
83
 
84
- define_behavior(Array, ArrayUpdateBehavior)
84
+ define_behavior(Array, CollectionUpdateBehavior)
85
+ define_behavior(Set, SetUpdateBehavior)
85
86
  define_behavior(FalseClass, NoUpdateBehavior)
86
87
  define_behavior(Hash, HashUpdateBehavior)
87
88
  define_behavior(NilClass, NoUpdateBehavior)
@@ -96,7 +97,7 @@ module Nanoc
96
97
  define_behavior(Nanoc::Core::Configuration, HashUpdateBehavior)
97
98
  define_behavior(Nanoc::Core::Context, ContextUpdateBehavior)
98
99
  define_behavior(Nanoc::Core::CodeSnippet, DataUpdateBehavior)
99
- define_behavior(Nanoc::Core::IdentifiableCollection, ArrayUpdateBehavior)
100
+ define_behavior(Nanoc::Core::IdentifiableCollection, CollectionUpdateBehavior)
100
101
  define_behavior(Nanoc::Core::Identifier, ToSUpdateBehavior)
101
102
  define_behavior(Nanoc::Core::Item, DocumentUpdateBehavior)
102
103
  define_behavior(Nanoc::Core::ItemRep, ItemRepUpdateBehavior)
@@ -194,7 +195,7 @@ module Nanoc
194
195
  end
195
196
  end
196
197
 
197
- class ArrayUpdateBehavior < UpdateBehavior
198
+ class CollectionUpdateBehavior < UpdateBehavior
198
199
  def self.update(obj, digest)
199
200
  obj.each do |el|
200
201
  yield(el)
@@ -203,6 +204,13 @@ module Nanoc
203
204
  end
204
205
  end
205
206
 
207
+ class SetUpdateBehavior < CollectionUpdateBehavior
208
+ def self.update(obj, digest)
209
+ # Similar to CollectionUpdateBehavior, but sorted for consistency.
210
+ super(obj.sort { |a, b| (a <=> b) || 0 }, digest)
211
+ end
212
+ end
213
+
206
214
  class HashUpdateBehavior < UpdateBehavior
207
215
  def self.update(obj, digest)
208
216
  obj.each do |key, value|
@@ -25,6 +25,7 @@ module Nanoc
25
25
  Maybe = Ignorer.instance
26
26
  None = Ignorer.instance
27
27
  ArrayOf = Ignorer.instance
28
+ SetOf = Ignorer.instance
28
29
  Or = Ignorer.instance
29
30
  Func = Ignorer.instance
30
31
  RespondTo = Ignorer.instance
@@ -96,8 +97,7 @@ module Nanoc
96
97
  false
97
98
  end
98
99
 
99
- # FIXME: Do something better with contracts on Ruby 3.x
100
- @_contracts_support__should_enable = contracts_loadable && !RUBY_VERSION.start_with?('3') && !ENV.key?('DISABLE_CONTRACTS')
100
+ @_contracts_support__should_enable = contracts_loadable && !ENV.key?('DISABLE_CONTRACTS')
101
101
 
102
102
  if @_contracts_support__should_enable
103
103
  # FIXME: ugly
@@ -10,9 +10,39 @@ module Nanoc
10
10
  attr_reader :raw_content
11
11
 
12
12
  # TODO: Split raw_content for documents and collections
13
- C_RAW_CONTENT = C::Or[C::IterOf[C::Or[String, Regexp]], C::Bool]
14
- C_ATTRS = C::Or[C::IterOf[Symbol], C::Bool]
15
- contract C::KeywordArgs[raw_content: C::Optional[C_RAW_CONTENT], attributes: C::Optional[C_ATTRS], compiled_content: C::Optional[C::Bool], path: C::Optional[C::Bool]] => C::Any
13
+ C_RAW_CONTENT =
14
+ C::Or[
15
+ C::SetOf[C::Or[String, Regexp]],
16
+ C::ArrayOf[C::Or[String, Regexp]],
17
+ C::Bool
18
+ ]
19
+
20
+ C_ATTR =
21
+ C::Or[
22
+ C::SetOf[
23
+ C::Or[
24
+ Symbol, # any value
25
+ [Symbol, C::Any] # pair (specific value)
26
+ ],
27
+ ],
28
+ C::ArrayOf[
29
+ C::Or[
30
+ Symbol, # any value
31
+ [Symbol, C::Any] # pair (specific value)
32
+ ],
33
+ ],
34
+ C::Bool
35
+ ]
36
+
37
+ C_ARGS =
38
+ C::KeywordArgs[
39
+ raw_content: C::Optional[C_RAW_CONTENT],
40
+ attributes: C::Optional[C_ATTR],
41
+ compiled_content: C::Optional[C::Bool],
42
+ path: C::Optional[C::Bool]
43
+ ]
44
+
45
+ contract C_ARGS => C::Any
16
46
  def initialize(raw_content: false, attributes: false, compiled_content: false, path: false)
17
47
  @compiled_content = compiled_content
18
48
  @path = path
@@ -21,7 +51,7 @@ module Nanoc
21
51
  case attributes
22
52
  when Set
23
53
  attributes
24
- when Enumerable
54
+ when Array
25
55
  Set.new(attributes)
26
56
  else
27
57
  attributes
@@ -31,7 +61,7 @@ module Nanoc
31
61
  case raw_content
32
62
  when Set
33
63
  raw_content
34
- when Enumerable
64
+ when Array
35
65
  Set.new(raw_content)
36
66
  else
37
67
  raw_content
@@ -46,6 +76,23 @@ module Nanoc
46
76
  s << (attributes? ? 'a' : '_')
47
77
  s << (compiled_content? ? 'c' : '_')
48
78
  s << (path? ? 'p' : '_')
79
+
80
+ if @raw_content.is_a?(Set)
81
+ @raw_content.each do |elem|
82
+ s << '; raw_content('
83
+ s << elem.inspect
84
+ s << ')'
85
+ end
86
+ end
87
+
88
+ if @attributes.is_a?(Set)
89
+ @attributes.each do |elem|
90
+ s << '; attr('
91
+ s << elem.inspect
92
+ s << ')'
93
+ end
94
+ end
95
+
49
96
  s << ')'
50
97
  end
51
98
  end
@@ -63,7 +110,7 @@ module Nanoc
63
110
  contract C::None => C::Bool
64
111
  def raw_content?
65
112
  case @raw_content
66
- when Enumerable
113
+ when Set
67
114
  @raw_content.any?
68
115
  else
69
116
  @raw_content
@@ -73,7 +120,7 @@ module Nanoc
73
120
  contract C::None => C::Bool
74
121
  def attributes?
75
122
  case @attributes
76
- when Enumerable
123
+ when Set
77
124
  @attributes.any?
78
125
  else
79
126
  @attributes
@@ -136,6 +183,15 @@ module Nanoc
136
183
  end
137
184
  end
138
185
 
186
+ def attribute_keys
187
+ case @attributes
188
+ when Enumerable
189
+ @attributes.map { |a| a.is_a?(Array) ? a.first : a }
190
+ else
191
+ []
192
+ end
193
+ end
194
+
139
195
  contract C::None => Hash
140
196
  def to_h
141
197
  {
@@ -6,11 +6,36 @@ module Nanoc
6
6
  class DependencyStore < ::Nanoc::Core::Store
7
7
  include Nanoc::Core::ContractsSupport
8
8
 
9
- C_ATTR = C::Or[C::IterOf[Symbol], C::Bool]
10
- C_RAW_CONTENT = C::Or[C::IterOf[C::Or[String, Regexp]], C::Bool]
11
- C_KEYWORD_PROPS = C::KeywordArgs[raw_content: C::Optional[C_RAW_CONTENT], attributes: C::Optional[C_ATTR], compiled_content: C::Optional[C::Bool], path: C::Optional[C::Bool]]
9
+ C_RAW_CONTENT =
10
+ C::Or[
11
+ C::ArrayOf[C::Or[String, Regexp]],
12
+ C::Bool
13
+ ]
14
+
15
+ C_ATTR =
16
+ C::Or[
17
+ C::ArrayOf[Symbol],
18
+ C::HashOf[Symbol => C::Any],
19
+ C::Bool
20
+ ]
21
+
22
+ C_KEYWORD_PROPS =
23
+ C::KeywordArgs[
24
+ raw_content: C::Optional[C_RAW_CONTENT],
25
+ attributes: C::Optional[C_ATTR],
26
+ compiled_content: C::Optional[C::Bool],
27
+ path: C::Optional[C::Bool]
28
+ ]
29
+
12
30
  C_OBJ_SRC = Nanoc::Core::Item
13
- C_OBJ_DST = C::Or[Nanoc::Core::Item, Nanoc::Core::Layout, Nanoc::Core::Configuration, Nanoc::Core::IdentifiableCollection]
31
+
32
+ C_OBJ_DST =
33
+ C::Or[
34
+ Nanoc::Core::Item,
35
+ Nanoc::Core::Layout,
36
+ Nanoc::Core::Configuration,
37
+ Nanoc::Core::IdentifiableCollection
38
+ ]
14
39
 
15
40
  attr_reader :items
16
41
  attr_reader :layouts
@@ -116,11 +141,16 @@ module Nanoc
116
141
  src_ref = obj2ref(src)
117
142
  dst_ref = obj2ref(dst)
118
143
 
119
- existing_props = Nanoc::Core::DependencyProps.new(**(@graph.props_for(dst_ref, src_ref) || {}))
144
+ # Convert attributes into key-value pairs, if necessary
145
+ if attributes.is_a?(Hash)
146
+ attributes = attributes.to_a
147
+ end
148
+
149
+ existing_props = @graph.props_for(dst_ref, src_ref)
120
150
  new_props = Nanoc::Core::DependencyProps.new(raw_content: raw_content, attributes: attributes, compiled_content: compiled_content, path: path)
121
- props = existing_props.merge(new_props)
151
+ props = existing_props ? existing_props.merge(new_props) : new_props
122
152
 
123
- @graph.add_edge(dst_ref, src_ref, props: props.to_h)
153
+ @graph.add_edge(dst_ref, src_ref, props: props)
124
154
  end
125
155
 
126
156
  def add_vertex_for(obj)
@@ -162,11 +192,12 @@ module Nanoc
162
192
  refs.map { |r| ref2obj(r) }
163
193
  end
164
194
 
195
+ # TODO: Return not a Hash, but a DependencyProps instead
165
196
  def props_for(from, to)
166
- props = @graph.props_for(obj2ref(from), obj2ref(to)) || {}
197
+ props = @graph.props_for(obj2ref(from), obj2ref(to))
167
198
 
168
- if props.values.any? { |v| v }
169
- props
199
+ if props&.active&.any?
200
+ props.to_h
170
201
  else
171
202
  { raw_content: true, attributes: true, compiled_content: true, path: true }
172
203
  end
@@ -174,7 +205,7 @@ module Nanoc
174
205
 
175
206
  def data
176
207
  {
177
- edges: @graph.edges,
208
+ edges: @graph.edges.map { |arr| [arr[0], arr[1], arr[2].to_h] },
178
209
  vertices: @graph.vertices,
179
210
  }
180
211
  end
@@ -193,8 +224,11 @@ module Nanoc
193
224
  # Load edges
194
225
  new_data[:edges].each do |edge|
195
226
  from_index, to_index, props = *edge
196
- from = from_index && previous_refs[from_index]
197
- to = to_index && previous_refs[to_index]
227
+
228
+ from = from_index && previous_refs[from_index]
229
+ to = to_index && previous_refs[to_index]
230
+ props = Nanoc::Core::DependencyProps.new(**props)
231
+
198
232
  @graph.add_edge(from, to, props: props)
199
233
  end
200
234
 
@@ -16,13 +16,14 @@ module Nanoc
16
16
 
17
17
  C_RAW_CONTENT =
18
18
  C::Or[
19
- C::IterOf[C::Or[String, Regexp]],
19
+ C::ArrayOf[C::Or[String, Regexp]],
20
20
  C::Bool
21
21
  ]
22
22
 
23
23
  C_ATTR =
24
24
  C::Or[
25
- C::IterOf[Symbol],
25
+ C::ArrayOf[Symbol],
26
+ C::HashOf[Symbol => C::Any],
26
27
  C::Bool
27
28
  ]
28
29
 
@@ -90,3 +90,5 @@ module Nanoc
90
90
  end
91
91
  end
92
92
  end
93
+
94
+ Nanoc::Core::Feature.define('where', version: '4.12')
@@ -69,6 +69,34 @@ module Nanoc
69
69
  @objects.find_all(arg).map { |i| view_class.new(i, @context) }
70
70
  end
71
71
 
72
+ # Finds all objects that have the given attribute key/value pair.
73
+ #
74
+ # @example
75
+ #
76
+ # @items.where(kind: 'article')
77
+ # @items.where(kind: 'article', year: 2020)
78
+ #
79
+ # @return [Enumerable]
80
+ def where(**hash)
81
+ unless Nanoc::Core::Feature.enabled?(Nanoc::Core::Feature::WHERE)
82
+ raise(
83
+ Nanoc::Core::TrivialError,
84
+ '#where is experimental, and not yet available unless the corresponding feature flag is turned on. Set the `NANOC_FEATURES` environment variable to `where` to enable its usage. (Alternatively, set the environment variable to `all` to turn on all feature flags.)',
85
+ )
86
+ end
87
+
88
+ @context.dependency_tracker.bounce(_unwrap, attributes: hash)
89
+
90
+ # IDEA: Nanoc could remember (from the previous compilation) how many
91
+ # times #where is called with a given attribute key, and memoize the
92
+ # key-to-identifiers list.
93
+ found_objects = @objects.select do |i|
94
+ hash.all? { |k, v| i.attributes[k] == v }
95
+ end
96
+
97
+ found_objects.map { |i| view_class.new(i, @context) }
98
+ end
99
+
72
100
  # @overload [](string)
73
101
  #
74
102
  # Finds the object whose identifier matches the given string.
@@ -13,6 +13,7 @@ module Nanoc
13
13
 
14
14
  RULES_FOR_ITEM_REP =
15
15
  [
16
+ Rules::ItemAdded,
16
17
  Rules::RulesModified,
17
18
  Rules::ContentModified,
18
19
  Rules::AttributesModified,
@@ -23,6 +24,7 @@ module Nanoc
23
24
 
24
25
  RULES_FOR_LAYOUT =
25
26
  [
27
+ Rules::LayoutAdded,
26
28
  Rules::RulesModified,
27
29
  Rules::ContentModified,
28
30
  Rules::AttributesModified,
@@ -34,16 +36,6 @@ module Nanoc
34
36
  Rules::AttributesModified,
35
37
  ].freeze
36
38
 
37
- RULES_FOR_ITEM_COLLECTION =
38
- [
39
- Rules::ItemCollectionExtended,
40
- ].freeze
41
-
42
- RULES_FOR_LAYOUT_COLLECTION =
43
- [
44
- Rules::LayoutCollectionExtended,
45
- ].freeze
46
-
47
39
  C_OBJ_MAYBE_REP = C::Or[Nanoc::Core::Item, Nanoc::Core::ItemRep, Nanoc::Core::Configuration, Nanoc::Core::Layout, Nanoc::Core::ItemCollection, Nanoc::Core::LayoutCollection]
48
40
 
49
41
  contract C::KeywordArgs[outdatedness_checker: OutdatednessChecker, reps: Nanoc::Core::ItemRepRepo] => C::Any
@@ -67,10 +59,10 @@ module Nanoc
67
59
  apply_rules(RULES_FOR_LAYOUT, obj)
68
60
  when Nanoc::Core::Configuration
69
61
  apply_rules(RULES_FOR_CONFIG, obj)
70
- when Nanoc::Core::ItemCollection
71
- apply_rules(RULES_FOR_ITEM_COLLECTION, obj)
72
- when Nanoc::Core::LayoutCollection
73
- apply_rules(RULES_FOR_LAYOUT_COLLECTION, obj)
62
+ when Nanoc::Core::ItemCollection, Nanoc::Core::LayoutCollection
63
+ # Collections are never outdated. Objects inside them might be,
64
+ # however.
65
+ apply_rules([], obj)
74
66
  else
75
67
  raise Nanoc::Core::Errors::InternalInconsistency, "do not know how to check outdatedness of #{obj.inspect}"
76
68
  end
@@ -190,31 +182,111 @@ module Nanoc
190
182
 
191
183
  contract Nanoc::Core::Dependency => C::Bool
192
184
  def dependency_causes_outdatedness?(dependency)
193
- return true if dependency.from.nil?
194
-
195
- status = basic.outdatedness_status_for(dependency.from)
185
+ case dependency.from
186
+ when nil
187
+ true
188
+ when Nanoc::Core::ItemCollection, Nanoc::Core::LayoutCollection
189
+ all_objects = dependency.from
190
+
191
+ raw_content_prop_causes_outdatedness?(all_objects, dependency.props.raw_content) ||
192
+ attributes_prop_causes_outdatedness?(all_objects, dependency.props.attributes)
193
+ else
194
+ status = basic.outdatedness_status_for(dependency.from)
196
195
 
197
- active = status.props.active & dependency.props.active
198
- active.delete(:attributes) if attributes_unaffected?(status, dependency)
199
- active.delete(:raw_content) if raw_content_unaffected?(status, dependency)
196
+ active = status.props.active & dependency.props.active
197
+ active.delete(:attributes) if attributes_unaffected?(status, dependency)
200
198
 
201
- active.any?
199
+ active.any?
200
+ end
202
201
  end
203
202
 
204
203
  def attributes_unaffected?(status, dependency)
205
204
  reason = status.reasons.find { |r| r.is_a?(Nanoc::Core::OutdatednessReasons::AttributesModified) }
206
- reason && dependency.props.attributes.is_a?(Enumerable) && (dependency.props.attributes & reason.attributes).empty?
205
+ reason && dependency.props.attribute_keys.any? && (dependency.props.attribute_keys & reason.attributes).empty?
207
206
  end
208
207
 
209
- def raw_content_unaffected?(status, dependency)
210
- reason = status.reasons.find { |r| r.is_a?(Nanoc::Core::OutdatednessReasons::DocumentCollectionExtended) }
211
- if reason.nil?
212
- false
213
- elsif !dependency.props.raw_content.is_a?(Enumerable)
214
- false
215
- else
216
- patterns = dependency.props.raw_content.map { |r| Nanoc::Core::Pattern.from(r) }
217
- patterns.none? { |pat| reason.objects.any? { |obj| pat.match?(obj.identifier) } }
208
+ def raw_content_prop_causes_outdatedness?(objects, raw_content_prop)
209
+ return false unless raw_content_prop
210
+
211
+ matching_objects =
212
+ case raw_content_prop
213
+ when true
214
+ # If the `raw_content` dependency prop is `true`, then this is a
215
+ # dependency on all *objects* (items or layouts).
216
+ objects
217
+ when Enumerable
218
+ # If the `raw_content` dependency prop is a collection, then this
219
+ # is a dependency on specific objects, given by the patterns.
220
+ patterns = raw_content_prop.map { |r| Nanoc::Core::Pattern.from(r) }
221
+ patterns.flat_map { |pat| objects.select { |obj| pat.match?(obj.identifier) } }
222
+ else
223
+ raise(
224
+ Nanoc::Core::Errors::InternalInconsistency,
225
+ "Unexpected type of raw_content: #{raw_content_prop.inspect}",
226
+ )
227
+ end
228
+
229
+ # For all objects matching the `raw_content` dependency prop:
230
+ # If the object is outdated because it is newly added,
231
+ # then this dependency causes outdatedness.
232
+ #
233
+ # Note that these objects might be modified but *not* newly added,
234
+ # in which case this dependency will *not* cause outdatedness.
235
+ # However, when the object is used later (e.g. attributes are
236
+ # accessed), then another dependency will exist that will cause
237
+ # outdatedness.
238
+ matching_objects.any? do |obj|
239
+ status = basic.outdatedness_status_for(obj)
240
+ status.reasons.any? { |r| Nanoc::Core::OutdatednessReasons::DocumentAdded == r }
241
+ end
242
+ end
243
+
244
+ def attributes_prop_causes_outdatedness?(objects, attributes_prop)
245
+ return false unless attributes_prop
246
+
247
+ unless attributes_prop.is_a?(Set)
248
+ raise(
249
+ Nanoc::Core::Errors::InternalInconsistency,
250
+ 'expected attributes_prop to be a Set',
251
+ )
252
+ end
253
+
254
+ pairs = attributes_prop.select { |a| a.is_a?(Array) }.to_h
255
+
256
+ unless pairs.any?
257
+ raise(
258
+ Nanoc::Core::Errors::InternalInconsistency,
259
+ 'expected attributes_prop not to be empty',
260
+ )
261
+ end
262
+
263
+ dep_checksums = pairs.transform_values { |value| Nanoc::Core::Checksummer.calc(value) }
264
+
265
+ objects.any? do |object|
266
+ # Find old and new attribute checksums for the object
267
+ old_object_checksums = checksum_store.attributes_checksum_for(object)
268
+ next false unless old_object_checksums
269
+
270
+ new_object_checksums = checksums.attributes_checksum_for(object)
271
+
272
+ # Ignore any attribute not mentioned in the dependency
273
+ old_object_checksums = old_object_checksums.select { |k, _v| dep_checksums.key?(k) }
274
+ new_object_checksums = new_object_checksums.select { |k, _v| dep_checksums.key?(k) }
275
+
276
+ dep_checksums.any? do |key, dep_value|
277
+ # Get old and new checksum for this particular attribute
278
+ old_value = old_object_checksums[key]
279
+ new_value = new_object_checksums[key]
280
+
281
+ # If either the old or new vale match the value in the dependency,
282
+ # then a potential change is relevant to us, and can cause
283
+ # outdatedness.
284
+ is_match = [old_value, new_value].include?(dep_value)
285
+
286
+ is_changed = old_value != new_value
287
+
288
+ is_match && is_changed
289
+ end
218
290
  end
219
291
  end
220
292
  end
@@ -18,6 +18,10 @@ module Nanoc
18
18
  # @param [String] message The descriptive message for this outdatedness
19
19
  # reason
20
20
  def initialize(message, props = Nanoc::Core::DependencyProps.new)
21
+ # TODO: Replace `DependencyProps` with its own `OutdatednessProps`
22
+ # type. For `OutdatednessProps`, the only values are true/false;
23
+ # giving a collection for `raw_content` makes no sense (anymore).
24
+
21
25
  @message = message
22
26
  @props = props
23
27
  end
@@ -42,30 +46,16 @@ module Nanoc
42
46
  Nanoc::Core::DependencyProps.new(compiled_content: true, path: true),
43
47
  )
44
48
 
49
+ DocumentAdded = Generic.new(
50
+ 'The item or layout is newly added to the site.',
51
+ Nanoc::Core::DependencyProps.new, # NOTE: empty props, because they’re not relevant
52
+ )
53
+
45
54
  ContentModified = Generic.new(
46
55
  'The content of this item has been modified since the last time the site was compiled.',
47
56
  Nanoc::Core::DependencyProps.new(raw_content: true, compiled_content: true),
48
57
  )
49
58
 
50
- class DocumentCollectionExtended < Generic
51
- attr_reader :objects
52
-
53
- def initialize(objects)
54
- super(
55
- 'New items/layouts have been added to the site.',
56
- Nanoc::Core::DependencyProps.new(raw_content: true),
57
- )
58
-
59
- @objects = objects
60
- end
61
- end
62
-
63
- class ItemCollectionExtended < DocumentCollectionExtended
64
- end
65
-
66
- class LayoutCollectionExtended < DocumentCollectionExtended
67
- end
68
-
69
59
  class AttributesModified < Generic
70
60
  attr_reader :attributes
71
61
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ module OutdatednessRules
6
+ class ItemAdded < Nanoc::Core::OutdatednessRule
7
+ affects_props :raw_content
8
+
9
+ contract Nanoc::Core::ItemRep, C::Named['Nanoc::Core::OutdatednessChecker'] => C::Maybe[Nanoc::Core::OutdatednessReasons::Generic]
10
+ def apply(obj, outdatedness_checker)
11
+ if outdatedness_checker.dependency_store.new_items.include?(obj.item)
12
+ Nanoc::Core::OutdatednessReasons::DocumentAdded
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nanoc
4
+ module Core
5
+ module OutdatednessRules
6
+ class LayoutAdded < Nanoc::Core::OutdatednessRule
7
+ affects_props :raw_content
8
+
9
+ contract Nanoc::Core::Layout, C::Named['Nanoc::Core::OutdatednessChecker'] => C::Maybe[Nanoc::Core::OutdatednessReasons::Generic]
10
+ def apply(obj, outdatedness_checker)
11
+ if outdatedness_checker.dependency_store.new_layouts.include?(obj)
12
+ Nanoc::Core::OutdatednessReasons::DocumentAdded
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -22,6 +22,10 @@ module Nanoc
22
22
  props: @props.merge(reason.props),
23
23
  )
24
24
  end
25
+
26
+ def inspect
27
+ "<#{self.class} reasons=#{@reasons.inspect} props=#{@props.inspect}>"
28
+ end
25
29
  end
26
30
  end
27
31
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Nanoc
4
4
  module Core
5
- VERSION = '4.12.8'
5
+ VERSION = '4.12.9'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.8
4
+ version: 4.12.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-03 00:00:00.000000000 Z
11
+ date: 2022-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -261,8 +261,8 @@ files:
261
261
  - lib/nanoc/core/outdatedness_rules/attributes_modified.rb
262
262
  - lib/nanoc/core/outdatedness_rules/code_snippets_modified.rb
263
263
  - lib/nanoc/core/outdatedness_rules/content_modified.rb
264
- - lib/nanoc/core/outdatedness_rules/item_collection_extended.rb
265
- - lib/nanoc/core/outdatedness_rules/layout_collection_extended.rb
264
+ - lib/nanoc/core/outdatedness_rules/item_added.rb
265
+ - lib/nanoc/core/outdatedness_rules/layout_added.rb
266
266
  - lib/nanoc/core/outdatedness_rules/not_written.rb
267
267
  - lib/nanoc/core/outdatedness_rules/rules_modified.rb
268
268
  - lib/nanoc/core/outdatedness_rules/uses_always_outdated_filter.rb
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Core
5
- module OutdatednessRules
6
- class ItemCollectionExtended < Nanoc::Core::OutdatednessRule
7
- affects_props :raw_content
8
-
9
- contract Nanoc::Core::ItemCollection, C::Named['Nanoc::Core::OutdatednessChecker'] => C::Maybe[Nanoc::Core::OutdatednessReasons::Generic]
10
- def apply(_obj, outdatedness_checker)
11
- new_items = outdatedness_checker.dependency_store.new_items
12
-
13
- if new_items.any?
14
- Nanoc::Core::OutdatednessReasons::ItemCollectionExtended.new(new_items)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nanoc
4
- module Core
5
- module OutdatednessRules
6
- class LayoutCollectionExtended < Nanoc::Core::OutdatednessRule
7
- affects_props :raw_content
8
-
9
- contract Nanoc::Core::LayoutCollection, C::Named['Nanoc::Core::OutdatednessChecker'] => C::Maybe[Nanoc::Core::OutdatednessReasons::Generic]
10
- def apply(_obj, outdatedness_checker)
11
- new_layouts = outdatedness_checker.dependency_store.new_layouts
12
-
13
- if new_layouts.any?
14
- Nanoc::Core::OutdatednessReasons::LayoutCollectionExtended.new(new_layouts)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end