nanoc3 3.0.9 → 3.1.0a1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/LICENSE +1 -1
  2. data/NEWS.md +360 -0
  3. data/README.md +85 -0
  4. data/Rakefile +2 -2
  5. data/bin/nanoc3 +0 -4
  6. data/lib/nanoc3/base/code_snippet.rb +14 -6
  7. data/lib/nanoc3/base/compiler.rb +68 -49
  8. data/lib/nanoc3/base/compiler_dsl.rb +70 -29
  9. data/lib/nanoc3/base/context.rb +47 -0
  10. data/lib/nanoc3/base/core_ext/array.rb +4 -0
  11. data/lib/nanoc3/base/core_ext/hash.rb +5 -1
  12. data/lib/nanoc3/base/core_ext/string.rb +2 -0
  13. data/lib/nanoc3/base/data_source.rb +132 -96
  14. data/lib/nanoc3/base/dependency_tracker.rb +160 -185
  15. data/lib/nanoc3/base/directed_graph.rb +252 -0
  16. data/lib/nanoc3/base/errors.rb +52 -4
  17. data/lib/nanoc3/base/filter.rb +43 -28
  18. data/lib/nanoc3/base/item.rb +93 -25
  19. data/lib/nanoc3/base/item_rep.rb +166 -55
  20. data/lib/nanoc3/base/layout.rb +16 -13
  21. data/lib/nanoc3/base/notification_center.rb +28 -12
  22. data/lib/nanoc3/base/plugin_registry.rb +158 -0
  23. data/lib/nanoc3/base/rule.rb +27 -8
  24. data/lib/nanoc3/base/rule_context.rb +59 -46
  25. data/lib/nanoc3/base/site.rb +124 -77
  26. data/lib/nanoc3/base.rb +7 -2
  27. data/lib/nanoc3/cli/base.rb +4 -1
  28. data/lib/nanoc3/cli/commands/autocompile.rb +5 -4
  29. data/lib/nanoc3/cli/commands/compile.rb +28 -7
  30. data/lib/nanoc3/cli/commands/create_item.rb +1 -1
  31. data/lib/nanoc3/cli/commands/create_layout.rb +1 -1
  32. data/lib/nanoc3/cli/commands/create_site.rb +46 -22
  33. data/lib/nanoc3/cli/commands/debug.rb +100 -0
  34. data/lib/nanoc3/cli/commands/help.rb +1 -1
  35. data/lib/nanoc3/cli/commands/info.rb +1 -1
  36. data/lib/nanoc3/cli/commands/view.rb +85 -0
  37. data/lib/nanoc3/cli/commands.rb +2 -0
  38. data/lib/nanoc3/cli/logger.rb +7 -0
  39. data/lib/nanoc3/cli.rb +0 -3
  40. data/lib/nanoc3/data_sources/{delicious.rb → deprecated/delicious.rb} +1 -24
  41. data/lib/nanoc3/data_sources/{last_fm.rb → deprecated/last_fm.rb} +1 -27
  42. data/lib/nanoc3/data_sources/{twitter.rb → deprecated/twitter.rb} +1 -14
  43. data/lib/nanoc3/data_sources/filesystem.rb +188 -176
  44. data/lib/nanoc3/data_sources/filesystem_unified.rb +107 -0
  45. data/lib/nanoc3/data_sources/filesystem_verbose.rb +80 -0
  46. data/lib/nanoc3/data_sources.rb +18 -9
  47. data/lib/nanoc3/extra/core_ext/enumerable.rb +39 -0
  48. data/lib/nanoc3/extra/core_ext/time.rb +2 -2
  49. data/lib/nanoc3/extra/core_ext.rb +1 -0
  50. data/lib/nanoc3/extra/deployers/rsync.rb +49 -3
  51. data/lib/nanoc3/extra/file_proxy.rb +7 -0
  52. data/lib/nanoc3/extra/vcs.rb +25 -24
  53. data/lib/nanoc3/extra/vcses/bazaar.rb +4 -0
  54. data/lib/nanoc3/extra/vcses/dummy.rb +4 -0
  55. data/lib/nanoc3/extra/vcses/git.rb +4 -0
  56. data/lib/nanoc3/extra/vcses/mercurial.rb +4 -0
  57. data/lib/nanoc3/extra/vcses/subversion.rb +4 -0
  58. data/lib/nanoc3/extra.rb +4 -1
  59. data/lib/nanoc3/filters/erb.rb +1 -1
  60. data/lib/nanoc3/filters/erubis.rb +1 -1
  61. data/lib/nanoc3/filters/haml.rb +1 -1
  62. data/lib/nanoc3/filters/kramdown.rb +14 -0
  63. data/lib/nanoc3/filters/maruku.rb +1 -1
  64. data/lib/nanoc3/filters/rainpress.rb +1 -1
  65. data/lib/nanoc3/filters/rdiscount.rb +3 -1
  66. data/lib/nanoc3/filters.rb +2 -0
  67. data/lib/nanoc3/helpers/blogging.rb +91 -75
  68. data/lib/nanoc3/helpers/breadcrumbs.rb +18 -10
  69. data/lib/nanoc3/helpers/capturing.rb +24 -29
  70. data/lib/nanoc3/helpers/filtering.rb +20 -17
  71. data/lib/nanoc3/helpers/html_escape.rb +7 -4
  72. data/lib/nanoc3/helpers/link_to.rb +51 -41
  73. data/lib/nanoc3/helpers/rendering.rb +15 -8
  74. data/lib/nanoc3/helpers/tagging.rb +27 -21
  75. data/lib/nanoc3/helpers/text.rb +12 -8
  76. data/lib/nanoc3/helpers/xml_sitemap.rb +13 -15
  77. data/lib/nanoc3/tasks/deploy/rsync.rake +4 -1
  78. data/lib/nanoc3/tasks.rb +2 -1
  79. data/lib/nanoc3.rb +24 -1
  80. metadata +43 -87
  81. data/NEWS.rdoc +0 -328
  82. data/README.rdoc +0 -83
  83. data/lib/nanoc3/base/plugin.rb +0 -88
  84. data/lib/nanoc3/base/preprocessor_context.rb +0 -37
  85. data/lib/nanoc3/data_sources/filesystem_combined.rb +0 -214
  86. data/lib/nanoc3/data_sources/filesystem_common.rb +0 -22
  87. data/lib/nanoc3/data_sources/filesystem_compact.rb +0 -256
  88. data/lib/nanoc3/extra/context.rb +0 -24
  89. data/lib/nanoc3/package.rb +0 -107
  90. data/vendor/cri/ChangeLog +0 -0
  91. data/vendor/cri/LICENSE +0 -19
  92. data/vendor/cri/NEWS +0 -0
  93. data/vendor/cri/README +0 -4
  94. data/vendor/cri/Rakefile +0 -25
  95. data/vendor/cri/lib/cri/base.rb +0 -153
  96. data/vendor/cri/lib/cri/command.rb +0 -105
  97. data/vendor/cri/lib/cri/core_ext/string.rb +0 -41
  98. data/vendor/cri/lib/cri/core_ext.rb +0 -8
  99. data/vendor/cri/lib/cri/option_parser.rb +0 -186
  100. data/vendor/cri/lib/cri.rb +0 -12
  101. data/vendor/cri/test/test_base.rb +0 -6
  102. data/vendor/cri/test/test_command.rb +0 -6
  103. data/vendor/cri/test/test_core_ext.rb +0 -21
  104. data/vendor/cri/test/test_option_parser.rb +0 -279
