nanoc 4.0.0a1 → 4.0.0a2

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -4
  3. data/NEWS.md +13 -0
  4. data/lib/nanoc/base.rb +2 -0
  5. data/lib/nanoc/base/compilation/compiler.rb +0 -1
  6. data/lib/nanoc/base/compilation/compiler_dsl.rb +21 -7
  7. data/lib/nanoc/base/compilation/item_rep_proxy.rb +10 -1
  8. data/lib/nanoc/base/compilation/rule.rb +10 -12
  9. data/lib/nanoc/base/compilation/rules_collection.rb +2 -2
  10. data/lib/nanoc/base/pattern.rb +63 -0
  11. data/lib/nanoc/base/source_data/data_source.rb +33 -18
  12. data/lib/nanoc/base/source_data/identifier.rb +65 -3
  13. data/lib/nanoc/base/source_data/item.rb +1 -1
  14. data/lib/nanoc/base/source_data/item_array.rb +17 -2
  15. data/lib/nanoc/base/source_data/layout.rb +1 -1
  16. data/lib/nanoc/base/source_data/site.rb +4 -3
  17. data/lib/nanoc/base/views/config.rb +22 -0
  18. data/lib/nanoc/base/views/item.rb +76 -0
  19. data/lib/nanoc/base/views/item_collection.rb +46 -4
  20. data/lib/nanoc/base/views/item_rep.rb +23 -0
  21. data/lib/nanoc/base/views/layout.rb +4 -0
  22. data/lib/nanoc/base/views/layout_collection.rb +7 -1
  23. data/lib/nanoc/base/views/mutable_config.rb +5 -0
  24. data/lib/nanoc/base/views/mutable_item.rb +15 -0
  25. data/lib/nanoc/base/views/mutable_item_collection.rb +25 -0
  26. data/lib/nanoc/base/views/mutable_layout.rb +5 -0
  27. data/lib/nanoc/base/views/mutable_layout_collection.rb +20 -2
  28. data/lib/nanoc/cli/cleaning_stream.rb +15 -0
  29. data/lib/nanoc/cli/commands/create-site.rb +17 -35
  30. data/lib/nanoc/cli/commands/shell.rb +7 -4
  31. data/lib/nanoc/data_sources.rb +0 -1
  32. data/lib/nanoc/data_sources/filesystem.rb +75 -76
  33. data/lib/nanoc/data_sources/filesystem_unified.rb +4 -27
  34. data/lib/nanoc/data_sources/filesystem_verbose.rb +4 -21
  35. data/lib/nanoc/version.rb +1 -1
  36. data/nanoc.gemspec +1 -1
  37. data/test/base/test_compiler.rb +35 -15
  38. data/test/base/test_compiler_dsl.rb +32 -30
  39. data/test/base/test_data_source.rb +2 -2
  40. data/test/base/test_item_array.rb +10 -1
  41. data/test/base/test_rule.rb +2 -2
  42. data/test/base/test_site.rb +32 -0
  43. data/test/cli/commands/test_create_site.rb +7 -1
  44. data/test/cli/commands/test_prune.rb +2 -2
  45. data/test/data_sources/test_filesystem.rb +29 -9
  46. data/test/data_sources/test_filesystem_unified.rb +48 -68
  47. data/test/helper.rb +1 -0
  48. data/test/helpers/test_breadcrumbs.rb +4 -4
  49. data/test/test_gem.rb +0 -1
  50. metadata +4 -5
  51. data/lib/nanoc/data_sources/static.rb +0 -62
  52. data/test/data_sources/test_static.rb +0 -93
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a0053b307bb6f25cce2645c58960d5f3be1060e
4
- data.tar.gz: 27db68426f384c4e3af20088852300637fa545af
3
+ metadata.gz: e1055bcfad80c114e2f54b3e67d89468c828ce18
4
+ data.tar.gz: 121523a9ee6c375e4a4dc4fc56c680f7501b97ad
5
5
  SHA512:
