nanoc3 3.1.0b2 → 3.1.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/nanoc3/base/errors.rb +2 -2
- data/lib/nanoc3/base/item_rep.rb +74 -36
- data/lib/nanoc3/base/site.rb +13 -4
- data/lib/nanoc3/cli/commands/create_site.rb +5 -0
- data/lib/nanoc3/cli/commands/debug.rb +28 -14
- data/lib/nanoc3/filters/sass.rb +49 -2
- data/lib/nanoc3.rb +1 -1
- metadata +3 -3
data/lib/nanoc3/base/errors.rb
CHANGED
@@ -144,7 +144,7 @@ module Nanoc3
|
|
144
144
|
# @param [Nanoc3::ItemRep] The item representation that was attempted to
|
145
145
|
# be laid out
|
146
146
|
def initialize(rep)
|
147
|
-
super("The “{rep.item.identifier}” item (rep “#{rep.name}”) cannot be laid out because it is a binary item.".make_compatible_with_env)
|
147
|
+
super("The “{rep.item.identifier}” item (rep “#{rep.name}”) cannot be laid out because it is a binary item. If you are getting this error for an item that should be textual instead of binary, make sure that its extension is included in the text_extensions array in the site configuration.".make_compatible_with_env)
|
148
148
|
end
|
149
149
|
|
150
150
|
end
|
@@ -172,7 +172,7 @@ module Nanoc3
|
|
172
172
|
#
|
173
173
|
# @param [Class] filter_class The filter class that was used
|
174
174
|
def initialize(rep, filter_class)
|
175
|
-
super("The “#{filter_class.inspect}” filter cannot be used to filter the “#{rep.item.identifier}” item (rep “#{rep.name}”), because binary filters cannot be used on textual items.".make_compatible_with_env)
|
175
|
+
super("The “#{filter_class.inspect}” filter cannot be used to filter the “#{rep.item.identifier}” item (rep “#{rep.name}”), because binary filters cannot be used on textual items. If you are getting this error for an item that should be textual instead of binary, make sure that its extension is included in the text_extensions array in the site configuration.".make_compatible_with_env)
|
176
176
|
end
|
177
177
|
|
178
178
|
end
|
data/lib/nanoc3/base/item_rep.rb
CHANGED
@@ -20,6 +20,20 @@ module Nanoc3
|
|
20
20
|
# representation, and a symbol containing the filter class name).
|
21
21
|
class ItemRep
|
22
22
|
|
23
|
+
# The descriptive strings for each outdatedness reason. This hash is used
|
24
|
+
# by the {#outdatedness_reason} method.
|
25
|
+
OUTDATEDNESS_REASON_DESCRIPTIONS = {
|
26
|
+
:no_mtime => 'No file modification time is available.',
|
27
|
+
:forced => 'All pages are recompiled because of a `--force` flag given to the compilation command.',
|
28
|
+
:no_raw_path => 'The routing rules do not specify a path where this item should be written to, i.e. the item representation will never be written to the output directory.',
|
29
|
+
:not_written => 'This item representation has not yet been written to the output directory (but it does have a path).',
|
30
|
+
:source_modified => 'The source file of this item has been modified since the last time this item representation was compiled.',
|
31
|
+
:layouts_outdated => 'The source of one or more layouts has been modified since the last time this item representation was compiled.',
|
32
|
+
:code_outdated => 'The code snippets in the `lib/` directory have been modified since the last time this item representation was compiled.',
|
33
|
+
:config_outdated => 'The site configuration has been modified since the last time this item representation was compiled.',
|
34
|
+
:rules_outdated => 'The rules file has been modified since the last time this item representation was compiled.',
|
35
|
+
}
|
36
|
+
|
23
37
|
# @return [Nanoc3::Item] The item to which this rep belongs
|
24
38
|
attr_reader :item
|
25
39
|
|
@@ -105,44 +119,72 @@ module Nanoc3
|
|
105
119
|
@force_outdated = false
|
106
120
|
end
|
107
121
|
|
108
|
-
#
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
122
|
+
# Calculates the reason why this item representation is outdated. The
|
123
|
+
# output will be a hash with a `:type` key, containing the reason why the
|
124
|
+
# item is outdated in the form of a symbol, and a `:description` key,
|
125
|
+
# containing a descriptive string that can be printed if necessary.
|
126
|
+
#
|
127
|
+
# For documentation on the types that this method can return, check the
|
128
|
+
# {OUTDATEDNESS_REASON_DESCRIPTIONS} hash in this class.
|
129
|
+
#
|
130
|
+
# @return [Hash, nil] A hash containing the reason why this item rep is
|
131
|
+
# outdated, both in the form of a symbol and as a descriptive string, or
|
132
|
+
# nil if the item representation is not outdated.
|
133
|
+
def outdatedness_reason
|
134
|
+
# Get reason symbol
|
135
|
+
reason = lambda do
|
136
|
+
# Outdated if we don't know
|
137
|
+
return :no_mtime if @item.mtime.nil?
|
138
|
+
|
139
|
+
# Outdated if the dependency tracker says so
|
140
|
+
return :forced if @force_outdated
|
141
|
+
|
142
|
+
# Outdated if compiled file doesn't exist (yet)
|
143
|
+
return :no_raw_path if self.raw_path.nil?
|
144
|
+
return :not_written if !File.file?(self.raw_path)
|
145
|
+
|
146
|
+
# Get compiled mtime
|
147
|
+
compiled_mtime = File.stat(self.raw_path).mtime
|
148
|
+
|
149
|
+
# Outdated if file too old
|
150
|
+
return :source_modified if @item.mtime > compiled_mtime
|
151
|
+
|
152
|
+
# Outdated if layouts outdated
|
153
|
+
return :layouts_outdated if @item.site.layouts.any? do |l|
|
154
|
+
l.mtime.nil? || l.mtime > compiled_mtime
|
155
|
+
end
|
116
156
|
|
117
|
-
|
118
|
-
|
119
|
-
|
157
|
+
# Outdated if code outdated
|
158
|
+
return :code_outdated if @item.site.code_snippets.any? do |cs|
|
159
|
+
cs.mtime.nil? || cs.mtime > compiled_mtime
|
160
|
+
end
|
120
161
|
|
121
|
-
|
122
|
-
|
162
|
+
# Outdated if config outdated
|
163
|
+
return :config_outdated if @item.site.config_mtime.nil?
|
164
|
+
return :config_outdated if @item.site.config_mtime > compiled_mtime
|
123
165
|
|
124
|
-
|
125
|
-
|
166
|
+
# Outdated if rules outdated
|
167
|
+
return :rules_outdated if @item.site.rules_mtime.nil?
|
168
|
+
return :rules_outdated if @item.site.rules_mtime > compiled_mtime
|
126
169
|
|
127
|
-
|
128
|
-
|
129
|
-
l.mtime.nil? || l.mtime > compiled_mtime
|
130
|
-
end
|
170
|
+
return nil
|
171
|
+
end[]
|
131
172
|
|
132
|
-
#
|
133
|
-
|
134
|
-
|
173
|
+
# Build reason symbol and description
|
174
|
+
if reason.nil?
|
175
|
+
nil
|
176
|
+
else
|
177
|
+
{
|
178
|
+
:type => reason,
|
179
|
+
:description => OUTDATEDNESS_REASON_DESCRIPTIONS[reason]
|
180
|
+
}
|
135
181
|
end
|
182
|
+
end
|
136
183
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
# Outdated if rules outdated
|
142
|
-
return true if @item.site.rules_mtime.nil?
|
143
|
-
return true if @item.site.rules_mtime > compiled_mtime
|
144
|
-
|
145
|
-
return false
|
184
|
+
# @return [Boolean] true if this item rep's output file is outdated and
|
185
|
+
# must be regenerated, false otherwise
|
186
|
+
def outdated?
|
187
|
+
!outdatedness_reason.nil?
|
146
188
|
end
|
147
189
|
|
148
190
|
# @return [Hash] The assignments that should be available when compiling
|
@@ -354,7 +396,7 @@ module Nanoc3
|
|
354
396
|
# content in `diff(1)` format, or nil if there is no previous compiled
|
355
397
|
# content
|
356
398
|
def diff
|
357
|
-
|
399
|
+
return nil if !@item.site.config[:enable_output_diff]
|
358
400
|
|
359
401
|
if self.binary?
|
360
402
|
nil
|
@@ -409,10 +451,6 @@ module Nanoc3
|
|
409
451
|
end
|
410
452
|
|
411
453
|
def diff_strings(a, b)
|
412
|
-
# TODO Rewrite this string-diffing method in pure Ruby. It should not
|
413
|
-
# use the "diff" executable, because this will most likely not work on
|
414
|
-
# operating systems without it, such as Windows.
|
415
|
-
|
416
454
|
require 'tempfile'
|
417
455
|
require 'open3'
|
418
456
|
|
data/lib/nanoc3/base/site.rb
CHANGED
@@ -39,14 +39,20 @@ module Nanoc3
|
|
39
39
|
# that lacks some options, the default value will be taken from
|
40
40
|
# `DEFAULT_CONFIG`.
|
41
41
|
DEFAULT_CONFIG = {
|
42
|
-
:text_extensions
|
43
|
-
:output_dir
|
44
|
-
:data_sources
|
45
|
-
:index_filenames
|
42
|
+
:text_extensions => %w( css erb haml htm html js less markdown md php rb sass txt ),
|
43
|
+
:output_dir => 'output',
|
44
|
+
:data_sources => [ {} ],
|
45
|
+
:index_filenames => [ 'index.html' ],
|
46
|
+
:enable_output_diff => false
|
46
47
|
}
|
47
48
|
|
48
49
|
# The site configuration. The configuration has the following keys:
|
49
50
|
#
|
51
|
+
# * `text_extensions` ({Array<String>}) - A list of file extensions that
|
52
|
+
# will cause nanoc to threat the file as textual instead of binary. When
|
53
|
+
# the data source finds a content file with an extension that is
|
54
|
+
# included in this list, it will be marked as textual.
|
55
|
+
#
|
50
56
|
# * `output_dir` ({String}) - The directory to which compiled items will
|
51
57
|
# be written. This path is relative to the current working directory,
|
52
58
|
# but can also be an absolute path.
|
@@ -60,6 +66,9 @@ module Nanoc3
|
|
60
66
|
# `/about/` will be used instead of `/about/index.html`). The default
|
61
67
|
# value should be okay in most cases.
|
62
68
|
#
|
69
|
+
# * `enable_output_diff` ({Boolean}) - True when diffs should be generated
|
70
|
+
# for the compiled content of this site; false otherwise.
|
71
|
+
#
|
63
72
|
# The list of data sources consists of hashes with the following keys:
|
64
73
|
#
|
65
74
|
# * `:type` ({String}) - The type of data source, i.e. its identifier.
|
@@ -32,6 +32,11 @@ output_dir: #{Nanoc3::Site::DEFAULT_CONFIG[:output_dir]}
|
|
32
32
|
# such as “default.htm”. This list is used by nanoc to generate pretty URLs.
|
33
33
|
index_filenames: #{array_to_yaml(Nanoc3::Site::DEFAULT_CONFIG[:index_filenames])}
|
34
34
|
|
35
|
+
# Whether or not to generate a diff of the compiled content when compiling a
|
36
|
+
# site. The diff will contain the differences between the compiled content
|
37
|
+
# before and after the last site compilation.
|
38
|
+
enable_output_diff: false
|
39
|
+
|
35
40
|
# The data sources where nanoc loads its data from. This is an array of
|
36
41
|
# hashes; each array element represents a single data source. By default,
|
37
42
|
# there is only a single data source that reads data from the “content/” and
|
@@ -47,31 +47,45 @@ module Nanoc3::CLI::Commands
|
|
47
47
|
dependency_tracker = @base.site.compiler.send(:dependency_tracker)
|
48
48
|
dependency_tracker.load_graph
|
49
49
|
|
50
|
-
# Print
|
51
|
-
puts '===
|
50
|
+
# Print item dependencies
|
51
|
+
puts '=== Item dependencies ======================================================='
|
52
52
|
puts
|
53
|
-
row = 0
|
54
53
|
items.sort_by { |i| i.identifier }.each do |item|
|
55
|
-
puts "item #{item.identifier}:"
|
56
|
-
|
57
|
-
# Print item dependencies
|
58
|
-
puts " dependencies:"
|
54
|
+
puts "item #{item.identifier} depends on:"
|
59
55
|
predecessors = dependency_tracker.direct_predecessors_of(item).sort_by { |i| i.identifier }
|
60
56
|
predecessors.each do |pred|
|
61
|
-
puts "
|
57
|
+
puts " #{pred.identifier}"
|
62
58
|
end
|
63
|
-
puts "
|
59
|
+
puts " (nothing)" if predecessors.empty?
|
60
|
+
puts
|
61
|
+
end
|
64
62
|
|
65
|
-
|
66
|
-
|
63
|
+
# Print representation paths
|
64
|
+
puts '=== Representation paths ===================================================='
|
65
|
+
puts
|
66
|
+
items.sort_by { |i| i.identifier }.each do |item|
|
67
67
|
item.reps.sort_by { |r| r.name.to_s }.each do |rep|
|
68
|
-
puts "
|
68
|
+
puts "item #{item.identifier}, rep #{rep.name}:"
|
69
|
+
puts " #{rep.raw_path || '(not written)'}"
|
69
70
|
end
|
70
|
-
|
71
|
-
# Done
|
72
71
|
puts
|
73
72
|
end
|
73
|
+
|
74
|
+
# Print representation outdatedness
|
75
|
+
puts '=== Representation outdatedness ============================================='
|
74
76
|
puts
|
77
|
+
items.sort_by { |i| i.identifier }.each do |item|
|
78
|
+
item.reps.sort_by { |r| r.name.to_s }.each do |rep|
|
79
|
+
puts "item #{item.identifier}, rep #{rep.name}:"
|
80
|
+
outdatedness_reason = rep.outdatedness_reason
|
81
|
+
if outdatedness_reason
|
82
|
+
puts " is outdated: #{outdatedness_reason[:type]} (#{outdatedness_reason[:description]})"
|
83
|
+
else
|
84
|
+
puts " is not outdated"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
puts
|
88
|
+
end
|
75
89
|
|
76
90
|
# Print layouts
|
77
91
|
puts '=== Layouts'
|
data/lib/nanoc3/filters/sass.rb
CHANGED
@@ -12,11 +12,58 @@ module Nanoc3::Filters
|
|
12
12
|
def run(content, params={})
|
13
13
|
require 'sass'
|
14
14
|
|
15
|
+
# Add imported_filename read accessor to ImportNode
|
16
|
+
# … but… but… nex3 said I could monkey patch it! :(
|
17
|
+
methods = ::Sass::Tree::ImportNode.instance_methods
|
18
|
+
if !methods.include?(:import_filename) && !methods.include?('import_filename')
|
19
|
+
::Sass::Tree::ImportNode.send(:attr_reader, :imported_filename)
|
20
|
+
end
|
21
|
+
|
15
22
|
# Get options
|
16
23
|
options = params.merge(:filename => filename)
|
17
24
|
|
18
|
-
#
|
19
|
-
::Sass::Engine.new(content, options)
|
25
|
+
# Build engine
|
26
|
+
engine = ::Sass::Engine.new(content, options)
|
27
|
+
|
28
|
+
# Get import nodes
|
29
|
+
require 'set'
|
30
|
+
imported_nodes = []
|
31
|
+
unprocessed_nodes = Set.new([ engine.to_tree ])
|
32
|
+
until unprocessed_nodes.empty?
|
33
|
+
# Get an unprocessed node
|
34
|
+
node = unprocessed_nodes.each { |n| break n }
|
35
|
+
unprocessed_nodes.delete(node)
|
36
|
+
|
37
|
+
# Add to list of import nodes if necessary
|
38
|
+
imported_nodes << node if node.is_a?(::Sass::Tree::ImportNode)
|
39
|
+
|
40
|
+
# Mark children of this node for processing
|
41
|
+
node.children.each { |c| unprocessed_nodes << c }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get import paths
|
45
|
+
import_paths = (options[:load_paths] || []).dup
|
46
|
+
import_paths.unshift(File.dirname(options[:filename])) if options[:filename]
|
47
|
+
|
48
|
+
# Get imported filenames
|
49
|
+
imported_filenames = imported_nodes.map do |node|
|
50
|
+
::Sass::Files.find_file_to_import(node.imported_filename, import_paths)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Convert to items
|
54
|
+
imported_items = imported_filenames.map do |filename|
|
55
|
+
normalized_filename = Pathname.new(filename).realpath
|
56
|
+
@items.find { |i| Pathname.new(i[:filename]).realpath == normalized_filename }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Require compilation of each item
|
60
|
+
imported_items.each do |item|
|
61
|
+
any_uncompiled_rep = item.reps.find { |r| !r.compiled? }
|
62
|
+
raise Nanoc3::Errors::UnmetDependency.new(any_uncompiled_rep) if any_uncompiled_rep
|
63
|
+
end
|
64
|
+
|
65
|
+
# Done
|
66
|
+
engine.render
|
20
67
|
end
|
21
68
|
|
22
69
|
end
|
data/lib/nanoc3.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 3
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 3.1.
|
8
|
+
- 0rc1
|
9
|
+
version: 3.1.0rc1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Denis Defreyne
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-27 00:00:00 +01:00
|
18
18
|
default_executable: nanoc3
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|