@@ -0,0 +1,252 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3
4
+
5
+ # Nanoc3::DirectedGraph represents a directed graph. It is used by the
6
+ # dependency tracker for storing and querying dependencies between items.
7
+ # Internally, the graph will be stored as an adjacency matrix. For this,
8
+ # the {Nanoc3::DirectedGraph::SquareBooleanMatrix} class is used.
9
+ #
10
+ # @example Creating and using a directed graph
11
+ #
12
+ # # Create a graph with three vertices
13
+ # graph = DirectedGraph.new(%w( a b c d ))
14
+ #
15
+ # # Add edges
16
+ # graph.add_edge('a', 'b')
17
+ # graph.add_edge('b', 'c')
18
+ # graph.add_edge('c', 'd')
19
+ #
20
+ # # Get (direct) predecessors
21
+ # graph.direct_predecessors_of('d').sort
22
+ # # => %w( c )
23
+ # graph.predecessors_of('d').sort
24
+ # # => %w( a b c )
25
+ #
26
+ # # Modify edges
27
+ # graph.remove_edge('a', 'b')
28
+ #
29
+ # # Get (direct) predecessors again
30
+ # graph.direct_predecessors_of('d').sort
31
+ # # => %w( c )
32
+ # graph.predecessors_of('d').sort
33
+ # # => %w( b c )
34
+ class DirectedGraph
35
+
36
+ # Nanoc3::DirectedGraph::SquareBooleanMatrix is, as the name says, a
37
+ # square matrix that contains boolean values. It is used as an adjacency
38
+ # matrix by the {Nanoc3::DirectedGraph} class.
39
+ class SquareBooleanMatrix
40
+
41
+ # Creates a new matrix with the given number of rows/columns.
42
+ #
43
+ # @param [Number] size The number of elements along both sides of the
44
+ # matrix (in other words, the square root of the number of elements)
45
+ def initialize(size)
46
+ @size = size
47
+ end
48
+
49
+ # Gets the value at the given x/y coordinates.
50
+ #
51
+ # @param [Number] x The X coordinate
52
+ # @param [Number] y The Y coordinate
53
+ #
54
+ # @return The value at the given coordinates
55
+ def [](x, y)
56
+ @data ||= {}
57
+ @data[x] ||= {}
58
+ @data[x].has_key?(y) ? @data[x][y] : false
59
+ end
60
+
61
+ # Sets the value at the given x/y coordinates.
62
+ #
63
+ # @param [Number] x The X coordinate
64
+ # @param [Number] y The Y coordinate
65
+ # @param value The value to set at the given coordinates
66
+ #
67
+ # @return [void]
68
+ def []=(x, y, value)
69
+ @data ||= {}
70
+ @data[x] ||= {}
71
+ @data[x][y] = value
72
+ end
73
+
74
+ # Returns a string representing this matrix in ASCII art.
75
+ #
76
+ # @return [String] The string representation of this matrix
77
+ def to_s
78
+ s = ''
79
+
80
+ # Calculate column width
81
+ width = (@size-1).to_s.size
82
+
83
+ # Add header
84
+ s << ' ' + ' '*width + ' '
85
+ @size.times { |i| s << '| ' + format("%#{width}i", i) + ' ' }
86
+ s << "\n"
87
+
88
+ # Add rows
89
+ @size.times do |x|
90
+ # Add line
91
+ s << '-' + '-'*width + '-'
92
+ @size.times { |i| s << '+-' + '-'*width + '-' }
93
+ s << "\n"
94
+
95
+ # Add actual row
96
+ s << ' ' + format("%#{width}i", x)+ ' '
97
+ @size.times do |y|
98
+ s << '| ' + format("%#{width}s", self[x, y] ? '*' : ' ') + ' '
99
+ end
100
+ s << "\n"
101
+ end
102
+
103
+ # Done
104
+ s
105
+ end
106
+
107
+ end
108
+
109
+ # The list of vertices in this graph.
110
+ #
111
+ # @return [Array]
112
+ attr_reader :vertices
113
+
114
+ # Creates a new directed graph with the given vertices.
115
+ def initialize(vertices)
116
+ @vertices = vertices
117
+
118
+ @matrix = SquareBooleanMatrix.new(@vertices.size)
119
+ end
120
+
121
+ # Adds an edge from the first vertex to the second vertex.
122
+ #
123
+ # @param from Vertex where the edge should start
124
+ # @param to Vertex where the edge should end
125
+ #
126
+ # @return [void]
127
+ def add_edge(from, to)
128
+ from_index, to_index = indices_of(from, to)
129
+ @matrix[from_index, to_index] = true
130
+ end
131
+
132
+ # Removes the edge from the first vertex to the second vertex. If the
133
+ # edge does not exist, nothing is done.
134
+ #
135
+ # @param from Start vertex of the edge
136
+ # @param to End vertex of the edge
137
+ #
138
+ # @return [void]
139
+ def remove_edge(from, to)
140
+ from_index, to_index = indices_of(from, to)
141
+ @matrix[from_index, to_index] = false
142
+ end
143
+
144
+ # Returns the direct predecessors of the given vertex, i.e. the vertices
145
+ # x where there is an edge from x to the given vertex y.
146
+ #
147
+ # @param to The vertex of which the predecessors should be calculated
148
+ #
149
+ # @return [Array] Direct predecessors of the given vertex
150
+ def direct_predecessors_of(to)
151
+ @vertices.select do |from|
152
+ from_index, to_index = indices_of(from, to)
153
+ @matrix[from_index, to_index] == true
154
+ end
155
+ end
156
+
157
+ # Returns the direct successors of the given vertex, i.e. the vertices y
158
+ # where there is an edge from the given vertex x to y.
159
+ #
160
+ # @param from The vertex of which the successors should be calculated
161
+ #
162
+ # @return [Array] Direct successors of the given vertex
163
+ def direct_successors_of(from)
164
+ @vertices.select do |to|
165
+ from_index, to_index = indices_of(from, to)
166
+ @matrix[from_index, to_index] == true
167
+ end
168
+ end
169
+
170
+ # Returns the predecessors of the given vertex, i.e. the vertices x for
171
+ # which there is a path from x to the given vertex y.
172
+ #
173
+ # @param to The vertex of which the predecessors should be calculated
174
+ #
175
+ # @return [Array] Predecessors of the given vertex
176
+ def predecessors_of(to)
177
+ recursively_find_vertices(to, :direct_predecessors_of)
178
+ end
179
+
180
+ # Returns the successors of the given vertex, i.e. the vertices y for
181
+ # which there is a path from the given vertex x to y.
182
+ #
183
+ # @param from The vertex of which the successors should be calculated
184
+ #
185
+ # @return [Array] Successors of the given vertex
186
+ def successors_of(from)
187
+ recursively_find_vertices(from, :direct_successors_of)
188
+ end
189
+
190
+ # Returns an array of tuples representing the edges. The result of this
191
+ # method may take a while to compute and should be cached if possible.
192
+ #
193
+ # @return [Array] The list of all edges in this graph.
194
+ def edges
195
+ result = []
196
+
197
+ @vertices.each do |from|
198
+ @vertices.each do |to|
199
+ from_index, to_index = indices_of(from, to)
200
+ next if @matrix[from_index, to_index] == false
201
+
202
+ result << [ from_index, to_index ]
203
+ end
204
+ end
205
+
206
+ result
207
+ end
208
+
209
+ # Returns a string representing this graph in ASCII art (or, to be more
210
+ # precise, the string representation of the matrix backing this graph).
211
+ #
212
+ # @return [String] The string representation of this graph
213
+ def to_s
214
+ @matrix.to_s
215
+ end
216
+
217
+ private
218
+
219
+ # Returns an array of indices for the given vertices. Raises an error if
220
+ # one or more given objects are not vertices.
221
+ def indices_of(*vertices)
222
+ vertices.map { |v| @vertices.index(v) or raise RuntimeError, "#{v.inspect} not a vertex" }
223
+ end
224
+
225
+ # Recursively finds vertices, starting at the vertex start, using the
226
+ # given method, which should be a symbol to a method that takes a vertex
227
+ # and returns related vertices (e.g. predecessors, successors).
228
+ def recursively_find_vertices(start, method)
229
+ all_vertices = []
230
+
231
+ processed_vertices = []
232
+ unprocessed_vertices = [ start ]
233
+
234
+ until unprocessed_vertices.empty?
235
+ # Get next unprocessed vertex
236
+ vertex = unprocessed_vertices.pop
237
+ next if processed_vertices.include?(vertex)
238
+ processed_vertices << vertex
239
+
240
+ # Add predecessors of this vertex
241
+ send(method, vertex).each do |v|
242
+ all_vertices << v unless all_vertices.include?(v)
243
+ unprocessed_vertices << v
244
+ end
245
+ end
246
+
247
+ all_vertices
248
+ end
249
+
250
+ end
251
+
252
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Nanoc3
4
4
 
