nanoc3 3.2.0a2 → 3.2.0a3
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.
- data/NEWS.md +24 -0
- data/README.md +2 -0
- data/lib/nanoc3.rb +1 -1
- data/lib/nanoc3/base/compilation/checksum_store.rb +1 -1
- data/lib/nanoc3/base/compilation/compiler.rb +29 -3
- data/lib/nanoc3/base/compilation/dependency_tracker.rb +2 -1
- data/lib/nanoc3/base/directed_graph.rb +5 -0
- data/lib/nanoc3/base/source_data/code_snippet.rb +2 -11
- data/lib/nanoc3/base/source_data/item.rb +29 -7
- data/lib/nanoc3/base/source_data/layout.rb +12 -11
- data/lib/nanoc3/base/source_data/site.rb +20 -7
- data/lib/nanoc3/cli/base.rb +55 -10
- data/lib/nanoc3/cli/commands/debug.rb +1 -1
- data/lib/nanoc3/cli/commands/watch.rb +4 -8
- data/lib/nanoc3/cli/logger.rb +32 -21
- data/lib/nanoc3/data_sources/filesystem.rb +1 -1
- data/lib/nanoc3/filters/colorize_syntax.rb +16 -1
- data/lib/nanoc3/filters/redcloth.rb +30 -3
- data/lib/nanoc3/helpers/blogging.rb +19 -12
- data/lib/nanoc3/helpers/capturing.rb +83 -13
- data/lib/nanoc3/helpers/rendering.rb +24 -1
- metadata +4 -4
data/NEWS.md
CHANGED
@@ -5,6 +5,30 @@
|
|
5
5
|
* Sped up nanoc quite a bit
|
6
6
|
* Added AsciiDoc filter
|
7
7
|
* Added progress indicator for long-running filters
|
8
|
+
* Made all source data, such as item attributes, frozen during compilation
|
9
|
+
* Exposed RedCloth parameters in the filter [Vincent Driessen]
|
10
|
+
* Added --color option to force color on
|
11
|
+
* Cleaned up internals, deprecating several parts and/or marking them as
|
12
|
+
private in the progress
|
13
|
+
|
14
|
+
## 3.1.5 (???)
|
15
|
+
|
16
|
+
* Improved `#render` documentation
|
17
|
+
* Improved metadata section check so that e.g. raw diffs are handled properly
|
18
|
+
* Deprecated using `Nanoc3::Site#initialize` with a non-`"."` argument
|
19
|
+
* Added Ruby engine to version string
|
20
|
+
* Allowed the `created_at` and `updated_at` attributes used in the`Blogging`
|
21
|
+
helper to be `Date` instances
|
22
|
+
|
23
|
+
## 3.1.4 (2010-07-25)
|
24
|
+
|
25
|
+
* Made INT and TERM signals always quit the CLI
|
26
|
+
* Allowed relative imports in LESS
|
27
|
+
* Made sure modification times are unchanged for identical recompiled items
|
28
|
+
* Improved link validator error handling
|
29
|
+
* Made pygmentize not output extra divs and pres
|
30
|
+
* Allowed colorizers to be specified using symbols instead of strings
|
31
|
+
* Added scss to the default list of text extensions
|
8
32
|
|
9
33
|
## 3.1.3 (2010-04-25)
|
10
34
|
|
data/README.md
CHANGED
@@ -74,9 +74,11 @@ may be interested in the development dependencies:
|
|
74
74
|
* Dmitry Bilunov
|
75
75
|
* Devon Luke Buchanan
|
76
76
|
* Brian Candler
|
77
|
+
* Vincent Driessen
|
77
78
|
* Chris Eppstein
|
78
79
|
* Felix Hanley
|
79
80
|
* Starr Horne
|
81
|
+
* Tuomas Kareinen
|
80
82
|
* Ale Muñoz
|
81
83
|
* Nicky Peeters
|
82
84
|
* Christian Plessl
|
data/lib/nanoc3.rb
CHANGED
@@ -40,6 +40,8 @@ module Nanoc3
|
|
40
40
|
# the specified object.
|
41
41
|
class Compiler
|
42
42
|
|
43
|
+
# @group Accessors
|
44
|
+
|
43
45
|
# @return [Nanoc3::Site] The site this compiler belongs to
|
44
46
|
attr_reader :site
|
45
47
|
|
@@ -68,6 +70,8 @@ module Nanoc3
|
|
68
70
|
# loaded but before the site is compiled
|
69
71
|
attr_accessor :preprocessor
|
70
72
|
|
73
|
+
# @group Public instance methods
|
74
|
+
|
71
75
|
# Creates a new compiler fo the given site
|
72
76
|
#
|
73
77
|
# @param [Nanoc3::Site] site The site this compiler belongs to
|
@@ -96,6 +100,7 @@ module Nanoc3
|
|
96
100
|
|
97
101
|
# Compile reps
|
98
102
|
load
|
103
|
+
@site.freeze
|
99
104
|
dependency_tracker.start
|
100
105
|
compile_reps(reps)
|
101
106
|
dependency_tracker.stop
|
@@ -105,6 +110,8 @@ module Nanoc3
|
|
105
110
|
FileUtils.rm_rf(Nanoc3::Filter::TMP_BINARY_ITEMS_DIR)
|
106
111
|
end
|
107
112
|
|
113
|
+
# @group Private instance methods
|
114
|
+
|
108
115
|
# Load the helper data that is used for compiling the site.
|
109
116
|
#
|
110
117
|
# @api private
|
@@ -114,7 +121,8 @@ module Nanoc3
|
|
114
121
|
return if @loaded
|
115
122
|
@loaded = true
|
116
123
|
|
117
|
-
|
124
|
+
# Load site if necessary
|
125
|
+
@site.load
|
118
126
|
|
119
127
|
# Preprocess
|
120
128
|
load_rules
|
@@ -123,6 +131,9 @@ module Nanoc3
|
|
123
131
|
build_reps
|
124
132
|
route_reps
|
125
133
|
|
134
|
+
# Load auxiliary stores
|
135
|
+
stores.each { |s| s.load }
|
136
|
+
|
126
137
|
# Determine which reps need to be recompiled
|
127
138
|
dependency_tracker.propagate_outdatedness
|
128
139
|
forget_dependencies_if_outdated(items)
|
@@ -260,7 +271,17 @@ module Nanoc3
|
|
260
271
|
preprocessor_context.instance_eval(&preprocessor) if preprocessor
|
261
272
|
end
|
262
273
|
|
263
|
-
#
|
274
|
+
# Returns all objects managed by the site (items, layouts, code snippets,
|
275
|
+
# site configuration and the rules).
|
276
|
+
#
|
277
|
+
# @api private
|
278
|
+
def objects
|
279
|
+
# FIXME remove reference to rules
|
280
|
+
site.items + site.layouts + site.code_snippets + [ site.config, self.rules_with_reference ]
|
281
|
+
end
|
282
|
+
|
283
|
+
# Returns the rules along with an unique reference (`:rules`) so that the
|
284
|
+
# outdatedness checker can use them.
|
264
285
|
#
|
265
286
|
# @api private
|
266
287
|
def rules_with_reference
|
@@ -306,6 +327,9 @@ module Nanoc3
|
|
306
327
|
# Get basic path by applying matching rule
|
307
328
|
basic_path = rule.apply_to(rep, :compiler => self)
|
308
329
|
next if basic_path.nil?
|
330
|
+
if basic_path !~ %r{^/}
|
331
|
+
raise RuntimeError, "The path returned for the #{rep.inspect} item representation, “#{basic_path}”, does not start with a slash. Please ensure that all routing rules return a path that starts with a slash.".make_compatible_with_env
|
332
|
+
end
|
309
333
|
|
310
334
|
# Get raw path by prepending output directory
|
311
335
|
rep.raw_paths[snapshot] = @site.config[:output_dir] + basic_path
|
@@ -328,9 +352,11 @@ module Nanoc3
|
|
328
352
|
#
|
329
353
|
# @return [Hash] The assigns that should be used in the next filter/layout
|
330
354
|
# operation
|
355
|
+
#
|
356
|
+
# @api private
|
331
357
|
def assigns_for(rep)
|
332
358
|
if rep.binary?
|
333
|
-
content_or_filename_assigns = { :filename => rep.
|
359
|
+
content_or_filename_assigns = { :filename => rep.temporary_filenames[:last] }
|
334
360
|
else
|
335
361
|
content_or_filename_assigns = { :content => rep.content[:last] }
|
336
362
|
end
|
@@ -218,7 +218,8 @@ module Nanoc3
|
|
218
218
|
# Load edges
|
219
219
|
new_data[:edges].each do |edge|
|
220
220
|
from_index, to_index = *edge
|
221
|
-
from
|
221
|
+
from = from_index && @previous_objects[from_index]
|
222
|
+
to = to_index && @previous_objects[to_index]
|
222
223
|
@graph.add_edge(from, to)
|
223
224
|
end
|
224
225
|
end
|
@@ -67,6 +67,9 @@ module Nanoc3
|
|
67
67
|
#
|
68
68
|
# @return [void]
|
69
69
|
def add_edge(from, to)
|
70
|
+
add_vertex(from)
|
71
|
+
add_vertex(to)
|
72
|
+
|
70
73
|
@from_graph[from] ||= Set.new
|
71
74
|
@from_graph[from] << to
|
72
75
|
|
@@ -107,6 +110,8 @@ module Nanoc3
|
|
107
110
|
return if @vertices.include?(v)
|
108
111
|
|
109
112
|
@vertices << v
|
113
|
+
@vertice_indexes[v] = @vertices.size-1
|
114
|
+
|
110
115
|
@roots << v
|
111
116
|
end
|
112
117
|
|
@@ -22,20 +22,11 @@ module Nanoc3
|
|
22
22
|
#
|
23
23
|
# @param [String] filename The filename corresponding to this code snippet
|
24
24
|
#
|
25
|
-
# @param [Time, Hash] params Extra parameters.
|
26
|
-
#
|
27
|
-
# this code snippet was last modified (mtime).
|
28
|
-
#
|
29
|
-
# @option params [Time, nil] :mtime (nil) The time when this code snippet
|
30
|
-
# was last modified
|
25
|
+
# @param [Time, Hash] params Extra parameters. Ignored by nanoc; it is
|
26
|
+
# only included for backwards compatibility.
|
31
27
|
def initialize(data, filename, params=nil)
|
32
|
-
# Parse params
|
33
|
-
params ||= {}
|
34
|
-
params = { :mtime => params } if params.is_a?(Time)
|
35
|
-
|
36
28
|
@data = data
|
37
29
|
@filename = filename
|
38
|
-
@mtime = params[:mtime]
|
39
30
|
end
|
40
31
|
|
41
32
|
# Loads the code by executing it.
|
@@ -23,9 +23,6 @@ module Nanoc3
|
|
23
23
|
# @return [String] This item's identifier
|
24
24
|
attr_accessor :identifier
|
25
25
|
|
26
|
-
# @return [Time] The time where this item was last modified
|
27
|
-
attr_reader :mtime
|
28
|
-
|
29
26
|
# @return [Array<Nanoc3::ItemRep>] This item’s list of item reps
|
30
27
|
attr_reader :reps
|
31
28
|
|
@@ -60,7 +57,8 @@ module Nanoc3
|
|
60
57
|
# this item was last modified (mtime).
|
61
58
|
#
|
62
59
|
# @option params [Time, nil] :mtime (nil) The time when this item was last
|
63
|
-
# modified
|
60
|
+
# modified. Deprecated; pass the modification time as the `:mtime`
|
61
|
+
# attribute instead.
|
64
62
|
#
|
65
63
|
# @option params [Symbol, nil] :binary (true) Whether or not this item is
|
66
64
|
# binary
|
@@ -70,9 +68,6 @@ module Nanoc3
|
|
70
68
|
params = { :mtime => params } if params.is_a?(Time)
|
71
69
|
params[:binary] = false unless params.has_key?(:binary)
|
72
70
|
|
73
|
-
# Get mtime
|
74
|
-
@mtime = params[:mtime]
|
75
|
-
|
76
71
|
# Get type and raw content or raw filename
|
77
72
|
@is_binary = params[:binary]
|
78
73
|
if @is_binary
|
@@ -85,6 +80,9 @@ module Nanoc3
|
|
85
80
|
@attributes = attributes.symbolize_keys
|
86
81
|
@identifier = identifier.cleaned_identifier
|
87
82
|
|
83
|
+
# Set mtime
|
84
|
+
@attributes.merge(:mtime => params[:mtime]) if params[:mtime]
|
85
|
+
|
88
86
|
@parent = nil
|
89
87
|
@children = []
|
90
88
|
|
@@ -163,6 +161,19 @@ module Nanoc3
|
|
163
161
|
Nanoc3::NotificationCenter.post(:visit_started, self)
|
164
162
|
Nanoc3::NotificationCenter.post(:visit_ended, self)
|
165
163
|
|
164
|
+
# Get captured content (hax)
|
165
|
+
# TODO [in nanoc 4.0] remove me
|
166
|
+
if key.to_s =~ /^content_for_(.*)$/
|
167
|
+
# Include capturing helper if necessary
|
168
|
+
unless @_Nanoc3_Helpers_Capturing_included
|
169
|
+
self.class.send(:include, ::Nanoc3::Helpers::Capturing)
|
170
|
+
@_Nanoc3_Helpers_Capturing_included = true
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get content
|
174
|
+
return content_for(self, $1.to_sym)
|
175
|
+
end
|
176
|
+
|
166
177
|
@attributes[key]
|
167
178
|
end
|
168
179
|
|
@@ -199,10 +210,21 @@ module Nanoc3
|
|
199
210
|
[ type, self.identifier ]
|
200
211
|
end
|
201
212
|
|
213
|
+
# Prevents all further modifications to itself, its items, its layouts etc.
|
214
|
+
#
|
215
|
+
# @return [void]
|
216
|
+
def freeze
|
217
|
+
attributes.freeze
|
218
|
+
end
|
202
219
|
def inspect
|
203
220
|
"<#{self.class}:0x#{self.object_id.to_s(16)} identifier=#{self.identifier} binary?=#{self.binary?}>"
|
204
221
|
end
|
205
222
|
|
223
|
+
# @deprecated Access the modification time using `item[:mtime]` instead.
|
224
|
+
def mtime
|
225
|
+
self[:mtime]
|
226
|
+
end
|
227
|
+
|
206
228
|
end
|
207
229
|
|
208
230
|
end
|
@@ -16,9 +16,6 @@ module Nanoc3
|
|
16
16
|
# slash
|
17
17
|
attr_accessor :identifier
|
18
18
|
|
19
|
-
# @return [Time] The time where this layout was last modified
|
20
|
-
attr_reader :mtime
|
21
|
-
|
22
19
|
# Creates a new layout.
|
23
20
|
#
|
24
21
|
# @param [String] raw_content The raw content of this layout.
|
@@ -32,18 +29,17 @@ module Nanoc3
|
|
32
29
|
# this layout was last modified (mtime).
|
33
30
|
#
|
34
31
|
# @option params [Time, nil] :mtime (nil) The time when this layout was
|
35
|
-
# last modified
|
32
|
+
# last modified. Deprecated; pass the modification time as the `:mtime`
|
33
|
+
# attribute instead.
|
36
34
|
def initialize(raw_content, attributes, identifier, params=nil)
|
37
|
-
# Parse params
|
38
|
-
params ||= {}
|
39
|
-
params = { :mtime => params } if params.is_a?(Time)
|
40
|
-
|
41
|
-
# Get mtime
|
42
|
-
@mtime = params[:mtime]
|
43
|
-
|
44
35
|
@raw_content = raw_content
|
45
36
|
@attributes = attributes.symbolize_keys
|
46
37
|
@identifier = identifier.cleaned_identifier
|
38
|
+
|
39
|
+
# Set mtime
|
40
|
+
params ||= {}
|
41
|
+
params = { :mtime => params } if params.is_a?(Time)
|
42
|
+
@attributes.merge(:mtime => params[:mtime]) if params[:mtime]
|
47
43
|
end
|
48
44
|
|
49
45
|
# Requests the attribute with the given key.
|
@@ -78,6 +74,11 @@ module Nanoc3
|
|
78
74
|
"<#{self.class}:0x#{self.object_id.to_s(16)} identifier=#{self.identifier}>"
|
79
75
|
end
|
80
76
|
|
77
|
+
# @deprecated Access the modification time using `layout[:mtime]` instead.
|
78
|
+
def mtime
|
79
|
+
self[:mtime]
|
80
|
+
end
|
81
|
+
|
81
82
|
end
|
82
83
|
|
83
84
|
end
|
@@ -208,12 +208,16 @@ module Nanoc3
|
|
208
208
|
end
|
209
209
|
end
|
210
210
|
|
211
|
-
#
|
211
|
+
# Prevents all further modifications to itself, its items, its layouts etc.
|
212
212
|
#
|
213
|
-
# @
|
214
|
-
def
|
215
|
-
|
216
|
-
|
213
|
+
# @return [void]
|
214
|
+
def freeze
|
215
|
+
super
|
216
|
+
|
217
|
+
config.freeze
|
218
|
+
items.each { |i| i.freeze }
|
219
|
+
layouts.each { |l| l.freeze }
|
220
|
+
code_snippets.each { |cs| cs.freeze }
|
217
221
|
end
|
218
222
|
|
219
223
|
# @deprecated It is no longer necessary to explicitly load site data. It
|
@@ -222,10 +226,12 @@ module Nanoc3
|
|
222
226
|
warn 'It is no longer necessary to call Nanoc3::Site#load_data. This method no longer has any effect. All calls to this method can be safely removed.'
|
223
227
|
end
|
224
228
|
|
225
|
-
private
|
226
|
-
|
227
229
|
# Loads the site data. It is not necessary to call this method explicitly;
|
228
230
|
# it will be called when it is necessary.
|
231
|
+
#
|
232
|
+
# @api private
|
233
|
+
#
|
234
|
+
# @return [void]
|
229
235
|
def load
|
230
236
|
return if @data_loaded
|
231
237
|
@data_loaded = true
|
@@ -243,6 +249,8 @@ module Nanoc3
|
|
243
249
|
compiler.load
|
244
250
|
end
|
245
251
|
|
252
|
+
private
|
253
|
+
|
246
254
|
# Loads this site’s code and executes it.
|
247
255
|
def load_code_snippets
|
248
256
|
@code_snippets_loaded ||= false
|
@@ -296,6 +304,11 @@ module Nanoc3
|
|
296
304
|
# {#initialize} for details.
|
297
305
|
def build_config(dir_or_config_hash)
|
298
306
|
if dir_or_config_hash.is_a? String
|
307
|
+
# Check whether it is supported
|
308
|
+
if dir_or_config_hash != '.'
|
309
|
+
warn 'WARNING: Calling Nanoc3::Site.new with a directory that is not the current working directory is not supported. It is recommended to change the directory before calling Nanoc3::Site.new. For example, instead of Nanoc3::Site.new(\'abc\'), use Dir.chdir(\'abc\') { Nanoc3::Site.new(\'.\') }.'
|
310
|
+
end
|
311
|
+
|
299
312
|
# Read config from config.yaml in given dir
|
300
313
|
config_path = File.join(dir_or_config_hash, 'config.yaml')
|
301
314
|
@config = DEFAULT_CONFIG.merge(YAML.load_file(config_path).symbolize_keys)
|
data/lib/nanoc3/cli/base.rb
CHANGED
@@ -55,6 +55,11 @@ module Nanoc3::CLI
|
|
55
55
|
add_command(Nanoc3::CLI::Commands::Watch.new)
|
56
56
|
end
|
57
57
|
|
58
|
+
# Returns a fully initialised base instance. It is recommended to use this
|
59
|
+
# shared instance than to create new ones, as this will be the instance
|
60
|
+
# that will be used when reading all code from the `lib/` directory.
|
61
|
+
#
|
62
|
+
# @return [Nanoc3::CLI::Base]
|
58
63
|
def self.shared_base
|
59
64
|
@shared_base ||= Nanoc3::CLI::Base.new
|
60
65
|
end
|
@@ -64,8 +69,11 @@ module Nanoc3::CLI
|
|
64
69
|
@debug
|
65
70
|
end
|
66
71
|
|
67
|
-
#
|
68
|
-
#
|
72
|
+
# Asserts that the current working directory contains a site
|
73
|
+
# ({Nanoc3::Site} instance). If no site is present, prints an error
|
74
|
+
# message and exits.
|
75
|
+
#
|
76
|
+
# @return [void]
|
69
77
|
def require_site
|
70
78
|
if site.nil?
|
71
79
|
$stderr.puts 'The current working directory does not seem to be a ' +
|
@@ -74,7 +82,10 @@ module Nanoc3::CLI
|
|
74
82
|
end
|
75
83
|
end
|
76
84
|
|
77
|
-
# Gets the site (Nanoc3::Site) in the current directory and
|
85
|
+
# Gets the site ({Nanoc3::Site} instance) in the current directory and
|
86
|
+
# loads its data.
|
87
|
+
#
|
88
|
+
# @return [Nanoc3::Site] The site in the current working directory
|
78
89
|
def site
|
79
90
|
# Load site if possible
|
80
91
|
if File.file?('config.yaml') && (!self.instance_variable_defined?(:@site) || @site.nil?)
|
@@ -89,8 +100,16 @@ module Nanoc3::CLI
|
|
89
100
|
@site
|
90
101
|
end
|
91
102
|
|
92
|
-
#
|
103
|
+
# @see ::Cri::Base#run
|
93
104
|
def run(args)
|
105
|
+
# Set exit handler
|
106
|
+
[ 'INT', 'TERM' ].each do |signal|
|
107
|
+
Signal.trap(signal) do
|
108
|
+
puts
|
109
|
+
exit!(0)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
94
113
|
super(args)
|
95
114
|
rescue Interrupt => e
|
96
115
|
exit(1)
|
@@ -99,8 +118,12 @@ module Nanoc3::CLI
|
|
99
118
|
exit(1)
|
100
119
|
end
|
101
120
|
|
102
|
-
# Prints the given error to stderr. Includes message, possible resolution
|
103
|
-
# compilation stack, backtrace, etc.
|
121
|
+
# Prints the given error to stderr. Includes message, possible resolution
|
122
|
+
# (see {#resolution_for}), compilation stack, backtrace, etc.
|
123
|
+
#
|
124
|
+
# @param [Error] error The error that should be described
|
125
|
+
#
|
126
|
+
# @return [void]
|
104
127
|
def print_error(error)
|
105
128
|
$stderr.puts
|
106
129
|
|
@@ -144,8 +167,12 @@ module Nanoc3::CLI
|
|
144
167
|
$stderr.puts error.backtrace.to_enum(:each_with_index).map { |item, index| " #{index}. #{item}" }.join("\n")
|
145
168
|
end
|
146
169
|
|
147
|
-
#
|
148
|
-
#
|
170
|
+
# Attempts to find a resolution for the given error, or nil if no
|
171
|
+
# resolution can be automatically obtained.
|
172
|
+
#
|
173
|
+
# @param [Error] error The error to find a resolution for
|
174
|
+
#
|
175
|
+
# @return [String] The resolution for the given error
|
149
176
|
def resolution_for(error)
|
150
177
|
case error
|
151
178
|
when LoadError
|
@@ -157,12 +184,22 @@ module Nanoc3::CLI
|
|
157
184
|
if gem_name
|
158
185
|
"Try installing the '#{gem_name}' gem (`gem install #{gem_name}`) and then re-running the command."
|
159
186
|
end
|
187
|
+
when RuntimeError
|
188
|
+
if error.message =~ /^can't modify frozen/
|
189
|
+
"You attempted to modify immutable data. Some data, such as " \
|
190
|
+
"item/layout attributes and raw item/layout content, can no " \
|
191
|
+
"longer be modified once compilation has started."
|
192
|
+
end
|
160
193
|
end
|
161
194
|
end
|
162
195
|
|
163
196
|
# Sets the data source's VCS to the VCS with the given name. Does nothing
|
164
197
|
# when the site's data source does not support VCSes (i.e. does not
|
165
198
|
# implement #vcs=).
|
199
|
+
#
|
200
|
+
# @param [String] vcs_name The name of the VCS that should be used
|
201
|
+
#
|
202
|
+
# @return [void]
|
166
203
|
def set_vcs(vcs_name)
|
167
204
|
# Skip if not possible
|
168
205
|
return if vcs_name.nil? || site.nil?
|
@@ -183,13 +220,17 @@ module Nanoc3::CLI
|
|
183
220
|
end
|
184
221
|
end
|
185
222
|
|
186
|
-
#
|
223
|
+
# @return [Array] The list of global option definitions
|
187
224
|
def global_option_definitions
|
188
225
|
[
|
189
226
|
{
|
190
227
|
:long => 'help', :short => 'h', :argument => :forbidden,
|
191
228
|
:desc => 'show this help message and quit'
|
192
229
|
},
|
230
|
+
{
|
231
|
+
:long => 'color', :short => 'l', :argument => :forbidden,
|
232
|
+
:desc => 'enable color'
|
233
|
+
},
|
193
234
|
{
|
194
235
|
:long => 'no-color', :short => 'C', :argument => :forbidden,
|
195
236
|
:desc => 'disable color'
|
@@ -213,13 +254,15 @@ module Nanoc3::CLI
|
|
213
254
|
]
|
214
255
|
end
|
215
256
|
|
257
|
+
# @see Cri::Base#handle_option
|
216
258
|
def handle_option(option)
|
217
259
|
case option
|
218
260
|
when :version
|
219
261
|
gem_info = defined?(Gem) ? "with RubyGems #{Gem::VERSION}" : "without RubyGems"
|
262
|
+
engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
|
220
263
|
|
221
264
|
puts "nanoc #{Nanoc3::VERSION} (c) 2007-2010 Denis Defreyne."
|
222
|
-
puts "
|
265
|
+
puts "Running #{engine} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) on #{RUBY_PLATFORM} #{gem_info}"
|
223
266
|
exit 0
|
224
267
|
when :verbose
|
225
268
|
Nanoc3::CLI::Logger.instance.level = :low
|
@@ -227,6 +270,8 @@ module Nanoc3::CLI
|
|
227
270
|
@debug = true
|
228
271
|
when :warn
|
229
272
|
$-w = true
|
273
|
+
when :color
|
274
|
+
Nanoc3::CLI::Logger.instance.color = true
|
230
275
|
when :'no-color'
|
231
276
|
Nanoc3::CLI::Logger.instance.color = false
|
232
277
|
when :help
|
@@ -53,7 +53,7 @@ module Nanoc3::CLI::Commands
|
|
53
53
|
puts "item #{item.identifier} depends on:"
|
54
54
|
predecessors = dependency_tracker.direct_predecessors_of(item).sort_by { |i| i.identifier }
|
55
55
|
predecessors.each do |pred|
|
56
|
-
puts " #{pred.identifier}"
|
56
|
+
puts " [ #{format '%6s', pred.type} ] #{pred.identifier}"
|
57
57
|
end
|
58
58
|
puts " (nothing)" if predecessors.empty?
|
59
59
|
puts
|
@@ -31,11 +31,7 @@ module Nanoc3::CLI::Commands
|
|
31
31
|
|
32
32
|
def run(options, arguments)
|
33
33
|
require 'fssm'
|
34
|
-
|
35
|
-
Signal.trap("INT") do
|
36
|
-
puts
|
37
|
-
exit
|
38
|
-
end
|
34
|
+
require 'pathname'
|
39
35
|
|
40
36
|
@notifier = Notifier.new
|
41
37
|
|
@@ -119,7 +115,7 @@ module Nanoc3::CLI::Commands
|
|
119
115
|
# @param [String] message The message to include in the notification
|
120
116
|
def notify(message)
|
121
117
|
return if tool.nil?
|
122
|
-
send(tool.tr('-', '_'), message
|
118
|
+
send(tool.tr('-', '_'), message)
|
123
119
|
end
|
124
120
|
|
125
121
|
private
|
@@ -128,11 +124,11 @@ module Nanoc3::CLI::Commands
|
|
128
124
|
@tool ||= TOOLS.find { |t| !`which #{t}`.empty? }
|
129
125
|
end
|
130
126
|
|
131
|
-
def growlnotify(message
|
127
|
+
def growlnotify(message)
|
132
128
|
system('growlnotify', '-m', message)
|
133
129
|
end
|
134
130
|
|
135
|
-
def notify_send(message
|
131
|
+
def notify_send(message)
|
136
132
|
system('notify-send', message)
|
137
133
|
end
|
138
134
|
|
data/lib/nanoc3/cli/logger.rb
CHANGED
@@ -8,6 +8,8 @@ module Nanoc3::CLI
|
|
8
8
|
# feedback in the terminal.
|
9
9
|
class Logger
|
10
10
|
|
11
|
+
# Maps actions (`:create`, `:update`, `:identical` and `:skip`) onto their
|
12
|
+
# ANSI color codes.
|
11
13
|
ACTION_COLORS = {
|
12
14
|
:create => "\e[1m" + "\e[32m", # bold + green
|
13
15
|
:update => "\e[1m" + "\e[33m", # bold + yellow
|
@@ -17,35 +19,43 @@ module Nanoc3::CLI
|
|
17
19
|
|
18
20
|
include Singleton
|
19
21
|
|
20
|
-
#
|
21
|
-
# messages, only high-priority messages, or no messages at all,
|
22
|
+
# Returns the log level, which can be :high, :low or :off (which will log
|
23
|
+
# all messages, only high-priority messages, or no messages at all,
|
22
24
|
# respectively).
|
25
|
+
#
|
26
|
+
# @return [Symbol] The log level
|
23
27
|
attr_accessor :level
|
24
28
|
|
25
|
-
#
|
26
|
-
|
27
|
-
alias_method :color?, :color
|
29
|
+
# @return [Boolean] True if color should be used, false otherwise
|
30
|
+
attr_writer :color
|
28
31
|
|
29
32
|
def initialize
|
30
33
|
@level = :high
|
31
|
-
|
34
|
+
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
# @return [Boolean] true if colors are enabled, false otherwise
|
37
|
+
def color?
|
38
|
+
if @color.nil?
|
39
|
+
@color = true
|
40
|
+
begin
|
41
|
+
require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /mswin|mingw/
|
42
|
+
rescue LoadError
|
43
|
+
@color = false
|
44
|
+
end
|
38
45
|
end
|
46
|
+
|
47
|
+
@color
|
39
48
|
end
|
40
49
|
|
41
50
|
# Logs a file-related action.
|
42
51
|
#
|
43
|
-
#
|
52
|
+
# @param [:high, :low] level The importance of this action
|
44
53
|
#
|
45
|
-
#
|
46
|
-
# :identical.
|
54
|
+
# @param [:create, :update, :identical] action The kind of file action
|
47
55
|
#
|
48
|
-
#
|
56
|
+
# @param [String] name The name of the file the action was performed on
|
57
|
+
#
|
58
|
+
# @return [void]
|
49
59
|
def file(level, action, identifier, duration=nil)
|
50
60
|
log(
|
51
61
|
level,
|
@@ -61,18 +71,19 @@ module Nanoc3::CLI
|
|
61
71
|
|
62
72
|
# Logs a message.
|
63
73
|
#
|
64
|
-
#
|
74
|
+
# @param [:high, :low] level The importance of this message
|
75
|
+
#
|
76
|
+
# @param [String] message The message to be logged
|
65
77
|
#
|
66
|
-
#
|
78
|
+
# @param [#puts] io The stream to which the message should be written
|
67
79
|
#
|
68
|
-
#
|
69
|
-
|
70
|
-
def log(level, s, io=$stdout)
|
80
|
+
# @return [void]
|
81
|
+
def log(level, message, io=$stdout)
|
71
82
|
# Don't log when logging is disabled
|
72
83
|
return if @level == :off
|
73
84
|
|
74
85
|
# Log when level permits it
|
75
|
-
io.puts(
|
86
|
+
io.puts(message) if (@level == :low or @level == level)
|
76
87
|
end
|
77
88
|
|
78
89
|
end
|
@@ -107,8 +107,23 @@ module Nanoc3::Filters
|
|
107
107
|
code
|
108
108
|
end
|
109
109
|
|
110
|
+
# Runs the content through [pygmentize](http://pygments.org/docs/cmdline/),
|
111
|
+
# the commandline frontend for [Pygments](http://pygments.org/).
|
112
|
+
#
|
113
|
+
# @api private
|
114
|
+
#
|
115
|
+
# @param [String] code The code to colorize
|
116
|
+
#
|
117
|
+
# @param [String] language The language the code is written in
|
118
|
+
#
|
119
|
+
# @option params [String, Symbol] :encoding The encoding of the code block
|
120
|
+
#
|
121
|
+
# @return [String] The colorized output
|
110
122
|
def pygmentize(code, language, params={})
|
111
|
-
|
123
|
+
enc = ""
|
124
|
+
enc = "-O encoding=" + params[:encoding] if params[:encoding]
|
125
|
+
|
126
|
+
IO.popen("pygmentize -l #{language} -f html #{enc}", "r+") do |io|
|
112
127
|
io.write(code)
|
113
128
|
io.close_write
|
114
129
|
highlighted_code = io.read
|
@@ -3,8 +3,22 @@
|
|
3
3
|
module Nanoc3::Filters
|
4
4
|
class RedCloth < Nanoc3::Filter
|
5
5
|
|
6
|
-
# Runs the content through [RedCloth](http://redcloth.org/).
|
7
|
-
#
|
6
|
+
# Runs the content through [RedCloth](http://redcloth.org/). This method
|
7
|
+
# takes the following options:
|
8
|
+
#
|
9
|
+
# * `:filter_class`
|
10
|
+
# * `:filter_html`
|
11
|
+
# * `:filter_ids`
|
12
|
+
# * `:filter_style`
|
13
|
+
# * `:hard_breaks`
|
14
|
+
# * `:lite_mode`
|
15
|
+
# * `:no_span_caps`
|
16
|
+
# * `:sanitize_htm`
|
17
|
+
#
|
18
|
+
# Each of these options sets the corresponding attribute on the `RedCloth`
|
19
|
+
# instance. For example, when the `:hard_breaks => false` option is passed
|
20
|
+
# to this filter, the filter will call `r.hard_breaks = false` (with `r`
|
21
|
+
# being the `RedCloth` instance).
|
8
22
|
#
|
9
23
|
# @param [String] content The content to filter
|
10
24
|
#
|
@@ -12,8 +26,21 @@ module Nanoc3::Filters
|
|
12
26
|
def run(content, params={})
|
13
27
|
require 'redcloth'
|
14
28
|
|
29
|
+
# Create formatter
|
30
|
+
r = ::RedCloth.new(content)
|
31
|
+
|
32
|
+
# Set options
|
33
|
+
r.filter_classes = params[:filter_classes] if params.has_key?(:filter_classes)
|
34
|
+
r.filter_html = params[:filter_html] if params.has_key?(:filter_html)
|
35
|
+
r.filter_ids = params[:filter_ids] if params.has_key?(:filter_ids)
|
36
|
+
r.filter_styles = params[:filter_styles] if params.has_key?(:filter_styles)
|
37
|
+
r.hard_breaks = params[:hard_breaks] if params.has_key?(:hard_breaks)
|
38
|
+
r.lite_mode = params[:lite_mode] if params.has_key?(:lite_mode)
|
39
|
+
r.no_span_caps = params[:no_span_caps] if params.has_key?(:no_span_caps)
|
40
|
+
r.sanitize_html = params[:sanitize_html] if params.has_key?(:sanitize_html)
|
41
|
+
|
15
42
|
# Get result
|
16
|
-
|
43
|
+
r.to_html
|
17
44
|
end
|
18
45
|
|
19
46
|
end
|
@@ -39,8 +39,7 @@ module Nanoc3::Helpers
|
|
39
39
|
def sorted_articles
|
40
40
|
require 'time'
|
41
41
|
articles.sort_by do |a|
|
42
|
-
|
43
|
-
time.is_a?(String) ? Time.parse(time) : time
|
42
|
+
attribute_to_time(a[:created_at])
|
44
43
|
end.reverse
|
45
44
|
end
|
46
45
|
|
@@ -183,8 +182,7 @@ module Nanoc3::Helpers
|
|
183
182
|
|
184
183
|
# Get sorted relevant articles
|
185
184
|
sorted_relevant_articles = relevant_articles.sort_by do |a|
|
186
|
-
|
187
|
-
time.is_a?(String) ? Time.parse(time) : time
|
185
|
+
attribute_to_time(a[:created_at])
|
188
186
|
end.reverse.first(limit)
|
189
187
|
|
190
188
|
# Get most recent article
|
@@ -204,8 +202,7 @@ module Nanoc3::Helpers
|
|
204
202
|
xml.title title
|
205
203
|
|
206
204
|
# Add date
|
207
|
-
|
208
|
-
xml.updated((time.is_a?(String) ? Time.parse(time) : time).to_iso8601_time)
|
205
|
+
xml.updated(attribute_to_time(last_article[:created_at]).to_iso8601_time)
|
209
206
|
|
210
207
|
# Add links
|
211
208
|
xml.link(:rel => 'alternate', :href => root_url)
|
@@ -229,10 +226,8 @@ module Nanoc3::Helpers
|
|
229
226
|
xml.title a[:title], :type => 'html'
|
230
227
|
|
231
228
|
# Add dates
|
232
|
-
|
233
|
-
|
234
|
-
xml.published((create_time.is_a?(String) ? Time.parse(create_time) : create_time).to_iso8601_time)
|
235
|
-
xml.updated( (update_time.is_a?(String) ? Time.parse(update_time) : update_time).to_iso8601_time)
|
229
|
+
xml.published attribute_to_time(a[:created_at]).to_iso8601_time
|
230
|
+
xml.updated attribute_to_time(a[:updated_at] || a[:created_at]).to_iso8601_time
|
236
231
|
|
237
232
|
# Add specific author information
|
238
233
|
if a[:author_name] || a[:author_uri]
|
@@ -305,12 +300,24 @@ module Nanoc3::Helpers
|
|
305
300
|
|
306
301
|
hostname, base_dir = %r{^.+?://([^/]+)(.*)$}.match(@site.config[:base_url])[1..2]
|
307
302
|
|
308
|
-
|
309
|
-
formatted_date = (time.is_a?(String) ? Time.parse(time) : time).to_iso8601_date
|
303
|
+
formatted_date = attribute_to_time(item[:created_at]).to_iso8601_date
|
310
304
|
|
311
305
|
'tag:' + hostname + ',' + formatted_date + ':' + base_dir + (item.path || item.identifier)
|
312
306
|
end
|
313
307
|
|
308
|
+
# Converts the given attribute (which can be a string, a Time or a Date)
|
309
|
+
# into a Time.
|
310
|
+
#
|
311
|
+
# @param [String, Time, Date] time Something that contains time
|
312
|
+
# information but is not necessarily a Time instance yet
|
313
|
+
#
|
314
|
+
# @return [Time] The Time instance corresponding to the given input
|
315
|
+
def attribute_to_time(time)
|
316
|
+
time = Time.local(time.year, time.month, time.day) if time.is_a?(Date)
|
317
|
+
time = Time.parse(time) if time.is_a?(String)
|
318
|
+
time
|
319
|
+
end
|
320
|
+
|
314
321
|
end
|
315
322
|
|
316
323
|
end
|
@@ -12,7 +12,10 @@ module Nanoc3::Helpers
|
|
12
12
|
# you write the summary on the item itself, but capture it, and print it in
|
13
13
|
# the sidebar layout.
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# This helper has been tested with ERB and Haml. Other filters may not work
|
16
|
+
# correctly.
|
17
|
+
#
|
18
|
+
# @example Capturing content for a summary
|
16
19
|
#
|
17
20
|
# <% content_for :summary do %>
|
18
21
|
# <p>On this item, nanoc is introduced, blah blah.</p>
|
@@ -22,28 +25,95 @@ module Nanoc3::Helpers
|
|
22
25
|
#
|
23
26
|
# <div id="sidebar">
|
24
27
|
# <h3>Summary</h3>
|
28
|
+
# <%= content_for(@item, :summary) || '(no summary)' %>
|
29
|
+
# </div>
|
30
|
+
#
|
31
|
+
# @example Showing captured content in a sidebar the old, deprecated way (do not use or I will become very angry)
|
32
|
+
#
|
33
|
+
# <div id="sidebar">
|
34
|
+
# <h3>Summary</h3>
|
25
35
|
# <%= @item[:content_for_summary] || '(no summary)' %>
|
26
36
|
# </div>
|
27
37
|
module Capturing
|
28
38
|
|
29
|
-
#
|
30
|
-
|
31
|
-
|
39
|
+
# @api private
|
40
|
+
class CapturesStore
|
41
|
+
|
42
|
+
require 'singleton'
|
43
|
+
include Singleton
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@store = {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def []=(item, name, content)
|
50
|
+
@store[item.identifier] ||= {}
|
51
|
+
@store[item.identifier][name] = content
|
52
|
+
end
|
53
|
+
|
54
|
+
def [](item, name)
|
55
|
+
@store[item.identifier] ||= {}
|
56
|
+
@store[item.identifier][name]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
# @overload content_for(name, &block)
|
62
|
+
#
|
63
|
+
# Captures the content inside the block and stores it so that it can be
|
64
|
+
# referenced later on. The same method, {#content_for}, is used for
|
65
|
+
# getting the captured content as well as setting it. When capturing,
|
66
|
+
# the content of the block itself will not be outputted.
|
67
|
+
#
|
68
|
+
# For backwards compatibility, it is also possible to fetch the captured
|
69
|
+
# content by getting the contents of the attribute named `content_for_`
|
70
|
+
# followed by the given name. This way of accessing captures is
|
71
|
+
# deprecated.
|
72
|
+
#
|
73
|
+
# @param [Symbol, String] name The base name of the attribute into which
|
74
|
+
# the content should be stored
|
75
|
+
#
|
76
|
+
# @return [void]
|
77
|
+
#
|
78
|
+
# @overload content_for(item, name)
|
32
79
|
#
|
33
|
-
#
|
34
|
-
#
|
80
|
+
# Fetches the capture with the given name from the given item and
|
81
|
+
# returns it.
|
35
82
|
#
|
36
|
-
#
|
37
|
-
|
38
|
-
|
83
|
+
# @param [Nanoc3::Item] item The item for which to get the capture
|
84
|
+
#
|
85
|
+
# @param [Symbol, String] name The name of the capture to fetch
|
86
|
+
#
|
87
|
+
# @return [String] The stored captured content
|
88
|
+
def content_for(*args, &block)
|
89
|
+
if block_given? # Set content
|
90
|
+
# Get args
|
91
|
+
if args.size != 1
|
92
|
+
raise ArgumentError, "expected 1 argument (the name " +
|
93
|
+
"of the capture) but got #{args.size} instead"
|
94
|
+
end
|
95
|
+
name = args[0]
|
96
|
+
|
97
|
+
# Capture and store
|
98
|
+
content = capture(&block)
|
99
|
+
CapturesStore.instance[@item, name.to_sym] = content
|
100
|
+
else # Get content
|
101
|
+
# Get args
|
102
|
+
if args.size != 2
|
103
|
+
raise ArgumentError, "expected 2 arguments (the item " +
|
104
|
+
"and the name of the capture) but got #{args.size} instead"
|
105
|
+
end
|
106
|
+
item = args[0]
|
107
|
+
name = args[1]
|
108
|
+
|
109
|
+
# Get content
|
110
|
+
CapturesStore.instance[item, name.to_sym]
|
111
|
+
end
|
39
112
|
end
|
40
113
|
|
41
|
-
# Evaluates the given block and returns
|
114
|
+
# Evaluates the given block and returns its contents. The contents of the
|
42
115
|
# block is not outputted.
|
43
116
|
#
|
44
|
-
# This function has been tested with ERB and Haml. Other filters may not
|
45
|
-
# work correctly.
|
46
|
-
#
|
47
117
|
# @return [String] The captured result
|
48
118
|
def capture(&block)
|
49
119
|
# Get erbout so far
|
@@ -7,7 +7,18 @@ module Nanoc3::Helpers
|
|
7
7
|
|
8
8
|
include Nanoc3::Helpers::Capturing
|
9
9
|
|
10
|
-
# Returns a string containing the rendered given layout.
|
10
|
+
# Returns a string containing the rendered given layout. The given layout
|
11
|
+
# will first be run through the matching layout rule.
|
12
|
+
#
|
13
|
+
# The assigns (`@item`, `@config`, …) will not be available in the
|
14
|
+
# partial, but it is possible to pass custom assigns to the method. These
|
15
|
+
# assigns will be made available as instance variables inside the partial.
|
16
|
+
#
|
17
|
+
# The method can also take a block. In this case, the content of the block
|
18
|
+
# will be captured (using the {Nanoc3::Helpers::Capturing} helper) and
|
19
|
+
# this content will be made available with `yield`. In other words, a
|
20
|
+
# `yield` inside the partial will output the content of the block passed
|
21
|
+
# to the method.
|
11
22
|
#
|
12
23
|
# @param [String] identifier The identifier of the layout that should be
|
13
24
|
# rendered
|
@@ -29,6 +40,18 @@ module Nanoc3::Helpers
|
|
29
40
|
# <%= render 'head', :title => 'Foo' %>
|
30
41
|
# # => "<h1>Foo</h1>"
|
31
42
|
#
|
43
|
+
# @example Yielding inside a partial
|
44
|
+
#
|
45
|
+
# # The 'box' partial
|
46
|
+
# <div class="box">
|
47
|
+
# <%= yield %>
|
48
|
+
# </div>
|
49
|
+
#
|
50
|
+
# # The item/layout where the partial is rendered
|
51
|
+
# <% render 'box' do %>
|
52
|
+
# I'm boxy! Luvz!
|
53
|
+
# <% end %>
|
54
|
+
#
|
32
55
|
# @raise [Nanoc3::Errors::UnknownLayout] if the given layout does not
|
33
56
|
# exist
|
34
57
|
#
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nanoc3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: -
|
4
|
+
hash: -794993270
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 3.2.
|
9
|
+
- 0a3
|
10
|
+
version: 3.2.0a3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Denis Defreyne
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-08-24 00:00:00 +02:00
|
19
19
|
default_executable: nanoc3
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|