6
- metadata.gz: 96b78eb40b40e8b19f5c7f208f6266823c60f01fd9d4490a24f8fc4e2e843229d37ce36a42e4b2d91034d63782518c0f8debab9f5635a21b6f27b94b9ab71e57
7
- data.tar.gz: af28723ee5ea196858ffd429fd84aa215515a9248fb912167df8efaeae32522b0628910b4565904ccb0b4610dbf4b71125cdb5319bcc838b02fd8fbf812b185a
6
+ metadata.gz: 0da18d11db64365759e7be6dd9c6fd72334baa823813d39c7286d34f8ebf406cf73bb1059c2dc35d1955c0697495af986bb657a2003ac1ef7f88b8e1c19be249
7
+ data.tar.gz: 609b1ec27cad20f169346917dd688d08dbb4e8a12b4497d4884a1bb3f2dcf1492b36e34a9a4c6d27c77d58f6d346d98c4c6ee37933dc884932acb8dfebeefb3f
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nanoc (4.0.0a1)
4
+ nanoc (4.0.0a2)
5
5
  cri (~> 2.3)
6
6
 
7
7
  GEM
@@ -51,12 +51,13 @@ GEM
51
51
  ffi (1.9.8)
52
52
  fission (0.5.0)
53
53
  CFPropertyList (~> 2.2)
54
- fog (1.29.0)
54
+ fog (1.30.0)
55
55
  fog-atmos
56
56
  fog-aws (~> 0.0)
57
57
  fog-brightbox (~> 0.4)
58
58
  fog-core (~> 1.27, >= 1.27.4)
59
59
  fog-ecloud
60
+ fog-google (>= 0.0.2)
60
61
  fog-json
61
62
  fog-local
62
63
  fog-powerdns (>= 0.1.1)
@@ -95,6 +96,10 @@ GEM
95
96
  fog-ecloud (0.1.1)
96
97
  fog-core
97
98
  fog-xml
99
+ fog-google (0.0.5)
100
+ fog-core
101
+ fog-json
102
+ fog-xml
98
103
  fog-json (1.0.1)
99
104
  fog-core (~> 1.0)
100
105
  multi_json (~> 1.0)
@@ -184,7 +189,7 @@ GEM
184
189
  parser (2.2.2.2)
185
190
  ast (>= 1.1, < 3.0)
186
191
  posix-spawn (0.3.11)
187
- powerpack (0.1.0)
192
+ powerpack (0.1.1)
188
193
  pry (0.10.1)
189
194
  coderay (~> 1.1.0)
190
195
  method_source (~> 0.8.1)
@@ -221,7 +226,7 @@ GEM
221
226
  diff-lcs (>= 1.2.0, < 2.0)
222
227
  rspec-support (~> 3.2.0)
223
228
  rspec-support (3.2.2)
224
- rubocop (0.30.1)
229
+ rubocop (0.31.0)
225
230
  astrolabe (~> 1.3)
226
231
  parser (>= 2.2.2.1, < 3.0)
227
232
  powerpack (~> 0.1)
data/NEWS.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # nanoc news
2
2
 