5
+ # Module that contains all nanoc-specific errors.
5
6
  module Errors
6
7
 
7
8
  # Generic error. Superclass for all nanoc-specific errors.
@@ -11,83 +12,130 @@ module Nanoc3
11
12
  # Error that is raised when a site is loaded that uses a data source with
12
13
  # an unknown identifier.
13
14
  class UnknownDataSource < Generic
15
+
16
+ # @param [String] data_source_name The data source name for which no
17
+ # data source could be found
14
18
  def initialize(data_source_name)
15
19
  super("The data source specified in the site's configuration file, #{data_source_name}, does not exist.")
16
20
  end
21
+
17
22
  end
18
23
 
19
24
  # Error that is raised during site compilation when an item uses a layout
20
25
  # that is not present in the site.
21
26
  class UnknownLayout < Generic
27
+
28
+ # @param [String] layout_identifier The layout identifier for which no
29
+ # layout could be found
22
30
  def initialize(layout_identifier)
23
31
  super("The site does not have a layout with identifier '#{layout_identifier}'.")
24
32
  end
33
+
25
34
  end
26
35
 
27
36
  # Error that is raised during site compilation when an item uses a filter
28
37
  # that is not known.
29
38
  class UnknownFilter < Generic
39
+
40
+ # @param [Symbol] filter_name The filter name for which no filter could
41
+ # be found
30
42
  def initialize(filter_name)
