nanoc 4.0.0a1 → 4.0.0a2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +9 -4
- data/NEWS.md +13 -0
- data/lib/nanoc/base.rb +2 -0
- data/lib/nanoc/base/compilation/compiler.rb +0 -1
- data/lib/nanoc/base/compilation/compiler_dsl.rb +21 -7
- data/lib/nanoc/base/compilation/item_rep_proxy.rb +10 -1
- data/lib/nanoc/base/compilation/rule.rb +10 -12
- data/lib/nanoc/base/compilation/rules_collection.rb +2 -2
- data/lib/nanoc/base/pattern.rb +63 -0
- data/lib/nanoc/base/source_data/data_source.rb +33 -18
- data/lib/nanoc/base/source_data/identifier.rb +65 -3
- data/lib/nanoc/base/source_data/item.rb +1 -1
- data/lib/nanoc/base/source_data/item_array.rb +17 -2
- data/lib/nanoc/base/source_data/layout.rb +1 -1
- data/lib/nanoc/base/source_data/site.rb +4 -3
- data/lib/nanoc/base/views/config.rb +22 -0
- data/lib/nanoc/base/views/item.rb +76 -0
- data/lib/nanoc/base/views/item_collection.rb +46 -4
- data/lib/nanoc/base/views/item_rep.rb +23 -0
- data/lib/nanoc/base/views/layout.rb +4 -0
- data/lib/nanoc/base/views/layout_collection.rb +7 -1
- data/lib/nanoc/base/views/mutable_config.rb +5 -0
- data/lib/nanoc/base/views/mutable_item.rb +15 -0
- data/lib/nanoc/base/views/mutable_item_collection.rb +25 -0
- data/lib/nanoc/base/views/mutable_layout.rb +5 -0
- data/lib/nanoc/base/views/mutable_layout_collection.rb +20 -2
- data/lib/nanoc/cli/cleaning_stream.rb +15 -0
- data/lib/nanoc/cli/commands/create-site.rb +17 -35
- data/lib/nanoc/cli/commands/shell.rb +7 -4
- data/lib/nanoc/data_sources.rb +0 -1
- data/lib/nanoc/data_sources/filesystem.rb +75 -76
- data/lib/nanoc/data_sources/filesystem_unified.rb +4 -27
- data/lib/nanoc/data_sources/filesystem_verbose.rb +4 -21
- data/lib/nanoc/version.rb +1 -1
- data/nanoc.gemspec +1 -1
- data/test/base/test_compiler.rb +35 -15
- data/test/base/test_compiler_dsl.rb +32 -30
- data/test/base/test_data_source.rb +2 -2
- data/test/base/test_item_array.rb +10 -1
- data/test/base/test_rule.rb +2 -2
- data/test/base/test_site.rb +32 -0
- data/test/cli/commands/test_create_site.rb +7 -1
- data/test/cli/commands/test_prune.rb +2 -2
- data/test/data_sources/test_filesystem.rb +29 -9
- data/test/data_sources/test_filesystem_unified.rb +48 -68
- data/test/helper.rb +1 -0
- data/test/helpers/test_breadcrumbs.rb +4 -4
- data/test/test_gem.rb +0 -1
- metadata +4 -5
- data/lib/nanoc/data_sources/static.rb +0 -62
- data/test/data_sources/test_static.rb +0 -93
@@ -70,7 +70,7 @@ module Nanoc::Int
|
|
70
70
|
|
71
71
|
# Get rest of params
|
72
72
|
@attributes = attributes.__nanoc_symbolize_keys_recursively
|
73
|
-
@identifier = Nanoc::Identifier.
|
73
|
+
@identifier = Nanoc::Identifier.from(identifier)
|
74
74
|
|
75
75
|
# Set mtime
|
76
76
|
@attributes.merge!(mtime: params[:mtime]) if params[:mtime]
|
@@ -21,7 +21,9 @@ module Nanoc::Int
|
|
21
21
|
DELEGATED_METHODS = (Array.instance_methods + Enumerable.instance_methods).map(&:to_sym) - EXCLUDED_METHODS
|
22
22
|
def_delegators :@items, *DELEGATED_METHODS
|
23
23
|
|
24
|
-
def initialize
|
24
|
+
def initialize(config)
|
25
|
+
@config = config
|
26
|
+
|
25
27
|
@items = []
|
26
28
|
end
|
27
29
|
|
@@ -33,7 +35,7 @@ module Nanoc::Int
|
|
33
35
|
|
34
36
|
def [](*args)
|
35
37
|
if 1 == args.size && args.first.is_a?(String)
|
36
|
-
item_with_identifier(args.first)
|
38
|
+
item_with_identifier(args.first) || item_matching_glob(args.first)
|
37
39
|
elsif 1 == args.size && args.first.is_a?(Regexp)
|
38
40
|
@items.select { |i| i.identifier.to_s =~ args.first }
|
39
41
|
else
|
@@ -60,6 +62,15 @@ module Nanoc::Int
|
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
65
|
+
def item_matching_glob(glob)
|
66
|
+
if use_globs?
|
67
|
+
pat = Nanoc::Int::Pattern.from(glob)
|
68
|
+
@items.find { |i| pat.match?(i.identifier) }
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
63
74
|
def build_mapping
|
64
75
|
@mapping = {}
|
65
76
|
@items.each do |item|
|
@@ -67,5 +78,9 @@ module Nanoc::Int
|
|
67
78
|
end
|
68
79
|
@mapping.freeze
|
69
80
|
end
|
81
|
+
|
82
|
+
def use_globs?
|
83
|
+
@config[:pattern_syntax] == 'glob'
|
84
|
+
end
|
70
85
|
end
|
71
86
|
end
|
@@ -29,7 +29,7 @@ module Nanoc::Int
|
|
29
29
|
def initialize(raw_content, attributes, identifier, params = {})
|
30
30
|
@raw_content = raw_content
|
31
31
|
@attributes = attributes.__nanoc_symbolize_keys_recursively
|
32
|
-
@identifier = Nanoc::Identifier.
|
32
|
+
@identifier = Nanoc::Identifier.from(identifier)
|
33
33
|
end
|
34
34
|
|
35
35
|
# Requests the attribute with the given key.
|
@@ -176,6 +176,7 @@ module Nanoc::Int
|
|
176
176
|
|
177
177
|
item_map = {}
|
178
178
|
@items.each do |item|
|
179
|
+
next if item.identifier !~ /\/\z/
|
179
180
|
item_map[item.identifier.to_s] = item
|
180
181
|
end
|
181
182
|
|
@@ -324,11 +325,11 @@ module Nanoc::Int
|
|
324
325
|
@items_loaded = true
|
325
326
|
|
326
327
|
# Get items
|
327
|
-
@items = Nanoc::Int::ItemArray.new
|
328
|
+
@items = Nanoc::Int::ItemArray.new(@config)
|
328
329
|
data_sources.each do |ds|
|
329
330
|
items_in_ds = ds.items
|
330
331
|
items_in_ds.each do |i|
|
331
|
-
i.identifier =
|
332
|
+
i.identifier = i.identifier.prefix(ds.items_root)
|
332
333
|
i.site = self
|
333
334
|
end
|
334
335
|
@items.concat(items_in_ds)
|
@@ -346,7 +347,7 @@ module Nanoc::Int
|
|
346
347
|
data_sources.each do |ds|
|
347
348
|
layouts_in_ds = ds.layouts
|
348
349
|
layouts_in_ds.each do |l|
|
349
|
-
l.identifier =
|
350
|
+
l.identifier = l.identifier.prefix(ds.layouts_root)
|
350
351
|
end
|
351
352
|
@layouts.concat(layouts_in_ds)
|
352
353
|
end
|
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
module Nanoc
|
4
4
|
class ConfigView
|
5
|
+
# @api private
|
6
|
+
NONE = Object.new
|
7
|
+
|
5
8
|
# @api private
|
6
9
|
def initialize(config)
|
7
10
|
@config = config
|
@@ -12,6 +15,25 @@ module Nanoc
|
|
12
15
|
@config
|
13
16
|
end
|
14
17
|
|
18
|
+
# @see Hash#fetch
|
19
|
+
def fetch(key, fallback=NONE, &block)
|
20
|
+
@config.fetch(key) do
|
21
|
+
if !fallback.equal?(NONE)
|
22
|
+
fallback
|
23
|
+
elsif block_given?
|
24
|
+
yield(key)
|
25
|
+
else
|
26
|
+
raise KeyError, "key not found: #{key.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @see Hash#key?
|
32
|
+
def key?(key)
|
33
|
+
@config.key?(key)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @see Hash#[]
|
15
37
|
def [](key)
|
16
38
|
@config[key]
|
17
39
|
end
|
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
module Nanoc
|
4
4
|
class ItemView
|
5
|
+
# @api private
|
6
|
+
NONE = Object.new
|
7
|
+
|
5
8
|
# @api private
|
6
9
|
def initialize(item)
|
7
10
|
@item = item
|
@@ -12,39 +15,112 @@ module Nanoc
|
|
12
15
|
@item
|
13
16
|
end
|
14
17
|
|
18
|
+
# @see Object#==
|
15
19
|
def ==(other)
|
16
20
|
identifier == other.identifier
|
17
21
|
end
|
18
22
|
alias_method :eql?, :==
|
19
23
|
|
24
|
+
# @see Object#hash
|
20
25
|
def hash
|
21
26
|
self.class.hash ^ identifier.hash
|
22
27
|
end
|
23
28
|
|
29
|
+
# @return [Nanoc::Identifier]
|
24
30
|
def identifier
|
25
31
|
@item.identifier
|
26
32
|
end
|
27
33
|
|
34
|
+
# @see Hash#fetch
|
35
|
+
def fetch(key, fallback=NONE, &block)
|
36
|
+
res = @item[key] # necessary for dependency tracking
|
37
|
+
|
38
|
+
if @item.attributes.key?(key)
|
39
|
+
res
|
40
|
+
else
|
41
|
+
if !fallback.equal?(NONE)
|
42
|
+
fallback
|
43
|
+
elsif block_given?
|
44
|
+
yield(key)
|
45
|
+
else
|
46
|
+
raise KeyError, "key not found: #{key.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @see Hash#key?
|
52
|
+
def key?(key)
|
53
|
+
_res = @item[key] # necessary for dependency tracking
|
54
|
+
@item.attributes.key?(key)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @see Hash#[]
|
28
58
|
def [](key)
|
29
59
|
@item[key]
|
30
60
|
end
|
31
61
|
|
62
|
+
# Returns the compiled content.
|
63
|
+
#
|
64
|
+
# @option params [String] :rep (:default) The name of the representation
|
65
|
+
# from which the compiled content should be fetched. By default, the
|
66
|
+
# compiled content will be fetched from the default representation.
|
67
|
+
#
|
68
|
+
# @option params [String] :snapshot The name of the snapshot from which to
|
69
|
+
# fetch the compiled content. By default, the returned compiled content
|
70
|
+
# will be the content compiled right before the first layout call (if
|
71
|
+
# any).
|
72
|
+
#
|
73
|
+
# @return [String] The content of the given rep at the given snapshot.
|
32
74
|
def compiled_content(params = {})
|
33
75
|
@item.compiled_content(params)
|
34
76
|
end
|
35
77
|
|
78
|
+
# Returns the item path, as used when being linked to. It starts
|
79
|
+
# with a slash and it is relative to the output directory. It does not
|
80
|
+
# include the path to the output directory. It will not include the
|
81
|
+
# filename if the filename is an index filename.
|
82
|
+
#
|
83
|
+
# @option params [String] :rep (:default) The name of the representation
|
84
|
+
# from which the path should be fetched. By default, the path will be
|
85
|
+
# fetched from the default representation.
|
86
|
+
#
|
87
|
+
# @option params [Symbol] :snapshot (:last) The snapshot for which the
|
88
|
+
# path should be returned.
|
89
|
+
#
|
90
|
+
# @return [String] The item’s path.
|
36
91
|
def path(params = {})
|
37
92
|
@item.path(params)
|
38
93
|
end
|
39
94
|
|
95
|
+
# Returns the children of this item. For items with identifiers that have
|
96
|
+
# extensions, returns an empty collection.
|
97
|
+
#
|
98
|
+
# @return [Enumerable<Nanoc::ItemView>]
|
40
99
|
def children
|
41
100
|
@item.children.map { |i| Nanoc::ItemView.new(i) }
|
42
101
|
end
|
43
102
|
|
103
|
+
# Returns the parent of this item, if one exists. For items with identifiers
|
104
|
+
# that have extensions, returns nil.
|
105
|
+
#
|
106
|
+
# @return [Nanoc::ItemView] if the item has a parent
|
107
|
+
#
|
108
|
+
# @return [nil] if the item has no parent
|
109
|
+
def parent
|
110
|
+
Nanoc::ItemView.new(@item.parent)
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [Boolean] True if the item is binary, false otherwise
|
44
114
|
def binary?
|
45
115
|
@item.binary?
|
46
116
|
end
|
47
117
|
|
118
|
+
# For textual items, returns the raw (source) content of this item; for
|
119
|
+
# binary items, returns `nil`.
|
120
|
+
#
|
121
|
+
# @return [String] if the item is textual
|
122
|
+
#
|
123
|
+
# @return [nil] if the item is binary
|
48
124
|
def raw_content
|
49
125
|
@item.raw_content
|
50
126
|
end
|
@@ -19,20 +19,62 @@ module Nanoc
|
|
19
19
|
Nanoc::ItemView
|
20
20
|
end
|
21
21
|
|
22
|
+
# Calls the given block once for each item, passing that item as a parameter.
|
23
|
+
#
|
24
|
+
# @yieldparam [Nanoc::ItemView] item
|
25
|
+
#
|
26
|
+
# @yieldreturn [void]
|
27
|
+
#
|
28
|
+
# @return [self]
|
22
29
|
def each
|
23
30
|
@items.each { |i| yield view_class.new(i) }
|
31
|
+
self
|
24
32
|
end
|
25
33
|
|
34
|
+
# @return [Integer]
|
35
|
+
def size
|
36
|
+
@items.size
|
37
|
+
end
|
38
|
+
|
39
|
+
# @overload at(string)
|
40
|
+
#
|
41
|
+
# Finds the item whose identifier matches the given string.
|
42
|
+
#
|
43
|
+
# @param [String] string
|
44
|
+
#
|
45
|
+
# @return [nil] if no item matches the string
|
46
|
+
#
|
47
|
+
# @return [Nanoc::ItemView] if an item was found
|
26
48
|
def at(arg)
|
27
49
|
item = @items.at(arg)
|
28
50
|
item && view_class.new(item)
|
29
51
|
end
|
30
52
|
|
31
|
-
|
32
|
-
|
53
|
+
# @overload [](string)
|
54
|
+
#
|
55
|
+
# Finds the item whose identifier matches the given string.
|
56
|
+
#
|
57
|
+
# If the glob syntax is enabled, the string can be a glob, in which case
|
58
|
+
# this method finds the first item that matches the given glob.
|
59
|
+
#
|
60
|
+
# @param [String] string
|
61
|
+
#
|
62
|
+
# @return [nil] if no item matches the string
|
63
|
+
#
|
64
|
+
# @return [Nanoc::ItemView] if an item was found
|
65
|
+
#
|
66
|
+
# @overload [](regex)
|
67
|
+
#
|
68
|
+
# Finds the item whose identifier matches the given regular expression.
|
69
|
+
#
|
70
|
+
# @param [Regex] regex
|
71
|
+
#
|
72
|
+
# @return [nil] if no item matches the regex
|
73
|
+
#
|
74
|
+
# @return [Nanoc::ItemView] if an item was found
|
75
|
+
def [](arg)
|
76
|
+
res = @items[arg]
|
33
77
|
case res
|
34
|
-
when Array
|
35
|
-
res.map { |r| view_class.new(r) }
|
36
78
|
when nil
|
37
79
|
nil
|
38
80
|
else
|
@@ -12,27 +12,50 @@ module Nanoc
|
|
12
12
|
@item_rep
|
13
13
|
end
|
14
14
|
|
15
|
+
# @see Object#==
|
15
16
|
def ==(other)
|
16
17
|
item.identifier == other.item.identifier && name == other.name
|
17
18
|
end
|
18
19
|
alias_method :eql?, :==
|
19
20
|
|
21
|
+
# @see Object#hash
|
20
22
|
def hash
|
21
23
|
self.class.hash ^ item.identifier.hash ^ name.hash
|
22
24
|
end
|
23
25
|
|
26
|
+
# @return [Symbol]
|
24
27
|
def name
|
25
28
|
@item_rep.name
|
26
29
|
end
|
27
30
|
|
31
|
+
# Returns the compiled content.
|
32
|
+
#
|
33
|
+
# @option params [String] :snapshot The name of the snapshot from which to
|
34
|
+
# fetch the compiled content. By default, the returned compiled content
|
35
|
+
# will be the content compiled right before the first layout call (if
|
36
|
+
# any).
|
37
|
+
#
|
38
|
+
# @return [String] The content at the given snapshot.
|
28
39
|
def compiled_content(params = {})
|
29
40
|
@item_rep.compiled_content(params)
|
30
41
|
end
|
31
42
|
|
43
|
+
# Returns the item rep’s path, as used when being linked to. It starts
|
44
|
+
# with a slash and it is relative to the output directory. It does not
|
45
|
+
# include the path to the output directory. It will not include the
|
46
|
+
# filename if the filename is an index filename.
|
47
|
+
#
|
48
|
+
# @option params [Symbol] :snapshot (:last) The snapshot for which the
|
49
|
+
# path should be returned.
|
50
|
+
#
|
51
|
+
# @return [String] The item rep’s path.
|
32
52
|
def path(params = {})
|
33
53
|
@item_rep.path(params)
|
34
54
|
end
|
35
55
|
|
56
|
+
# Returns the item that this item rep belongs to.
|
57
|
+
#
|
58
|
+
# @return [Nanoc::ItemView]
|
36
59
|
def item
|
37
60
|
Nanoc::ItemView.new(@item_rep.item)
|
38
61
|
end
|
@@ -12,19 +12,23 @@ module Nanoc
|
|
12
12
|
@layout
|
13
13
|
end
|
14
14
|
|
15
|
+
# @see Object#==
|
15
16
|
def ==(other)
|
16
17
|
identifier == other.identifier
|
17
18
|
end
|
18
19
|
alias_method :eql?, :==
|
19
20
|
|
21
|
+
# @see Object#hash
|
20
22
|
def hash
|
21
23
|
self.class.hash ^ identifier.hash
|
22
24
|
end
|
23
25
|
|
26
|
+
# @return [Nanoc::Identifier]
|
24
27
|
def identifier
|
25
28
|
@layout.identifier
|
26
29
|
end
|
27
30
|
|
31
|
+
# @see Hash#[]
|
28
32
|
def [](key)
|
29
33
|
@layout[key]
|
30
34
|
end
|
@@ -11,7 +11,7 @@ module Nanoc
|
|
11
11
|
|
12
12
|
# @api private
|
13
13
|
def unwrap
|
14
|
-
@
|
14
|
+
@layouts
|
15
15
|
end
|
16
16
|
|
17
17
|
# @api private
|
@@ -19,8 +19,14 @@ module Nanoc
|
|
19
19
|
Nanoc::LayoutView
|
20
20
|
end
|
21
21
|
|
22
|
+
# Calls the given block once for each layout, passing that layout as a parameter.
|
23
|
+
#
|
24
|
+
# @yieldparam [Nanoc::LayoutView] layout
|
25
|
+
#
|
26
|
+
# @yieldreturn [void]
|
22
27
|
def each
|
23
28
|
@layouts.each { |l| yield view_class.new(l) }
|
29
|
+
self
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|
@@ -2,8 +2,23 @@
|
|
2
2
|
|
3
3
|
module Nanoc
|
4
4
|
class MutableItemView < Nanoc::ItemView
|
5
|
+
# Sets the value for the given attribute.
|
6
|
+
#
|
7
|
+
# @param [Symbol] key
|
8
|
+
#
|
9
|
+
# @see Hash#[]=
|
5
10
|
def []=(key, value)
|
6
11
|
unwrap[key] = value
|
7
12
|
end
|
13
|
+
|
14
|
+
# Updates the attributes based on the given hash.
|
15
|
+
#
|
16
|
+
# @param [Hash] hash
|
17
|
+
#
|
18
|
+
# @return [self]
|
19
|
+
def update_attributes(hash)
|
20
|
+
hash.each { |k, v| unwrap[k] = v }
|
21
|
+
self
|
22
|
+
end
|
8
23
|
end
|
9
24
|
end
|