nanoc-core 4.14.6 → 4.14.8
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/lib/nanoc/core/action_sequence.rb +1 -1
- data/lib/nanoc/core/action_sequence_builder.rb +12 -4
- data/lib/nanoc/core/action_sequence_store.rb +8 -5
- data/lib/nanoc/core/assertions.rb +12 -2
- data/lib/nanoc/core/basic_outdatedness_checker.rb +26 -10
- data/lib/nanoc/core/binary_compiled_content_cache.rb +24 -10
- data/lib/nanoc/core/checksum_collection.rb +7 -2
- data/lib/nanoc/core/checksum_store.rb +26 -9
- data/lib/nanoc/core/checksummer.rb +63 -32
- data/lib/nanoc/core/code_snippet.rb +1 -1
- data/lib/nanoc/core/compilation_stages/build_reps.rb +7 -2
- data/lib/nanoc/core/compilation_stages/calculate_checksums.rb +2 -0
- data/lib/nanoc/core/compilation_stages/cleanup.rb +8 -2
- data/lib/nanoc/core/compilation_stages/compile_reps.rb +78 -36
- data/lib/nanoc/core/compilation_stages/determine_outdatedness.rb +2 -0
- data/lib/nanoc/core/compilation_stages/forget_outdated_dependencies.rb +5 -1
- data/lib/nanoc/core/compilation_stages/load_stores.rb +6 -1
- data/lib/nanoc/core/compilation_stages/postprocess.rb +2 -0
- data/lib/nanoc/core/compilation_stages/preprocess.rb +12 -3
- data/lib/nanoc/core/compilation_stages/prune.rb +6 -1
- data/lib/nanoc/core/compilation_stages/store_post_compilation_state.rb +2 -0
- data/lib/nanoc/core/compilation_stages/store_pre_compilation_state.rb +6 -1
- data/lib/nanoc/core/compiled_content_cache.rb +7 -2
- data/lib/nanoc/core/compiled_content_repo.rb +13 -5
- data/lib/nanoc/core/compiler.rb +12 -3
- data/lib/nanoc/core/compiler_loader.rb +13 -4
- data/lib/nanoc/core/config_loader.rb +14 -4
- data/lib/nanoc/core/configuration.rb +36 -15
- data/lib/nanoc/core/content.rb +5 -1
- data/lib/nanoc/core/context.rb +4 -5
- data/lib/nanoc/core/contracts_support.rb +26 -8
- data/lib/nanoc/core/core_ext/hash.rb +12 -2
- data/lib/nanoc/core/data_source.rb +22 -6
- data/lib/nanoc/core/dependency.rb +8 -2
- data/lib/nanoc/core/dependency_props.rb +27 -8
- data/lib/nanoc/core/dependency_store.rb +55 -22
- data/lib/nanoc/core/dependency_tracker.rb +20 -4
- data/lib/nanoc/core/directed_graph.rb +27 -64
- data/lib/nanoc/core/document.rb +4 -1
- data/lib/nanoc/core/errors.rb +45 -12
- data/lib/nanoc/core/executor.rb +26 -9
- data/lib/nanoc/core/feature.rb +2 -1
- data/lib/nanoc/core/filter.rb +27 -11
- data/lib/nanoc/core/identifiable_collection.rb +2 -1
- data/lib/nanoc/core/identifier.rb +23 -8
- data/lib/nanoc/core/in_memory_data_source.rb +3 -1
- data/lib/nanoc/core/item.rb +1 -1
- data/lib/nanoc/core/item_collection.rb +2 -2
- data/lib/nanoc/core/item_rep.rb +1 -1
- data/lib/nanoc/core/item_rep_builder.rb +14 -5
- data/lib/nanoc/core/item_rep_router.rb +27 -13
- data/lib/nanoc/core/item_rep_writer.rb +28 -5
- data/lib/nanoc/core/layout.rb +1 -1
- data/lib/nanoc/core/layout_collection.rb +2 -2
- data/lib/nanoc/core/mutable_document_view_mixin.rb +3 -6
- data/lib/nanoc/core/outdatedness_checker.rb +170 -95
- data/lib/nanoc/core/outdatedness_reasons.rb +45 -16
- data/lib/nanoc/core/outdatedness_rules/attributes_modified.rb +24 -10
- data/lib/nanoc/core/outdatedness_rules/item_added.rb +9 -4
- data/lib/nanoc/core/outdatedness_rules/layout_added.rb +9 -4
- data/lib/nanoc/core/outdatedness_rules/not_written.rb +7 -2
- data/lib/nanoc/core/outdatedness_rules/rules_modified.rb +14 -6
- data/lib/nanoc/core/outdatedness_rules/uses_always_outdated_filter.rb +1 -1
- data/lib/nanoc/core/outdatedness_store.rb +7 -1
- data/lib/nanoc/core/pattern.rb +4 -1
- data/lib/nanoc/core/prefixed_data_source.rb +6 -2
- data/lib/nanoc/core/processing_actions/filter.rb +2 -0
- data/lib/nanoc/core/processing_actions/layout.rb +2 -0
- data/lib/nanoc/core/processing_actions/snapshot.rb +12 -3
- data/lib/nanoc/core/pruner.rb +11 -3
- data/lib/nanoc/core/regexp_pattern.rb +1 -1
- data/lib/nanoc/core/site.rb +10 -4
- data/lib/nanoc/core/site_loader.rb +25 -17
- data/lib/nanoc/core/store.rb +33 -6
- data/lib/nanoc/core/string_pattern.rb +1 -1
- data/lib/nanoc/core/textual_compiled_content_cache.rb +60 -5
- data/lib/nanoc/core/textual_content.rb +4 -1
- data/lib/nanoc/core/version.rb +1 -1
- data/lib/nanoc/core/view_context_for_compilation.rb +6 -2
- data/lib/nanoc/core/views/basic_item_rep_collection_view.rb +11 -4
- data/lib/nanoc/core/views/basic_item_rep_view.rb +9 -2
- data/lib/nanoc/core/views/basic_item_view.rb +17 -9
- data/lib/nanoc/core/views/compilation_item_rep_view.rb +12 -4
- data/lib/nanoc/core/views/compilation_item_view.rb +3 -1
- data/lib/nanoc/core/views/identifiable_collection_view.rb +17 -5
- data/lib/nanoc/core/views/mutable_item_collection_view.rb +5 -2
- data/lib/nanoc/core/views/mutable_layout_collection_view.rb +5 -2
- data/lib/nanoc/core/views/post_compile_item_view.rb +3 -1
- data/lib/nanoc/core.rb +4 -4
- metadata +3 -9
- data/lib/nanoc/core/compilation_phases/abstract.rb +0 -48
- data/lib/nanoc/core/compilation_phases/cache.rb +0 -28
- data/lib/nanoc/core/compilation_phases/mark_done.rb +0 -23
- data/lib/nanoc/core/compilation_phases/notify.rb +0 -22
- data/lib/nanoc/core/compilation_phases/recalculate.rb +0 -59
- data/lib/nanoc/core/compilation_phases/write.rb +0 -31
data/lib/nanoc/core/errors.rb
CHANGED
|
@@ -20,7 +20,10 @@ module Nanoc
|
|
|
20
20
|
def initialize(item_rep, snapshot)
|
|
21
21
|
@item_rep = item_rep
|
|
22
22
|
@snapshot = snapshot
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
super(
|
|
25
|
+
"The “#{item_rep.inspect}” item rep does not have a snapshot “#{snapshot.inspect}”"
|
|
26
|
+
)
|
|
24
27
|
end
|
|
25
28
|
end
|
|
26
29
|
|
|
@@ -30,6 +33,8 @@ module Nanoc
|
|
|
30
33
|
attr_reader :item_rep
|
|
31
34
|
|
|
32
35
|
def initialize(wrapped, item_rep)
|
|
36
|
+
super(wrapped.message)
|
|
37
|
+
|
|
33
38
|
@wrapped = wrapped
|
|
34
39
|
@item_rep = item_rep
|
|
35
40
|
end
|
|
@@ -45,7 +50,9 @@ module Nanoc
|
|
|
45
50
|
# @param [String] data_source_name The data source name for which no
|
|
46
51
|
# data source could be found
|
|
47
52
|
def initialize(data_source_name)
|
|
48
|
-
super(
|
|
53
|
+
super(
|
|
54
|
+
'The data source specified in the site’s configuration file, ' \
|
|
55
|
+
"“#{data_source_name}”, does not exist.")
|
|
49
56
|
end
|
|
50
57
|
end
|
|
51
58
|
|
|
@@ -65,7 +72,10 @@ module Nanoc
|
|
|
65
72
|
@rep = rep
|
|
66
73
|
@snapshot_name = snapshot_name
|
|
67
74
|
|
|
68
|
-
super(
|
|
75
|
+
super(
|
|
76
|
+
'The current item cannot be compiled yet because of an ' \
|
|
77
|
+
"unmet dependency on the “#{rep.item.identifier}” item " \
|
|
78
|
+
"(rep “#{rep.name}”, snapshot “#{snapshot_name}”).")
|
|
69
79
|
end
|
|
70
80
|
end
|
|
71
81
|
|
|
@@ -79,9 +89,9 @@ module Nanoc
|
|
|
79
89
|
cycle.each.with_index do |r, i|
|
|
80
90
|
msg_bits << " (#{i + 1}) item #{r.item.identifier}, rep #{r.name.inspect}, uses compiled content of"
|
|
81
91
|
end
|
|
82
|
-
msg_bits <<
|
|
92
|
+
msg_bits << "#{msg_bits.pop} (1)"
|
|
83
93
|
|
|
84
|
-
super(msg_bits.map { |x| x
|
|
94
|
+
super(msg_bits.map { |x| "#{x}\n" }.join)
|
|
85
95
|
end
|
|
86
96
|
end
|
|
87
97
|
|
|
@@ -92,22 +102,31 @@ module Nanoc
|
|
|
92
102
|
# @param [String] layout_identifier The identifier of the layout for
|
|
93
103
|
# which the filter could not be determined
|
|
94
104
|
def initialize(layout_identifier)
|
|
95
|
-
super(
|
|
105
|
+
super(
|
|
106
|
+
"The filter to be used for the “#{layout_identifier}” layout " \
|
|
107
|
+
'could not be determined. Make sure the layout does have a filter.')
|
|
96
108
|
end
|
|
97
109
|
end
|
|
98
110
|
|
|
99
111
|
# Error that is raised when the compiled content of a binary item is attempted to be accessed.
|
|
100
112
|
class CannotGetCompiledContentOfBinaryItem < ::Nanoc::Core::Error
|
|
101
|
-
# @param [Nanoc::Core::ItemRep] rep The binary item representation
|
|
113
|
+
# @param [Nanoc::Core::ItemRep] rep The binary item representation
|
|
114
|
+
# whose compiled content was attempted to be accessed
|
|
102
115
|
def initialize(rep)
|
|
103
|
-
super(
|
|
116
|
+
super(
|
|
117
|
+
'You cannot access the compiled content of a binary item ' \
|
|
118
|
+
"representation (but you can access the path). The offending item rep is #{rep}.")
|
|
104
119
|
end
|
|
105
120
|
end
|
|
106
121
|
|
|
107
122
|
# Error that is raised when attempting to call #parent or #children on an item with a legacy identifier.
|
|
108
123
|
class CannotGetParentOrChildrenOfNonLegacyItem < ::Nanoc::Core::Error
|
|
109
124
|
def initialize(identifier)
|
|
110
|
-
super(
|
|
125
|
+
super(
|
|
126
|
+
'You cannot get the parent or children of an item that has a ' \
|
|
127
|
+
"“full” identifier (#{identifier}). Getting the parent or " \
|
|
128
|
+
'children of an item is only possible for items that have a ' \
|
|
129
|
+
'legacy identifier.')
|
|
111
130
|
end
|
|
112
131
|
end
|
|
113
132
|
|
|
@@ -126,7 +145,12 @@ module Nanoc
|
|
|
126
145
|
# @param [Nanoc::Core::ItemRep] rep The item representation that was attempted
|
|
127
146
|
# to be laid out
|
|
128
147
|
def initialize(rep)
|
|
129
|
-
super(
|
|
148
|
+
super(
|
|
149
|
+
"The “#{rep.item.identifier}” item (rep “#{rep.name}”) cannot " \
|
|
150
|
+
'be laid out because it is a binary item. If you are getting ' \
|
|
151
|
+
'this error for an item that should be textual instead of ' \
|
|
152
|
+
'binary, make sure that its extension is included in the ' \
|
|
153
|
+
'text_extensions array in the site configuration.')
|
|
130
154
|
end
|
|
131
155
|
end
|
|
132
156
|
|
|
@@ -138,7 +162,10 @@ module Nanoc
|
|
|
138
162
|
#
|
|
139
163
|
# @param [Class] filter_class The filter class that was used
|
|
140
164
|
def initialize(rep, filter_class)
|
|
141
|
-
super(
|
|
165
|
+
super(
|
|
166
|
+
"The “#{filter_class.inspect}” filter cannot be used to filter " \
|
|
167
|
+
"the “#{rep.item.identifier}” item (rep “#{rep.name}”), because " \
|
|
168
|
+
'textual filters cannot be used on binary items.')
|
|
142
169
|
end
|
|
143
170
|
end
|
|
144
171
|
|
|
@@ -150,7 +177,13 @@ module Nanoc
|
|
|
150
177
|
#
|
|
151
178
|
# @param [Class] filter_class The filter class that was used
|
|
152
179
|
def initialize(rep, filter_class)
|
|
153
|
-
super(
|
|
180
|
+
super(
|
|
181
|
+
"The “#{filter_class.inspect}” filter cannot be used to filter " \
|
|
182
|
+
"the “#{rep.item.identifier}” item (rep “#{rep.name}”), because " \
|
|
183
|
+
'binary filters cannot be used on textual items. If you are ' \
|
|
184
|
+
'getting this error for an item that should be textual instead ' \
|
|
185
|
+
'of binary, make sure that its extension is included in the ' \
|
|
186
|
+
'text_extensions array in the site configuration.')
|
|
154
187
|
end
|
|
155
188
|
end
|
|
156
189
|
|
data/lib/nanoc/core/executor.rb
CHANGED
|
@@ -13,7 +13,9 @@ module Nanoc
|
|
|
13
13
|
filter = filter_for_filtering(filter_name)
|
|
14
14
|
|
|
15
15
|
begin
|
|
16
|
-
Nanoc::Core::NotificationCenter.post(
|
|
16
|
+
Nanoc::Core::NotificationCenter.post(
|
|
17
|
+
:filtering_started, @rep, filter_name
|
|
18
|
+
)
|
|
17
19
|
|
|
18
20
|
# Run filter
|
|
19
21
|
last = @compilation_context.compiled_content_repo.get_current(@rep)
|
|
@@ -30,16 +32,20 @@ module Nanoc
|
|
|
30
32
|
# Store
|
|
31
33
|
@compilation_context.compiled_content_repo.set_current(@rep, last)
|
|
32
34
|
ensure
|
|
33
|
-
Nanoc::Core::NotificationCenter.post(
|
|
35
|
+
Nanoc::Core::NotificationCenter.post(
|
|
36
|
+
:filtering_ended, @rep, filter_name
|
|
37
|
+
)
|
|
34
38
|
end
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
def layout(layout_identifier, extra_filter_args = nil)
|
|
38
42
|
layout = find_layout(layout_identifier)
|
|
39
|
-
filter_name_and_args =
|
|
43
|
+
filter_name_and_args =
|
|
44
|
+
@compilation_context.filter_name_and_args_for_layout(layout)
|
|
40
45
|
filter_name = filter_name_and_args.name
|
|
41
46
|
if filter_name.nil?
|
|
42
|
-
raise Nanoc::Core::Errors::CannotDetermineFilter
|
|
47
|
+
raise Nanoc::Core::Errors::CannotDetermineFilter
|
|
48
|
+
.new(layout_identifier)
|
|
43
49
|
end
|
|
44
50
|
|
|
45
51
|
filter_args = filter_name_and_args.args
|
|
@@ -48,7 +54,9 @@ module Nanoc
|
|
|
48
54
|
|
|
49
55
|
# Check whether item can be laid out
|
|
50
56
|
last = @compilation_context.compiled_content_repo.get_current(@rep)
|
|
51
|
-
|
|
57
|
+
if last.binary?
|
|
58
|
+
raise Nanoc::Core::Errors::CannotLayoutBinaryItem.new(@rep)
|
|
59
|
+
end
|
|
52
60
|
|
|
53
61
|
# Create filter
|
|
54
62
|
klass = Nanoc::Core::Filter.named!(filter_name)
|
|
@@ -59,7 +67,9 @@ module Nanoc
|
|
|
59
67
|
@dependency_tracker.bounce(layout, raw_content: true)
|
|
60
68
|
|
|
61
69
|
begin
|
|
62
|
-
Nanoc::Core::NotificationCenter.post(
|
|
70
|
+
Nanoc::Core::NotificationCenter.post(
|
|
71
|
+
:filtering_started, @rep, filter_name
|
|
72
|
+
)
|
|
63
73
|
|
|
64
74
|
# Layout
|
|
65
75
|
content = layout.content
|
|
@@ -70,14 +80,21 @@ module Nanoc
|
|
|
70
80
|
last = Nanoc::Core::TextualContent.new(res).tap(&:freeze)
|
|
71
81
|
@compilation_context.compiled_content_repo.set_current(@rep, last)
|
|
72
82
|
ensure
|
|
73
|
-
Nanoc::Core::NotificationCenter.post(
|
|
83
|
+
Nanoc::Core::NotificationCenter.post(
|
|
84
|
+
:filtering_ended, @rep, filter_name
|
|
85
|
+
)
|
|
74
86
|
end
|
|
75
87
|
end
|
|
76
88
|
|
|
77
89
|
def snapshot(snapshot_name)
|
|
78
90
|
last = @compilation_context.compiled_content_repo.get_current(@rep)
|
|
79
|
-
@compilation_context.compiled_content_repo.set(
|
|
80
|
-
|
|
91
|
+
@compilation_context.compiled_content_repo.set(
|
|
92
|
+
@rep, snapshot_name,
|
|
93
|
+
last
|
|
94
|
+
)
|
|
95
|
+
Nanoc::Core::NotificationCenter.post(
|
|
96
|
+
:snapshot_created, @rep, snapshot_name
|
|
97
|
+
)
|
|
81
98
|
end
|
|
82
99
|
|
|
83
100
|
def assigns
|
data/lib/nanoc/core/feature.rb
CHANGED
data/lib/nanoc/core/filter.rb
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Nanoc
|
|
4
4
|
module Core
|
|
5
|
-
# Nanoc::Core::Filter is responsible for filtering items. It is the
|
|
6
|
-
# for all textual filters.
|
|
5
|
+
# Nanoc::Core::Filter is responsible for filtering items. It is the
|
|
6
|
+
# superclass for all textual filters.
|
|
7
7
|
#
|
|
8
8
|
# A filter instance should only be used once. Filters should not be reused
|
|
9
9
|
# since they store state.
|
|
@@ -48,7 +48,10 @@ module Nanoc
|
|
|
48
48
|
|
|
49
49
|
contract C::Or[String, Symbol], String => self
|
|
50
50
|
def initialize(filter_name, output_filename)
|
|
51
|
-
super(
|
|
51
|
+
super(
|
|
52
|
+
"The #{filter_name.inspect} filter did not write anything to " \
|
|
53
|
+
"the required output file, #{output_filename}.",
|
|
54
|
+
)
|
|
52
55
|
end
|
|
53
56
|
end
|
|
54
57
|
|
|
@@ -57,7 +60,10 @@ module Nanoc
|
|
|
57
60
|
|
|
58
61
|
contract C::Or[String, Symbol] => self
|
|
59
62
|
def initialize(filter_name)
|
|
60
|
-
super(
|
|
63
|
+
super(
|
|
64
|
+
"The #{filter_name.inspect} filter returned nil, but is " \
|
|
65
|
+
'required to return a String.',
|
|
66
|
+
)
|
|
61
67
|
end
|
|
62
68
|
end
|
|
63
69
|
|
|
@@ -130,8 +136,8 @@ module Nanoc
|
|
|
130
136
|
@always_outdated || false
|
|
131
137
|
end
|
|
132
138
|
|
|
133
|
-
# Marks this filter as always causing the item rep to be outdated. This
|
|
134
|
-
# that cannot do dependency tracking properly.
|
|
139
|
+
# Marks this filter as always causing the item rep to be outdated. This
|
|
140
|
+
# is useful for filters that cannot do dependency tracking properly.
|
|
135
141
|
#
|
|
136
142
|
# @return [void]
|
|
137
143
|
def always_outdated
|
|
@@ -140,11 +146,14 @@ module Nanoc
|
|
|
140
146
|
|
|
141
147
|
# @overload requires(*requires)
|
|
142
148
|
# Sets the required libraries for this filter.
|
|
143
|
-
# @param [Array<String>] requires A list of library names that are
|
|
149
|
+
# @param [Array<String>] requires A list of library names that are
|
|
150
|
+
# required
|
|
144
151
|
# @return [void]
|
|
152
|
+
#
|
|
145
153
|
# @overload requires
|
|
146
154
|
# Returns the required libraries for this filter.
|
|
147
|
-
# @return [Enumerable<String>] This filter’s list of library names
|
|
155
|
+
# @return [Enumerable<String>] This filter’s list of library names
|
|
156
|
+
# that are required
|
|
148
157
|
def requires(*requires)
|
|
149
158
|
if requires.empty?
|
|
150
159
|
@requires || []
|
|
@@ -203,17 +212,24 @@ module Nanoc
|
|
|
203
212
|
# value is undefined; if the filter outputs textual content, the return
|
|
204
213
|
# value will be the filtered content.
|
|
205
214
|
def run(content_or_filename, params = {}) # rubocop:disable Lint/UnusedMethodArgument
|
|
206
|
-
raise NotImplementedError.new(
|
|
215
|
+
raise NotImplementedError.new(
|
|
216
|
+
'Nanoc::Core::Filter subclasses must implement #run',
|
|
217
|
+
)
|
|
207
218
|
end
|
|
208
219
|
|
|
209
220
|
def verify(res)
|
|
210
221
|
if self.class.to_binary?
|
|
211
222
|
unless File.file?(output_filename)
|
|
212
|
-
raise Nanoc::Core::Filter::OutputNotWrittenError.new(
|
|
223
|
+
raise Nanoc::Core::Filter::OutputNotWrittenError.new(
|
|
224
|
+
self.class.identifier,
|
|
225
|
+
output_filename,
|
|
226
|
+
)
|
|
213
227
|
end
|
|
214
228
|
elsif self.class.to_text?
|
|
215
229
|
unless res
|
|
216
|
-
raise Nanoc::Core::Filter::FilterReturnedNilError.new(
|
|
230
|
+
raise Nanoc::Core::Filter::FilterReturnedNilError.new(
|
|
231
|
+
self.class.identifier,
|
|
232
|
+
)
|
|
217
233
|
end
|
|
218
234
|
end
|
|
219
235
|
end
|
|
@@ -17,7 +17,8 @@ module Nanoc
|
|
|
17
17
|
raise 'IdentifiableCollection is abstract and cannot be instantiated'
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# contract C::Or[Hash, C::Named['Nanoc::Core::Configuration']],
|
|
20
|
+
# contract C::Or[Hash, C::Named['Nanoc::Core::Configuration']],
|
|
21
|
+
# C::IterOf[C::RespondTo[:identifier]], C::Maybe[String] => C::Any
|
|
21
22
|
def initialize_basic(config, objects = [], name = nil)
|
|
22
23
|
@config = config
|
|
23
24
|
@objects = Immutable::Vector.new(objects)
|
|
@@ -8,37 +8,48 @@ module Nanoc
|
|
|
8
8
|
|
|
9
9
|
class InvalidIdentifierError < ::Nanoc::Core::Error
|
|
10
10
|
def initialize(string)
|
|
11
|
-
super(
|
|
11
|
+
super(
|
|
12
|
+
'Invalid identifier (does not start with a slash): ' \
|
|
13
|
+
"#{string.inspect}")
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
class InvalidFullIdentifierError < ::Nanoc::Core::Error
|
|
16
18
|
def initialize(string)
|
|
17
|
-
super(
|
|
19
|
+
super(
|
|
20
|
+
'Invalid full identifier (ends with a slash): ' \
|
|
21
|
+
"#{string.inspect}")
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
class InvalidTypeError < ::Nanoc::Core::Error
|
|
22
26
|
def initialize(type)
|
|
23
|
-
super(
|
|
27
|
+
super(
|
|
28
|
+
"Invalid type for identifier: #{type.inspect} " \
|
|
29
|
+
'(can be :full or :legacy)')
|
|
24
30
|
end
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
class InvalidPrefixError < ::Nanoc::Core::Error
|
|
28
34
|
def initialize(string)
|
|
29
|
-
super(
|
|
35
|
+
super(
|
|
36
|
+
'Invalid prefix (does not start with a slash): ' \
|
|
37
|
+
"#{string.inspect}")
|
|
30
38
|
end
|
|
31
39
|
end
|
|
32
40
|
|
|
33
41
|
class UnsupportedLegacyOperationError < ::Nanoc::Core::Error
|
|
34
42
|
def initialize
|
|
35
|
-
super(
|
|
43
|
+
super(
|
|
44
|
+
'Cannot use this method on legacy identifiers')
|
|
36
45
|
end
|
|
37
46
|
end
|
|
38
47
|
|
|
39
48
|
class NonCoercibleObjectError < ::Nanoc::Core::Error
|
|
40
49
|
def initialize(obj)
|
|
41
|
-
super(
|
|
50
|
+
super(
|
|
51
|
+
"#{obj.inspect} cannot be converted into a " \
|
|
52
|
+
'Nanoc::Core::Identifier')
|
|
42
53
|
end
|
|
43
54
|
end
|
|
44
55
|
|
|
@@ -113,7 +124,8 @@ module Nanoc
|
|
|
113
124
|
end
|
|
114
125
|
|
|
115
126
|
contract C::None => C::Bool
|
|
116
|
-
# Whether or not this is a legacy identifier (i.e. does not include the
|
|
127
|
+
# Whether or not this is a legacy identifier (i.e. does not include the
|
|
128
|
+
# extension).
|
|
117
129
|
def legacy?
|
|
118
130
|
@type == :legacy
|
|
119
131
|
end
|
|
@@ -137,7 +149,10 @@ module Nanoc
|
|
|
137
149
|
raise InvalidPrefixError.new(string)
|
|
138
150
|
end
|
|
139
151
|
|
|
140
|
-
Nanoc::Core::Identifier.new(
|
|
152
|
+
Nanoc::Core::Identifier.new(
|
|
153
|
+
string.sub(%r{/+\z}, '') + @string,
|
|
154
|
+
type: @type,
|
|
155
|
+
)
|
|
141
156
|
end
|
|
142
157
|
|
|
143
158
|
contract C::None => String
|
|
@@ -8,7 +8,9 @@ module Nanoc
|
|
|
8
8
|
attr_reader :items
|
|
9
9
|
attr_reader :layouts
|
|
10
10
|
|
|
11
|
-
contract Nanoc::Core::ItemCollection,
|
|
11
|
+
contract Nanoc::Core::ItemCollection,
|
|
12
|
+
Nanoc::Core::LayoutCollection,
|
|
13
|
+
C::Maybe[Nanoc::Core::DataSource] => C::Any
|
|
12
14
|
def initialize(items, layouts, orig_data_source = nil)
|
|
13
15
|
super({}, '/', '/', {})
|
|
14
16
|
|
data/lib/nanoc/core/item.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Nanoc
|
|
4
4
|
module Core
|
|
5
|
-
class ItemCollection < IdentifiableCollection
|
|
5
|
+
class ItemCollection < Nanoc::Core::IdentifiableCollection
|
|
6
6
|
prepend MemoWise
|
|
7
7
|
|
|
8
8
|
def initialize(config, objects = [])
|
|
@@ -10,7 +10,7 @@ module Nanoc
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def reference
|
|
13
|
-
|
|
13
|
+
:items
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
data/lib/nanoc/core/item_rep.rb
CHANGED
|
@@ -6,7 +6,9 @@ module Nanoc
|
|
|
6
6
|
class ItemRepBuilder
|
|
7
7
|
include Nanoc::Core::ContractsSupport
|
|
8
8
|
|
|
9
|
-
contract Nanoc::Core::ActionSequence,
|
|
9
|
+
contract Nanoc::Core::ActionSequence,
|
|
10
|
+
Nanoc::Core::ItemRep =>
|
|
11
|
+
C::ArrayOf[Nanoc::Core::SnapshotDef]
|
|
10
12
|
def self.snapshot_defs_for(action_sequence, rep)
|
|
11
13
|
is_binary = rep.item.content.binary?
|
|
12
14
|
snapshot_defs = []
|
|
@@ -15,7 +17,8 @@ module Nanoc
|
|
|
15
17
|
case action
|
|
16
18
|
when Nanoc::Core::ProcessingActions::Snapshot
|
|
17
19
|
action.snapshot_names.each do |snapshot_name|
|
|
18
|
-
snapshot_defs <<
|
|
20
|
+
snapshot_defs <<
|
|
21
|
+
Nanoc::Core::SnapshotDef.new(snapshot_name, binary: is_binary)
|
|
19
22
|
end
|
|
20
23
|
when Nanoc::Core::ProcessingActions::Filter
|
|
21
24
|
is_binary = Nanoc::Core::Filter.named!(action.filter_name).to_binary?
|
|
@@ -27,7 +30,9 @@ module Nanoc
|
|
|
27
30
|
|
|
28
31
|
attr_reader :reps
|
|
29
32
|
|
|
30
|
-
contract Nanoc::Core::Site,
|
|
33
|
+
contract Nanoc::Core::Site,
|
|
34
|
+
Nanoc::Core::ActionProvider,
|
|
35
|
+
Nanoc::Core::ItemRepRepo => C::Any
|
|
31
36
|
def initialize(site, action_provider, reps)
|
|
32
37
|
@site = site
|
|
33
38
|
@action_provider = action_provider
|
|
@@ -41,10 +46,14 @@ module Nanoc
|
|
|
41
46
|
end
|
|
42
47
|
end
|
|
43
48
|
|
|
44
|
-
action_sequences = Nanoc::Core::ItemRepRouter.new(
|
|
49
|
+
action_sequences = Nanoc::Core::ItemRepRouter.new(
|
|
50
|
+
@reps, @action_provider, @site
|
|
51
|
+
).run
|
|
45
52
|
|
|
46
53
|
@reps.each do |rep|
|
|
47
|
-
rep.snapshot_defs = self.class.snapshot_defs_for(
|
|
54
|
+
rep.snapshot_defs = self.class.snapshot_defs_for(
|
|
55
|
+
action_sequences[rep], rep
|
|
56
|
+
)
|
|
48
57
|
end
|
|
49
58
|
|
|
50
59
|
action_sequences
|
|
@@ -10,17 +10,22 @@ module Nanoc
|
|
|
10
10
|
|
|
11
11
|
class IdenticalRoutesError < ::Nanoc::Core::Error
|
|
12
12
|
def initialize(output_path, rep_a, rep_b)
|
|
13
|
-
super(
|
|
13
|
+
super(
|
|
14
|
+
"The item representations #{rep_a} and #{rep_b} are both " \
|
|
15
|
+
"routed to #{output_path}.")
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
class RouteWithoutSlashError < ::Nanoc::Core::Error
|
|
18
20
|
def initialize(output_path, rep)
|
|
19
|
-
super(
|
|
21
|
+
super(
|
|
22
|
+
"The item representation #{rep} is routed to #{output_path}, " \
|
|
23
|
+
'which does not start with a slash, as required.')
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
26
|
|
|
23
|
-
contract Nanoc::Core::ItemRepRepo, Nanoc::Core::ActionProvider,
|
|
27
|
+
contract Nanoc::Core::ItemRepRepo, Nanoc::Core::ActionProvider,
|
|
28
|
+
Nanoc::Core::Site => C::Any
|
|
24
29
|
def initialize(reps, action_provider, site)
|
|
25
30
|
@reps = reps
|
|
26
31
|
@action_provider = action_provider
|
|
@@ -31,12 +36,14 @@ module Nanoc
|
|
|
31
36
|
action_sequences = {}
|
|
32
37
|
assigned_paths = {}
|
|
33
38
|
@reps.each do |rep|
|
|
34
|
-
# Sigh. We route reps twice, because the first time, the paths might
|
|
35
|
-
# yet. This isn’t ideal, but it’s the only way to
|
|
36
|
-
# I can think of. For details,
|
|
37
|
-
# https://github.com/nanoc/nanoc/pull/1085#issuecomment-280628426.
|
|
39
|
+
# Sigh. We route reps twice, because the first time, the paths might
|
|
40
|
+
# not have converged yet. This isn’t ideal, but it’s the only way to
|
|
41
|
+
# work around the divergence issues that I can think of. For details,
|
|
42
|
+
# see https://github.com/nanoc/nanoc/pull/1085#issuecomment-280628426.
|
|
38
43
|
|
|
39
|
-
@action_provider
|
|
44
|
+
@action_provider
|
|
45
|
+
.action_sequence_for(rep)
|
|
46
|
+
.paths.each do |(snapshot_names, paths)|
|
|
40
47
|
route_rep(rep, paths, snapshot_names, {})
|
|
41
48
|
end
|
|
42
49
|
|
|
@@ -52,7 +59,8 @@ module Nanoc
|
|
|
52
59
|
action_sequences
|
|
53
60
|
end
|
|
54
61
|
|
|
55
|
-
contract Nanoc::Core::ItemRep, C::IterOf[String], C::IterOf[Symbol],
|
|
62
|
+
contract Nanoc::Core::ItemRep, C::IterOf[String], C::IterOf[Symbol],
|
|
63
|
+
C::HashOf[String => Nanoc::Core::ItemRep] => C::Any
|
|
56
64
|
def route_rep(rep, paths, snapshot_names, assigned_paths)
|
|
57
65
|
# Encode
|
|
58
66
|
paths = paths.map { |path| path.encode('UTF-8') }
|
|
@@ -66,7 +74,9 @@ module Nanoc
|
|
|
66
74
|
# Validate uniqueness
|
|
67
75
|
if assigned_paths.include?(path)
|
|
68
76
|
# TODO: Include snapshot names in error message
|
|
69
|
-
reps = [assigned_paths[path], rep].sort_by
|
|
77
|
+
reps = [assigned_paths[path], rep].sort_by do |r|
|
|
78
|
+
[r.item.identifier, r.name]
|
|
79
|
+
end
|
|
70
80
|
raise IdenticalRoutesError.new(path, *reps)
|
|
71
81
|
end
|
|
72
82
|
assigned_paths[path] = rep
|
|
@@ -74,15 +84,19 @@ module Nanoc
|
|
|
74
84
|
|
|
75
85
|
# Assign
|
|
76
86
|
snapshot_names.each do |snapshot_name|
|
|
77
|
-
rep.raw_paths[snapshot_name] = paths.map
|
|
78
|
-
|
|
87
|
+
rep.raw_paths[snapshot_name] = paths.map do |path|
|
|
88
|
+
@site.config.output_dir + path
|
|
89
|
+
end
|
|
90
|
+
rep.paths[snapshot_name] = paths.map do |path|
|
|
91
|
+
strip_index_filename(path)
|
|
92
|
+
end
|
|
79
93
|
end
|
|
80
94
|
end
|
|
81
95
|
|
|
82
96
|
contract String => String
|
|
83
97
|
def strip_index_filename(basic_path)
|
|
84
98
|
@site.config[:index_filenames].each do |index_filename|
|
|
85
|
-
slashed_index_filename =
|
|
99
|
+
slashed_index_filename = "/#{index_filename}"
|
|
86
100
|
if basic_path.end_with?(slashed_index_filename)
|
|
87
101
|
return basic_path[0..(-index_filename.length - 1)]
|
|
88
102
|
end
|
|
@@ -18,11 +18,23 @@ module Nanoc
|
|
|
18
18
|
|
|
19
19
|
def write(item_rep, compiled_content_repo, snapshot_name, written_paths)
|
|
20
20
|
item_rep.raw_paths.fetch(snapshot_name, []).each do |raw_path|
|
|
21
|
-
write_single(
|
|
21
|
+
write_single(
|
|
22
|
+
item_rep,
|
|
23
|
+
compiled_content_repo,
|
|
24
|
+
snapshot_name,
|
|
25
|
+
raw_path,
|
|
26
|
+
written_paths,
|
|
27
|
+
)
|
|
22
28
|
end
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
def write_single(
|
|
31
|
+
def write_single(
|
|
32
|
+
item_rep,
|
|
33
|
+
compiled_content_repo,
|
|
34
|
+
snapshot_name,
|
|
35
|
+
raw_path,
|
|
36
|
+
written_paths
|
|
37
|
+
)
|
|
26
38
|
assert Nanoc::Core::Assertions::PathIsAbsolute.new(path: raw_path)
|
|
27
39
|
|
|
28
40
|
# Don’t write twice
|
|
@@ -56,7 +68,10 @@ module Nanoc
|
|
|
56
68
|
# Notify ready for diff generation
|
|
57
69
|
if !is_created && is_modified && !content.binary?
|
|
58
70
|
Nanoc::Core::NotificationCenter.post(
|
|
59
|
-
:rep_ready_for_diff,
|
|
71
|
+
:rep_ready_for_diff,
|
|
72
|
+
raw_path,
|
|
73
|
+
File.read(raw_path, encoding: 'UTF-8'),
|
|
74
|
+
content.string,
|
|
60
75
|
)
|
|
61
76
|
end
|
|
62
77
|
|
|
@@ -69,7 +84,12 @@ module Nanoc
|
|
|
69
84
|
|
|
70
85
|
# Notify
|
|
71
86
|
Nanoc::Core::NotificationCenter.post(
|
|
72
|
-
:rep_write_ended,
|
|
87
|
+
:rep_write_ended,
|
|
88
|
+
item_rep,
|
|
89
|
+
content.binary?,
|
|
90
|
+
raw_path,
|
|
91
|
+
is_created,
|
|
92
|
+
is_modified,
|
|
73
93
|
)
|
|
74
94
|
end
|
|
75
95
|
|
|
@@ -84,7 +104,10 @@ module Nanoc
|
|
|
84
104
|
begin
|
|
85
105
|
res = Clonefile.always(from, to)
|
|
86
106
|
return if res
|
|
87
|
-
rescue Clonefile::UnsupportedPlatform,
|
|
107
|
+
rescue Clonefile::UnsupportedPlatform,
|
|
108
|
+
Errno::ENOTSUP,
|
|
109
|
+
Errno::EXDEV,
|
|
110
|
+
Errno::EINVAL
|
|
88
111
|
end
|
|
89
112
|
end
|
|
90
113
|
|