31
43
  super("The requested filter, #{filter_name}, does not exist.")
32
44
  end
45
+
33
46
  end
34
47
 
35
48
  # Error that is raised during site compilation when a layout is compiled
36
49
  # for which the filter cannot be determined. This is similar to the
37
- # UnknownFilterError, but specific for filters for layouts.
50
+ # {UnknownFilter} error, but specific for filters for layouts.
38
51
  class CannotDetermineFilter < Generic
52
+
53
+ # @param [String] layout_identifier The identifier of the layout for
54
+ # which the filter could not be determined
39
55
  def initialize(layout_identifier)
40
56
  super("The filter to be used for the '#{layout_identifier}' could not be determined. Make sure the layout does have a filter.")
41
57
  end
58
+
42
59
  end
43
60
 
44
61
  # Error that is raised when data is requested when the data is not yet
45
- # available (possibly due to a missing Nanoc::Site#load_data).
62
+ # available (possibly due to a missing {Nanoc3::Site#load_data}).
46
63
  class DataNotYetAvailable < Generic
64
+
65
+ # @param [String] type The name of the data type that is not yet
66
+ # available. For example: `"site"`, `"items"`.
67
+ #
68
+ # @param [Boolean] plural True if the given type is plural, false
69
+ # otherwise. This only has an effect on the exception message. For
70
+ # example, if the given type is `"site"`, plural would be `false`; if
71
+ # the given type is `"items"`, plural would be `true`.
47
72
  def initialize(type, plural)