3
+ ## 4.0.0a2 (2015-05-??)
4
+
5
+ Features:
6
+
7
+ * Glob patterns (opt-in by setting `pattern_syntax` to `"glob"` in the site configuration)
8
+ * Identifiers with extensions (opt-in by setting `identifier_style` to `"full"` in the data source configuration)
9
+
10
+ Enhancements:
11
+
12
+ * Added several convenience methods to view classes (#570, #572)
13
+
14
+ See the [nanoc 4 upgrade guide](http://nanoc.ws/docs/nanoc-4-upgrade-guide/) for details.
15
+
3
16
  ## 4.0.0a1 (2015-05-09)
4
17
 
5
18
  This is a major upgrade. For details on upgrading, see the [nanoc 4 upgrade guide](http://nanoc.ws/docs/nanoc-4-upgrade-guide/).
@@ -27,6 +27,8 @@ end
27
27
 
28
28
  # @api private
29
29
  module Nanoc::Int
30
+ require_relative 'base/pattern'
31
+
30
32
  # Load helper classes
31
33
  autoload 'Context', 'nanoc/base/context'
32
34
  autoload 'Checksummer', 'nanoc/base/checksummer'
@@ -412,7 +412,6 @@ module Nanoc::Int
412
412
  # Returns a preprocessor context, creating one if none exists yet.
413
413
  def preprocessor_context
414
414
  Nanoc::Int::Context.new({
415
- site: Nanoc::SiteView.new(@site), # TODO: remove me
416
415
  config: Nanoc::MutableConfigView.new(@site.config),
417
416
  items: Nanoc::MutableItemCollectionView.new(@site.items),
418
417
  layouts: Nanoc::MutableLayoutCollectionView.new(@site.layouts),
@@ -77,7 +77,7 @@ module Nanoc::Int
77
77
  rep_name = params[:rep] || :default
78
78
 
79
79
  # Create rule
80
- rule = Nanoc::Int::Rule.new(identifier_to_regex(identifier), rep_name, block)
80
+ rule = Nanoc::Int::Rule.new(create_pattern(identifier), rep_name, block)
81
81
  @rules_collection.add_item_compilation_rule(rule)
82
82
  end
83
83
 
@@ -122,7 +122,7 @@ module Nanoc::Int
122
122
  snapshot_name = params[:snapshot] || :last
123
123
 
124
124
  # Create rule
125
- rule = Nanoc::Int::Rule.new(identifier_to_regex(identifier), rep_name, block, snapshot_name: snapshot_name)
125
+ rule = Nanoc::Int::Rule.new(create_pattern(identifier), rep_name, block, snapshot_name: snapshot_name)
126
126
  @rules_collection.add_item_routing_rule(rule)
127
127
  end
128
128
 
@@ -151,7 +151,8 @@ module Nanoc::Int
151
151
  #
152
152
  # layout '/custom/', :haml, :format => :html5
153
153
  def layout(identifier, filter_name, params = {})
154
- @rules_collection.layout_filter_mapping[identifier_to_regex(identifier)] = [filter_name, params]
154
+ pattern = Nanoc::Int::Pattern.from(create_pattern(identifier))
155
+ @rules_collection.layout_filter_mapping[pattern] = [filter_name, params]
155
156
  end
156
157
 
157
158
  # Creates a pair of compilation and routing rules that indicate that the
@@ -188,7 +189,7 @@ module Nanoc::Int
188
189
 
189
190
  # Create compilation rule
190
191
  compilation_block = proc {}
191
- compilation_rule = Nanoc::Int::Rule.new(identifier_to_regex(identifier), rep_name, compilation_block)
192
+ compilation_rule = Nanoc::Int::Rule.new(create_pattern(identifier), rep_name, compilation_block)
192
193
  @rules_collection.add_item_compilation_rule(compilation_rule)
193
194
 
194
195
  # Create routing rule
@@ -199,7 +200,7 @@ module Nanoc::Int
199
200
  # data source.
200
201
  item[:extension].nil? || (item[:content_filename].nil? && item.identifier =~ %r{#{item[:extension]}/$}) ? item.identifier.chop : item.identifier.chop + '.' + item[:extension]
201
202
  end
202
- routing_rule = Nanoc::Int::Rule.new(identifier_to_regex(identifier), rep_name, routing_block, snapshot_name: :last)
203
+ routing_rule = Nanoc::Int::Rule.new(create_pattern(identifier), rep_name, routing_block, snapshot_name: :last)
203
204
  @rules_collection.add_item_routing_rule(routing_rule)
204
205
  end
205
206
 
@@ -227,10 +228,10 @@ module Nanoc::Int
227
228
 
228
229
  rep_name = params[:rep] || :default
229
230
 
230
- compilation_rule = Nanoc::Int::Rule.new(identifier_to_regex(identifier), rep_name, proc {})
231
+ compilation_rule = Nanoc::Int::Rule.new(create_pattern(identifier), rep_name, proc {})
231
232
  @rules_collection.add_item_compilation_rule(compilation_rule)
232
233
 
233
- routing_rule = Nanoc::Int::Rule.new(identifier_to_regex(identifier), rep_name, proc {}, snapshot_name: :last)
234
+ routing_rule = Nanoc::Int::Rule.new(create_pattern(identifier), rep_name, proc {}, snapshot_name: :last)
234
235
  @rules_collection.add_item_routing_rule(routing_rule)
235
236
  end
236
237
 
@@ -253,6 +254,19 @@ module Nanoc::Int
253
254
  @rules_collection.parse(filename)
254
255
  end
255
256
 
257
+ # @api private
258
+ def create_pattern(arg)
259
+ case @config[:pattern_syntax]
260
+ when 'glob'
261
+ Nanoc::Int::Pattern.from(arg)
262
+ when nil
263
+ Nanoc::Int::Pattern.from(identifier_to_regex(arg))
264
+ else
265
+ raise Nanoc::Int::Errors::GenericTrivial,
266
+ "Invalid pattern_syntax: #{@config[:pattern_syntax]}"
267
+ end
268
+ end
269
+
256
270
  private
257
271
 
258
272
  # Converts the given identifier, which can contain the '*' or '+'
@@ -94,9 +94,18 @@ module Nanoc::Int
94
94
  end
95
95
 
96
96
  def layout_with_identifier(layout_identifier)
97
- layout ||= layouts.find { |l| l.identifier == layout_identifier.__nanoc_cleaned_identifier }
97
+ req_id = layout_identifier.__nanoc_cleaned_identifier
98
+ layout = layouts.find { |l| l.identifier == req_id }
99
+ if layout.nil? && use_globs?
100
+ pat = Nanoc::Int::Pattern.from(layout_identifier)
101
+ layout = layouts.find { |l| pat.match?(l.identifier) }
102
+ end
98
103
  raise Nanoc::Int::Errors::UnknownLayout.new(layout_identifier) if layout.nil?
99
104
  layout
100
105
  end
106
+
107
+ def use_globs?
108
+ @compiler.site.config[:pattern_syntax] == 'glob'
109
+ end
101
110
  end
102
111
  end
@@ -5,11 +5,6 @@ module Nanoc::Int
5
5
  #
6
6
  # @api private
7
7
  class Rule
8
- # @return [Regexp] The regex that determines which items this rule can be
9
- # applied to. This rule can be applied to items with a identifier
10
- # matching this regex.
11
- attr_reader :identifier_regex
12
-
13
8
  # @return [Symbol] The name of the representation that will be compiled
14
9
  # using this rule
15
10
  attr_reader :rep_name
@@ -24,8 +19,7 @@ module Nanoc::Int
24
19
  # compiler and block. The block will be called during compilation with the
25
20
  # item rep as its argument.
26
21
  #
27
- # @param [Regexp] identifier_regex A regular expression that will be used
28
- # to determine whether this rule is applicable to certain items.
22
+ # @param [Nanoc::Int::Pattern] pattern
29
23
  #
30
24
  # @param [String, Symbol] rep_name The name of the item representation
31
25
  # where this rule can be applied to
@@ -36,8 +30,13 @@ module Nanoc::Int
36
30
  # @option params [Symbol, nil] :snapshot (nil) The name of the snapshot
37
31
  # this rule will apply to. Ignored for compilation rules, but used for
38
32
  # routing rules.
39
- def initialize(identifier_regex, rep_name, block, params = {})
40
- @identifier_regex = identifier_regex
33
+ def initialize(pattern, rep_name, block, params = {})
34
+ # TODO: remove me
35
+ unless pattern.is_a?(Nanoc::Int::StringPattern) || pattern.is_a?(Nanoc::Int::RegexpPattern)
36
+ raise "Can only create rules with patterns"
37
+ end
38
+
39
+ @pattern = pattern
41
40
  @rep_name = rep_name.to_sym
42
41
  @snapshot_name = params[:snapshot_name]
43
42
 
@@ -49,7 +48,7 @@ module Nanoc::Int
49
48
  # @return [Boolean] true if this rule can be applied to the given item
50
49
  # rep, false otherwise
51
50
  def applicable_to?(item)
52
- item.identifier =~ @identifier_regex
51
+ @pattern.match?(item.identifier)
53
52
  end
54
53
 
55
54
  # Applies this rule to the given item rep.
@@ -80,8 +79,7 @@ module Nanoc::Int
80
79
  #
81
80
  # @return [nil, Array] Captured groups, if any
82
81
  def matches(identifier)
83
- matches = @identifier_regex.match(identifier.to_s)
84
- matches && matches.captures
82
+ @pattern.captures(identifier)
85
83
  end
86
84
  end
87
85
  end
@@ -153,8 +153,8 @@ module Nanoc::Int
153
153
  # @return [Array, nil] A tuple containing the filter name and the filter
154
154
  # arguments for the given layout.
155
155
  def filter_for_layout(layout)
156
- @layout_filter_mapping.each_pair do |layout_identifier, filter_name_and_args|
157
- return filter_name_and_args if layout.identifier =~ layout_identifier
156
+ @layout_filter_mapping.each_pair do |pattern, filter_name_and_args|
157
+ return filter_name_and_args if pattern.match?(layout.identifier)
158
158
  end
159
159
  nil
160
160
  end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc::Int
4
+ # @api private
5
+ class Pattern
6
+ def self.from(obj)
7
+ case obj
8
+ when Nanoc::Int::StringPattern, Nanoc::Int::RegexpPattern
9
+ obj
10
+ when String
11
+ Nanoc::Int::StringPattern.new(obj)
12
+ when Regexp
13
+ Nanoc::Int::RegexpPattern.new(obj)
14
+ else
15
+ raise ArgumentError, "Do not know how to convert #{obj} into a Nanoc::Pattern"
16
+ end
17
+ end
18
+
19
+ def initialize(_obj)
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def match?(_identifier)
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def captures(_identifier)
28
+ raise NotImplementedError
29
+ end
30
+ end
31
+
32
+ # @api private
33
+ class StringPattern
34
+ def initialize(string)
35
+ @string = string
36
+ end
37
+
38
+ def match?(identifier)
39
+ opts = File::FNM_PATHNAME | File::FNM_EXTGLOB
40
+ File.fnmatch(@string, identifier.to_s, opts)
41
+ end
42
+
43
+ def captures(_identifier)
44
+ nil
45
+ end
46
+ end
47
+
48
+ # @api private
49
+ class RegexpPattern
50
+ def initialize(regexp)
51
+ @regexp = regexp
52
+ end
53
+
54
+ def match?(identifier)
55
+ (identifier.to_s =~ @regexp) != nil
56
+ end
57
+
58
+ def captures(identifier)
59
+ matches = @regexp.match(identifier.to_s)
60
+ matches && matches.captures
61
+ end
62
+ end
63
+ end
@@ -114,8 +114,8 @@ module Nanoc
114
114
  def down
115
115
  end
116
116
 
117
- # Returns the list of items (represented by {Nanoc::Int::Item}) in this site.
118
- # The default implementation simply returns an empty array.
117
+ # Returns the collection of items (represented by {Nanoc::Int::Item}) in
118
+ # this site. The default implementation simply returns an empty array.
119
119
  #
120
120
  # Subclasses should not prepend `items_root` to the item's identifiers, as
121
121
  # this will be done automatically.
@@ -123,13 +123,13 @@ module Nanoc
123
123
  # Subclasses may override this method, but are not required to do so; the
124
124
  # default implementation simply does nothing.
125
125
  #
126
- # @return [Array<Nanoc::Int::Item>] A list of items
126
+ # @return [Enumerable] The collection of items
127
127
  def items
128
128
  []
129
129
  end
130
130
 
131
- # Returns the list of layouts (represented by {Nanoc::Int::Layout}) in this
132
- # site. The default implementation simply returns an empty array.
131
+ # Returns the collection of layouts (represented by {Nanoc::Int::Layout}) in
132
+ # this site. The default implementation simply returns an empty array.
133
133
  #
134
134
  # Subclasses should prepend `layout_root` to the layout's identifiers,
135
135
  # since this is not done automatically.
@@ -137,25 +137,40 @@ module Nanoc
137
137
  # Subclasses may override this method, but are not required to do so; the
138
138
  # default implementation simply does nothing.
139
139
  #
140
- # @return [Array<Nanoc::Int::Layout>] A list of layouts
140
+ # @return [Enumerable] The collection of layouts
141
141
  def layouts
142
142
  []
143
143
  end
144
144
 
145
- def new_item(content, attributes, identifier, params = {})
146
- Nanoc::Int::Item.new(content, attributes, identifier, params)
147
- end
148
-
149
- def new_layout(content, attributes, identifier)
150
- Nanoc::Int::Layout.new(content, attributes, identifier)
145
+ # Creates a new in-memory item instance. This is intended for use within
146
+ # the {#items} method.
147
+ #
148
+ # @param [String] raw_content_or_raw_filename The uncompiled item content
149
+ # (if it is a textual item) or the path to the filename containing the
150
+ # content (if it is a binary item).
151
+ #
152
+ # @param [Hash] attributes A hash containing this item's attributes.
153
+ #
154
+ # @param [String] identifier This item's identifier.
155
+ #
156
+ # @param [Hash] params Extra parameters.
157
+ #
158
+ # @option params [Symbol, nil] :binary (true) Whether or not this item is
159
+ # binary
160
+ def new_item(raw_content_or_raw_filename, attributes, identifier, params = {})
161
+ Nanoc::Int::Item.new(raw_content_or_raw_filename, attributes, identifier, params)
151
162
  end
152
163
 
153
- private
154
-
155
- def not_implemented(name)
156
- raise NotImplementedError.new(
157
- "#{self.class} does not implement ##{name}"
158
- )
164
+ # Creates a new in-memory layout instance. This is intended for use within
165
+ # the {#layouts} method.
166
+ #
167
+ # @param [String] raw_content The raw content of this layout.
168
+ #
169
+ # @param [Hash] attributes A hash containing this layout's attributes.
170
+ #
171
+ # @param [String] identifier This layout's identifier.
172
+ def new_layout(raw_content, attributes, identifier)
173
+ Nanoc::Int::Layout.new(raw_content, attributes, identifier)
159
174
  end
160
175
  end
161
176
  end
@@ -4,8 +4,33 @@ module Nanoc
4
4
  class Identifier
5
5
  include Comparable
6
6
 
7
- def initialize(string)
8
- @string = "/#{string}/".gsub(/^\/+|\/+$/, '/').freeze
7
+ def self.from(obj)
8
+ case obj
9
+ when Nanoc::Identifier
10
+ obj
11
+ when String
12
+ Nanoc::Identifier.new(obj)
13
+ else
14
+ raise ArgumentError, "Do not know how to convert #{obj} into a Nanoc::Identifier"
15
+ end
16
+ end
17
+
18
+ def initialize(string, params = {})
19
+ @style = params.fetch(:style, :stripped)
20
+
21
+ case @style
22
+ when :stripped
23
+ @string = "/#{string}/".gsub(/^\/+|\/+$/, '/').freeze
24
+ when :full
25
+ if string !~ /\A\//
26
+ raise Nanoc::Int::Errors::Generic,
27
+ "Invalid identifier (does not start with a slash): #{string.inspect}"
28
+ end
29
+ @string = string.dup.freeze
30
+ else
31
+ raise Nanoc::Int::Errors::Generic,
32
+ "Invalid :style param for identifier: #{@style.inspect}"
33
+ end
9
34
  end
10
35
 
11
36
  def ==(other)
@@ -35,6 +60,43 @@ module Nanoc
35
60
  to_s + string
36
61
  end
37
62
 
63
+ # @return [Nanoc::Identifier]
64
+ def prefix(string)
65
+ if string !~ /\A\//
66
+ raise Nanoc::Int::Errors::Generic,
67
+ "Invalid prefix (does not start with a slash): #{@string.inspect}"
68
+ end
69
+ Nanoc::Identifier.new(string.sub(/\/+\z/, '') + @string, style: @style)
70
+ end
71
+
72
+ # @return [String]
73
+ def with_ext(ext)
74
+ if @style == :stripped
75
+ raise Nanoc::Int::Errors::Generic,
76
+ 'Cannot use #with_ext on identifier that does not include the file extension'
77
+ end
78
+
79
+ # Strip extension, if any
80
+ extname = File.extname(@string)
81
+ string =
82
+ if extname.size > 0
83
+ @string[0..-extname.size-1]
84
+ else
85
+ @string
86
+ end
87
+
88
+ # Add extension
89
+ if ext.size > 0
90
+ if ext.start_with?('.')
91
+ string + ext
92
+ else
93
+ string + '.' + ext
94
+ end
95
+ else
96
+ string
97
+ end
98
+ end
99
+
38
100
  def to_s
39
101
  @string
40
102
  end
@@ -44,7 +106,7 @@ module Nanoc
44
106
  end
45
107
 
46
108
  def inspect
47
- "<Nanoc::Identifier #{to_s.inspect}>"
109
+ "<Nanoc::Identifier style=#{@style} #{to_s.inspect}>"
48
110
  end
49
111
  end
50
112
  end