48
- super("#{type} #{plural ? 'are' : 'is'} not available yet. You may be missing a Nanoc::Site#load_data call.")
73
+ super("#{type} #{plural ? 'are' : 'is'} not available yet. You may be missing a Nanoc3::Site#load_data call.")
49
74
  end
75
+
50
76
  end
51
77
 
52
78
  # Error that is raised during site compilation when an item (directly or
53
79
  # indirectly) includes its own item content, leading to endless recursion.
54
80
  class RecursiveCompilation < Generic
81
+
82
+ # @param [Array<Nanoc3::ItemRep>] reps A list of item representations
83
+ # that mutually depend on each other
55
84
  def initialize(reps)
56
85
  super("The site cannot be compiled because the following items mutually depend on each other: #{reps.inspect}.")
57
86
  end
87
+
58
88
  end
59
89
 
60
90
  # Error that is raised when no rules file can be found in the current
61
91
  # working directory.
62
92
  class NoRulesFileFound < Generic
93
+
63
94
  def initialize
64
95
  super("This site does not have a rules file, which is required for nanoc sites.")
65
96
  end
97
+
66
98
  end
67
99
 
68
100
  # Error that is raised when no compilation rule that can be applied to the
69
101
  # current item can be found.
70
102
  class NoMatchingCompilationRuleFound < Generic
103
+
104
+ # @param [Nanoc3::Item] item The item for which no compilation rule
105
+ # could be found
71
106
  def initialize(item)
72
107
  super("No compilation rules were found for the '#{item.identifier}' item.")
73
108
  end
109
+
74
110
  end
75
111
 
76
112
  # Error that is raised when no routing rule that can be applied to the
77
113
  # current item can be found.
78
114
  class NoMatchingRoutingRuleFound < Generic
115
+
116
+ # @param [Nanoc3::Item] item The item for which no routing rule could be
117
+ # found
79
118
  def initialize(rep)
80
119
  super("No routing rules were found for the '#{rep.item.identifier}' item (rep '#{rep.name}').")
81
120
  end
121
+
82
122
  end
83
123
 
84
- # Error that is raised when an rep cannot be compiled because it depends on other representations.
124
+ # Error that is raised when an rep cannot be compiled because it depends
125
+ # on other representations.
85
126
  class UnmetDependency < Generic
127
+
128
+ # @return [Nanoc3::ItemRep] The item representation that cannot yet be
129
+ # compiled
86
130
  attr_reader :rep
131
+
132
+ # @param [Nanoc3::ItemRep] The item representation that cannot yet be
133
+ # compiled
87
134
  def initialize(rep)
88
135
  @rep = rep
89
136
  super("The '#{rep.item.identifier}' item (rep '#{rep.name}') cannot currently be compiled yet due to an unmet dependency.")
90
137
  end
138
+
91
139
  end
92
140
 
93
141
  end
@@ -2,49 +2,64 @@
2
2
 
3
3
  module Nanoc3
4
4
 
5
- # Nanoc3::Filter is responsible for filtering items. It is
6
- # the (abstract) superclass for all textual filters. Subclasses should
7
- # override the +run+ method.
8
- class Filter < Plugin
5
+ # Nanoc3::Filter is responsible for filtering items. It is the superclass
6
+ # for all textual filters.
7
+ #
8
+ # When creating a filter with a hash containing assigned variables, those
9
+ # variables will be made available in the `@assigns` instance variable and
10
+ # the {#assigns} method. The assigns itself will also be available as
11
+ # instance variables and instance methods.
12
+ #
13
+ # @example Accessing assigns in different ways
14
+ #
15
+ # filter = SomeFilter.new({ :foo => 'bar' })
16
+ # filter.instance_eval { @assigns[:foo] }
17
+ # # => 'bar'
18
+ # filter.instance_eval { assigns[:foo] }
19
+ # # => 'bar'
20
+ # filter.instance_eval { @foo }
21
+ # # => 'bar'
22
+ # filter.instance_eval { foo }
23
+ # # => 'bar'
24
+ #
25
+ # @abstract Subclass and override {#run} to implement a custom filter.
26
+ class Filter < Context
9
27
 
10
28
  # A hash containing variables that will be made available during
11
29
  # filtering.
12
- attr_reader :assigns
13
-
14
- # Creates a new filter with the given assigns.
15
30
  #
16
- # +a_assigns+:: A hash containing variables that should be made available
17
- # during filtering.
18
- def initialize(a_assigns={})
19
- @assigns = a_assigns
20
- end
31
+ # @return [Hash]
32
+ attr_reader :assigns
21
33
 
22
- # Sets the identifiers for this filter.
23
- def self.identifiers(*identifiers)
24
- Nanoc3::Filter.register(self, *identifiers)
25
- end
34
+ extend Nanoc3::PluginRegistry::PluginMethods
26
35
 
27
- # Sets the identifier for this filter.
28
- def self.identifier(identifier)
29
- Nanoc3::Filter.register(self, identifier)
30
- end
31
-
32
- # Registers the given class as a filter with the given identifier.
33
- def self.register(class_or_name, *identifiers)
34
- Nanoc3::Plugin.register(Nanoc3::Filter, class_or_name, *identifiers)
36
+ # Creates a new filter that has access to the given assigns.
37
+ #
38
+ # @param [Hash] a_assigns A hash containing variables that should be made
39
+ # available during filtering.
40
+ def initialize(hash={})
41
+ @assigns = hash
42
+ super
35
43
  end
36
44
 
37
- # Runs the filter. This method returns the filtered content.
45
+ # Runs the filter on the given content.
46
+ #
47
+ # @abstract
38
48
  #
39
- # +content+:: The unprocessed content that should be filtered.
49
+ # @param [String] content The unprocessed content that should be filtered.
40
50
  #
41
- # Subclasses must implement this method.
51
+ # @param [Hash] params A hash containing parameters. Filter subclasses can
52
+ # use these parameters to allow modifying the filter's behaviour.
53
+ #
54
+ # @return [String] The filtered content
42
55
  def run(content, params={})
43
56
  raise NotImplementedError.new("Nanoc3::Filter subclasses must implement #run")
44
57
  end
45
58
 
46
59
  # Returns the filename associated with the item that is being filtered.
47
- # The returned filename is in the format "item <identifier> (rep <name>)".
60
+ # It is in the format `item <identifier> (rep <name>)`.
61
+ #
62
+ # @return [String] The filename
48
63
  def filename
49
64
  if assigns[:layout]
50
65
  "layout #{assigns[:layout].identifier}"
@@ -2,47 +2,48 @@
2
2
 
3
3
  module Nanoc3
4
4
 
5
- # Nanoc3::Item represents a compileable item in a site. It has content and
6
- # attributes, as well as an identifier. It can also store the modification
7
- # time to speed up compilation.
5
+ # Represents a compileable item in a site. It has content and attributes, as
6
+ # well as an identifier (which starts and ends with a slash). It can also
7
+ # store the modification time to speed up compilation.
8
8
  class Item
9
9
 
10
- # The Nanoc3::Site this item belongs to.
10
+ # @return [Nanoc3::Site] The site this item belongs to
11
11
  attr_accessor :site
12
12
 
13
- # A hash containing this item's attributes.
13
+ # @return [Hash] This item's attributes
14
14
  attr_accessor :attributes
15
15
 
16
- # This item's identifier.
16
+ # @return [String] This item's identifier
17
17
  attr_accessor :identifier
18
18
 
19
- # The time when this item was last modified.
19
+ # @return [Time] The time when this item was last modified
20
20
  attr_reader :mtime
21
21
 
22
- # This item's list of item representations.
22
+ # @return [Array<Nanoc3::ItemRep>] This items list of item reps
23
23
  attr_reader :reps
24
24
 
25
- # This item's raw, uncompiled content.
25
+ # @return [String] This item's raw, uncompiled content
26
26
  attr_reader :raw_content
27
27
 
28
- # The parent item of this item. This can be nil even for non-root items.
28
+ # @return [Nanoc3::Item, nil] The parent item of this item. This can be
29
+ # nil even for non-root items.
29
30
  attr_accessor :parent
30
31
 
31
- # The child items of this item.
32
+ # @return [Array<Nanoc3::Item>] The child items of this item
32
33
  attr_accessor :children
33
34
 
34
- # A boolean indicating whether or not this item is outdated because of its dependencies are outdated.
35
- attr_accessor :dependencies_outdated
35
+ # @return [Boolean] Whether or not this item is outdated because of its
36
+ # dependencies are outdated
37
+ attr_accessor :outdated_due_to_dependencies
38
+ alias_method :outdated_due_to_dependencies?, :outdated_due_to_dependencies
36
39
 
37
- # Creates a new item.
40
+ # @param [String] raw_content The uncompiled item content.
38
41
  #
39
- # +raw_content+:: The uncompiled item content.
42
+ # @param [Hash] attributes A hash containing this item's attributes.
40
43
  #
41
- # +attributes+:: A hash containing this item's attributes.
44
+ # @param [String] identifier This item's identifier.
42
45
  #
43
- # +identifier+:: This item's identifier.
44
- #
45
- # +mtime+:: The time when this item was last modified.
46
+ # @param [String, nil] mtime The time when this item was last modified.
46
47
  def initialize(raw_content, attributes, identifier, mtime=nil)
47
48
  @raw_content = raw_content
48
49
  @attributes = attributes.symbolize_keys
@@ -55,7 +56,72 @@ module Nanoc3
55
56
  @reps = []
56
57
  end
57
58
 
59
+ # Returns the rep with the given name.
60
+ #
61
+ # @param [Symbol] rep_name The name of the representation to return
62
+ #
63
+ # @return [Nanoc3::ItemRep] The representation with the given name
64
+ def rep(rep_name)
65
+ @reps.find { |r| r.name == rep_name }
66
+ end
67
+
68
+ # Returns the compiled content from a given representation and a given
69
+ # snapshot. This is a convenience method that makes fetching compiled
70
+ # content easier.
71
+ #
72
+ # @option params [String] :rep (:default) The name of the representation
73
+ # from which the compiled content should be fetched. By default, the
74
+ # compiled content will be fetched from the default representation.
75
+ #
76
+ # @option params [String] :snapshot (:last) The name of the snapshot from
77
+ # which to fetch the compiled content. By default, the fully compiled
78
+ # content will be fetched, with all filters and layouts applied--not the
79
+ # pre-layout content.
80
+ #
81
+ # @return [String] The compiled content of the given rep (or the default
82
+ # rep if no rep is specified) at the given snapshot (or the default
83
+ # snapshot if no snapshot is specified)
84
+ def compiled_content(params={})
85
+ # Get rep
86
+ rep_name = params[:rep] || :default
87
+ rep = reps.find { |r| r.name == rep_name }
88
+ if rep.nil?
89
+ raise Nanoc3::Errors::Generic,
90
+ "No rep named #{rep_name.inspect} was found."
91
+ end
92
+
93
+ # Get rep's content
94
+ rep.compiled_content(params)
95
+ end
96
+
97
+ # Returns the path from a given representation. This is a convenience
98
+ # method that makes fetching the path of a rep easier.
99
+ #
100
+ # @option params [String] :rep (:default) The name of the representation
101
+ # from which the path should be fetched. By default, the path will be
102
+ # fetched from the default representation.
103
+ #
104
+ # @return [String] The path of the given rep ( or the default rep if no
105
+ # rep is specified)
106
+ def path(params={})
107
+ rep_name = params[:rep] || :default
108
+
109
+ # Get rep
110
+ rep = reps.find { |r| r.name == rep_name }
111
+ if rep.nil?
112
+ raise Nanoc3::Errors::Generic,
113
+ "No rep named #{rep_name.inspect} was found."
114
+ end
115
+
116
+ # Get rep's path
117
+ rep.path
118
+ end
119
+
58
120
  # Requests the attribute with the given key.
121
+ #
122
+ # @param [Symbol] key The name of the attribute to fetch
123
+ #
124
+ # @return [Object] The value of the requested attribute
59
125
  def [](key)
60
126
  Nanoc3::NotificationCenter.post(:visit_started, self)
61
127
  Nanoc3::NotificationCenter.post(:visit_ended, self)
@@ -64,20 +130,22 @@ module Nanoc3
64
130
  end
65
131
 
66
132
  # Sets the attribute with the given key to the given value.
133
+ #
134
+ # @param [Symbol] key The name of the attribute to set
135
+ #
136
+ # @param [Object] value The value of the attribute to set
67
137
  def []=(key, value)
68
138
  @attributes[key] = value
69
139
  end
70
140
 
71
- # True if any reps are outdated; false otherwise.
141
+ # Determines whether this item (or rather, its reps) is outdated and
142
+ # should be recompiled (or rather, its reps should be recompiled).
143
+ #
144
+ # @return [Boolean] true if any reps are outdated; false otherwise.
72
145
  def outdated?
73
146
  @reps.any? { |r| r.outdated? }
74
147
  end
75
148
 
76
- # Alias for #dependencies_outdated.
77
- def dependencies_outdated?
78
- self.dependencies_outdated
79
- end
80
-
81
149
  def inspect
82
150
  "<#{self.class}:0x#{self.object_id.to_s(16)} identifier=#{self.identifier}>"
83
151
  end