nanoc 4.2.0 → 4.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62464e0106788a92d1c8ebe9ff6b186fe6f00f10
4
- data.tar.gz: a6d7768e4124360a3d48f5805d1b1fd4aa86dd69
3
+ metadata.gz: bcf1b9df213270119c9391459276baf1156c8c2b
4
+ data.tar.gz: 57939ccb41f7b9800f3e60309d425a7e3232e3e8
5
5
  SHA512:
6
- metadata.gz: be55ec0837f06213c9673cb0ebe91e8a973f494a8b90a4c63c6757cdb7083401825a075ed952f994158f3ef72bdee204e98fe516b9c72806ab5c5a27f87effff
7
- data.tar.gz: af81c35ffea130df18be4018e5f20ed18f5d348f9b923c2ebb2521113512d89e2e05238d6a955eadc339c1d553abfd6568f672b8441a61a94cde5a8cb43076e0
6
+ metadata.gz: 103f4ea43eb903dfdaab16054ea0dfaab142d061bc905a48493dfbdcbeccf04c4846239ed9ea5cb85c92c0c3b69c83f3f97481d4e559a791f00c9a99ce4ff5ef
7
+ data.tar.gz: 9e93d95dd041a8492c3c29a472dc26b8422442a80646f8389ba8603fc0c11276b2b03e8aebeb6b181a949835b8a6cdff8b3c5bf3b1ee69afa71e28bb15ea721b
data/Gemfile CHANGED
@@ -3,8 +3,10 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :devel do
6
+ gem 'contracts', '~> 0.14'
6
7
  gem 'coveralls', require: false
7
8
  gem 'guard-rake'
9
+ gem 'fuubar'
8
10
  gem 'minitest', '~> 5.0'
9
11
  gem 'mocha'
10
12
  gem 'pry'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nanoc (4.2.0)
4
+ nanoc (4.2.1)
5
5
  cri (~> 2.3)
6
6
 
7
7
  GEM
@@ -12,7 +12,7 @@ GEM
12
12
  addressable (2.4.0)
13
13
  adsf (1.2.1)
14
14
  rack (>= 1.0.0)
15
- ast (2.2.0)
15
+ ast (2.3.0)
16
16
  bluecloth (2.2.0)
17
17
  builder (3.2.2)
18
18
  chunky_png (1.3.5)
@@ -35,6 +35,7 @@ GEM
35
35
  sass (>= 3.3.0, < 3.5)
36
36
  compass-import-once (1.0.5)
37
37
  sass (>= 3.2, < 3.5)
38
+ contracts (0.14.0)
38
39
  coveralls (0.8.13)
39
40
  json (~> 1.8)
40
41
  simplecov (~> 0.11.0)
@@ -155,7 +156,7 @@ GEM
155
156
  fog-serverlove (0.1.2)
156
157
  fog-core
157
158
  fog-json
158
- fog-softlayer (1.1.1)
159
+ fog-softlayer (1.1.2)
159
160
  fog-core
160
161
  fog-json
161
162
  fog-storm_on_demand (0.1.1)
@@ -170,7 +171,7 @@ GEM
170
171
  fog-voxel (0.1.0)
171
172
  fog-core
172
173
  fog-xml
173
- fog-vsphere (0.7.0)
174
+ fog-vsphere (0.8.0)
174
175
  fog-core
175
176
  rbvmomi (~> 1.8)
176
177
  fog-xenserver (0.2.3)
@@ -180,6 +181,9 @@ GEM
180
181
  fog-core
181
182
  nokogiri (~> 1.5, >= 1.5.11)
182
183
  formatador (0.2.5)
184
+ fuubar (2.0.0)
185
+ rspec (~> 3.0)
186
+ ruby-progressbar (~> 1.4)
183
187
  guard (2.14.0)
184
188
  formatador (>= 0.2.4)
185
189
  listen (>= 2.7, < 4.0)
@@ -219,21 +223,23 @@ GEM
219
223
  mime-types (3.1)
220
224
  mime-types-data (~> 3.2015)
221
225
  mime-types-data (3.2016.0521)
222
- mini_portile2 (2.0.0)
226
+ mini_portile2 (2.1.0)
223
227
  minitest (5.9.0)
224
228
  mocha (1.1.0)
225
229
  metaclass (~> 0.0.1)
226
230
  multi_json (1.12.1)
227
231
  mustache (1.0.3)
228
232
  nenv (0.3.0)
229
- nokogiri (1.6.7.2)
230
- mini_portile2 (~> 2.0.0.rc2)
233
+ nokogiri (1.6.8)
234
+ mini_portile2 (~> 2.1.0)
235
+ pkg-config (~> 1.1.7)
231
236
  notiffany (0.1.0)
232
237
  nenv (~> 0.1)
233
238
  shellany (~> 0.0)
234
239
  pandoc-ruby (2.0.1)
235
240
  parser (2.3.1.2)
236
241
  ast (~> 2.2)
242
+ pkg-config (1.1.7)
237
243
  posix-spawn (0.3.11)
238
244
  powerpack (0.1.1)
239
245
  pry (0.10.3)
@@ -246,7 +252,7 @@ GEM
246
252
  rack (1.6.4)
247
253
  rainbow (2.1.0)
248
254
  rainpress (1.0)
249
- rake (11.1.2)
255
+ rake (11.2.2)
250
256
  rb-fsevent (0.9.7)
251
257
  rb-inotify (0.9.7)
252
258
  ffi (>= 0.5.0)
@@ -259,7 +265,7 @@ GEM
259
265
  json (~> 1.4)
260
266
  redcarpet (3.3.4)
261
267
  ref (2.0.0)
262
- rouge (1.10.1)
268
+ rouge (2.0.1)
263
269
  rspec (3.4.0)
264
270
  rspec-core (~> 3.4.0)
265
271
  rspec-expectations (~> 3.4.0)
@@ -334,9 +340,11 @@ DEPENDENCIES
334
340
  coderay
335
341
  coffee-script
336
342
  compass
343
+ contracts (~> 0.14)
337
344
  coveralls
338
345
  erubis
339
346
  fog
347
+ fuubar
340
348
  guard-rake
341
349
  haml
342
350
  handlebars
@@ -377,4 +385,4 @@ DEPENDENCIES
377
385
  yuicompressor
378
386
 
379
387
  BUNDLED WITH
380
- 1.12.4
388
+ 1.12.5
data/NEWS.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.2.1 (2016-06-19)
4
+
5
+ Fixes:
6
+
7
+ * Fixed an occasional `WeakRef::RefError` (#863, #865)
8
+ * Fixed `show-data` command not running preprocessor (#867, #870)
9
+
3
10
  ## 4.2 (2016-06-04)
4
11
 
5
12
  Enhancements:
@@ -22,6 +22,7 @@ module Nanoc::Int
22
22
  end
23
23
 
24
24
  require_relative 'base/core_ext'
25
+ require_relative 'base/contracts_support'
25
26
 
26
27
  require_relative 'base/entities'
27
28
  require_relative 'base/repos'
@@ -0,0 +1,60 @@
1
+ require 'singleton'
2
+
3
+ module Nanoc::Int
4
+ # @api private
5
+ module ContractsSupport
6
+ class Ignorer
7
+ include Singleton
8
+
9
+ def method_missing(*_args)
10
+ self
11
+ end
12
+ end
13
+
14
+ module DisabledContracts
15
+ Any = Ignorer.instance
16
+ Bool = Ignorer.instance
17
+ Num = Ignorer.instance
18
+ KeywordArgs = Ignorer.instance
19
+ Optional = Ignorer.instance
20
+ Maybe = Ignorer.instance
21
+ None = Ignorer.instance
22
+ ArrayOf = Ignorer.instance
23
+ Or = Ignorer.instance
24
+ Func = Ignorer.instance
25
+ RespondTo = Ignorer.instance
26
+
27
+ def contract(*args)
28
+ end
29
+ end
30
+
31
+ module EnabledContracts
32
+ def contract(*args)
33
+ Contract(*args)
34
+ end
35
+ end
36
+
37
+ def self.included(base)
38
+ contracts_loadable =
39
+ begin
40
+ require 'contracts'
41
+ true
42
+ rescue LoadError
43
+ false
44
+ end
45
+
46
+ should_enable = contracts_loadable && !ENV.key?('DISABLE_CONTRACTS')
47
+
48
+ if should_enable
49
+ unless base.include?(::Contracts::Core)
50
+ base.include(::Contracts::Core)
51
+ base.extend(EnabledContracts)
52
+ base.const_set('C', ::Contracts)
53
+ end
54
+ else
55
+ base.extend(DisabledContracts)
56
+ base.const_set('C', DisabledContracts)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,16 +1,17 @@
1
+ require_relative 'entities/identifier'
2
+ require_relative 'entities/content'
3
+ require_relative 'entities/rule_memory_action'
4
+ require_relative 'entities/rule_memory_actions'
5
+
1
6
  require_relative 'entities/code_snippet'
2
7
  require_relative 'entities/configuration'
3
8
  require_relative 'entities/lazy_value'
4
- require_relative 'entities/content'
5
9
  require_relative 'entities/document'
6
- require_relative 'entities/identifier'
7
10
  require_relative 'entities/identifiable_collection'
8
11
  require_relative 'entities/item'
9
12
  require_relative 'entities/item_rep'
10
13
  require_relative 'entities/layout'
11
14
  require_relative 'entities/pattern'
12
15
  require_relative 'entities/rule_memory'
13
- require_relative 'entities/rule_memory_action'
14
- require_relative 'entities/rule_memory_actions'
15
16
  require_relative 'entities/site'
16
17
  require_relative 'entities/snapshot_def'
@@ -3,6 +3,8 @@ module Nanoc::Int
3
3
  #
4
4
  # @api private
5
5
  class CodeSnippet
6
+ include Nanoc::Int::ContractsSupport
7
+
6
8
  # A string containing the actual code in this code snippet.
7
9
  #
8
10
  # @return [String]
@@ -13,6 +15,7 @@ module Nanoc::Int
13
15
  # @return [String]
14
16
  attr_reader :filename
15
17
 
18
+ contract String, String => C::Any
16
19
  # Creates a new code snippet.
17
20
  #
18
21
  # @param [String] data The raw source code which will be executed before
@@ -24,11 +27,13 @@ module Nanoc::Int
24
27
  @filename = filename
25
28
  end
26
29
 
30
+ contract C::None => nil
27
31
  # Loads the code by executing it.
28
32
  #
29
33
  # @return [void]
30
34
  def load
31
35
  eval(@data, TOPLEVEL_BINDING, @filename)
36
+ nil
32
37
  end
33
38
 
34
39
  # Returns an object that can be used for uniquely identifying objects.
@@ -3,6 +3,8 @@ module Nanoc::Int
3
3
  #
4
4
  # @api private
5
5
  class Configuration
6
+ include Nanoc::Int::ContractsSupport
7
+
6
8
  NONE = Object.new.freeze
7
9
 
8
10
  # The default configuration for a data source. A data source's
@@ -31,6 +33,7 @@ module Nanoc::Int
31
33
  string_pattern_type: 'glob',
32
34
  }.freeze
33
35
 
36
+ contract Hash => C::Any
34
37
  # Creates a new configuration with the given hash.
35
38
  #
36
39
  # @param [Hash] hash The actual configuration hash
@@ -38,6 +41,7 @@ module Nanoc::Int
38
41
  @wrapped = hash.__nanoc_symbolize_keys_recursively
39
42
  end
40
43
 
44
+ contract C::None => self
41
45
  def with_defaults
42
46
  new_wrapped = DEFAULT_CONFIG.merge(@wrapped)
43
47
  new_wrapped[:data_sources] = new_wrapped[:data_sources].map do |ds|
@@ -47,18 +51,22 @@ module Nanoc::Int
47
51
  self.class.new(new_wrapped)
48
52
  end
49
53
 
54
+ contract C::None => Hash
50
55
  def to_h
51
56
  @wrapped
52
57
  end
53
58
 
59
+ contract C::Any => C::Bool
54
60
  def key?(key)
55
61
  @wrapped.key?(key)
56
62
  end
57
63
 
64
+ contract C::Any => C::Any
58
65
  def [](key)
59
66
  @wrapped[key]
60
67
  end
61
68
 
69
+ contract C::Any, C::Maybe[C::Any], C::Maybe[C::Func[C::None => C::Any]] => C::Any
62
70
  def fetch(key, fallback = NONE, &_block)
63
71
  @wrapped.fetch(key) do
64
72
  if !fallback.equal?(NONE)
@@ -71,30 +79,38 @@ module Nanoc::Int
71
79
  end
72
80
  end
73
81
 
82
+ contract C::Any, C::Any => C::Any
74
83
  def []=(key, value)
75
84
  @wrapped[key] = value
76
85
  end
77
86
 
87
+ contract C::Or[Hash, self] => self
78
88
  def merge(hash)
79
89
  self.class.new(@wrapped.merge(hash.to_h))
80
90
  end
81
91
 
92
+ contract C::Any => self
82
93
  def without(key)
83
94
  self.class.new(@wrapped.reject { |k, _v| k == key })
84
95
  end
85
96
 
97
+ contract C::Any => self
86
98
  def update(hash)
87
99
  @wrapped.update(hash)
100
+ self
88
101
  end
89
102
 
103
+ contract C::Func[C::Any, C::Any => C::Any] => self
90
104
  def each
91
105
  @wrapped.each { |k, v| yield(k, v) }
92
106
  self
93
107
  end
94
108
 
109
+ contract C::None => self
95
110
  def freeze
96
111
  super
97
112
  @wrapped.__nanoc_freeze_recursively
113
+ self
98
114
  end
99
115
 
100
116
  # Returns an object that can be used for uniquely identifying objects.
@@ -10,9 +10,12 @@ module Nanoc
10
10
  #
11
11
  # @api private
12
12
  class Content
13
+ include Nanoc::Int::ContractsSupport
14
+
13
15
  # @return [String, nil]
14
16
  attr_reader :filename
15
17
 
18
+ contract C::Maybe[String] => C::Any
16
19
  # @param [String, nil] filename
17
20
  def initialize(filename)
18
21
  if filename && Pathname.new(filename).relative?
@@ -22,14 +25,17 @@ module Nanoc
22
25
  @filename = filename
23
26
  end
24
27
 
28
+ contract C::None => self
25
29
  def freeze
26
30
  super
27
31
  @filename.freeze
32
+ self
28
33
  end
29
34
 
30
- # @param [String, Proc] content The uncompiled item content (if it is textual
31
- # content) or the path to the filename containing the content (if this
32
- # is binary content).
35
+ contract C::Or[Nanoc::Int::Content, String, Proc], C::KeywordArgs[binary: C::Optional[C::Bool], filename: C::Optional[C::Maybe[String]]] => self
36
+ # @param [Nanoc::Int::Content, String, Proc] content The uncompiled item
37
+ # content (if it is textual content) or the path to the filename
38
+ # containing the content (if this is binary content).
33
39
  #
34
40
  # @param [Boolean] binary Whether or not this item is binary
35
41
  #
@@ -57,29 +63,36 @@ module Nanoc
57
63
 
58
64
  # @api private
59
65
  class TextualContent < Content
66
+ contract C::None => String
60
67
  # @return [String]
61
68
  def string
62
69
  @string.value
63
70
  end
64
71
 
72
+ contract C::Or[String, Proc], C::KeywordArgs[filename: C::Optional[C::Maybe[String]]] => C::Any
65
73
  def initialize(string, filename: nil)
66
74
  super(filename)
67
75
  @string = Nanoc::Int::LazyValue.new(string)
68
76
  end
69
77
 
78
+ contract C::None => self
70
79
  def freeze
71
80
  super
72
81
  @string.freeze
82
+ self
73
83
  end
74
84
 
85
+ contract C::None => C::Bool
75
86
  def binary?
76
87
  false
77
88
  end
78
89
 
90
+ # TODO: Add contract
79
91
  def marshal_dump
80
92
  [filename, string]
81
93
  end
82
94
 
95
+ # TODO: Add contract
83
96
  def marshal_load(array)
84
97
  @filename = array[0]
85
98
  @string = Nanoc::Int::LazyValue.new(array[1])
@@ -88,6 +101,7 @@ module Nanoc
88
101
 
89
102
  # @api private
90
103
  class BinaryContent < Content
104
+ contract C::None => C::Bool
91
105
  def binary?
92
106
  true
93
107
  end
@@ -2,6 +2,8 @@ module Nanoc
2
2
  module Int
3
3
  # @api private
4
4
  class Document
5
+ include Nanoc::Int::ContractsSupport
6
+
5
7
  # @return [Nanoc::Int::Content]
6
8
  attr_reader :content
7
9
 
@@ -16,6 +18,12 @@ module Nanoc
16
18
  # @return [String, nil]
17
19
  attr_accessor :checksum_data
18
20
 
21
+ c_content = C::Or[String, Nanoc::Int::Content]
22
+ c_attributes = C::Or[Hash, Proc]
23
+ c_identifier = C::Or[String, Nanoc::Identifier]
24
+ c_checksum_data = C::Optional[C::Maybe[String]]
25
+
26
+ contract c_content, c_attributes, c_identifier, C::KeywordArgs[checksum_data: c_checksum_data] => C::Any
19
27
  # @param [String, Nanoc::Int::Content] content
20
28
  #
21
29
  # @param [Hash, Proc] attributes
@@ -30,13 +38,16 @@ module Nanoc
30
38
  @checksum_data = checksum_data
31
39
  end
32
40
 
41
+ contract C::None => self
33
42
  # @return [void]
34
43
  def freeze
35
44
  super
36
45
  @content.freeze
37
46
  @attributes.freeze
47
+ self
38
48
  end
39
49
 
50
+ contract C::None => String
40
51
  # @abstract
41
52
  #
42
53
  # @return Unique reference to this object
@@ -44,14 +55,17 @@ module Nanoc
44
55
  raise NotImplementedError
45
56
  end
46
57
 
58
+ contract C::None => String
47
59
  def inspect
48
60
  "<#{self.class} identifier=\"#{identifier}\">"
49
61
  end
50
62
 
63
+ contract C::None => C::Num
51
64
  def hash
52
65
  self.class.hash ^ identifier.hash
53
66
  end
54
67
 
68
+ contract C::Any => C::Bool
55
69
  def ==(other)
56
70
  other.respond_to?(:identifier) && identifier == other.identifier
57
71
  end
@@ -1,6 +1,7 @@
1
1
  module Nanoc::Int
2
2
  # @api private
3
3
  class IdentifiableCollection
4
+ include Nanoc::Int::ContractsSupport
4
5
  include Enumerable
5
6
 
6
7
  extend Forwardable
@@ -10,12 +11,15 @@ module Nanoc::Int
10
11
  def_delegator :@objects, :<<
11
12
  def_delegator :@objects, :concat
12
13
 
14
+ # FIXME: use Nanoc::Int::Configuration
15
+ contract C::Any => C::Any
13
16
  def initialize(config)
14
17
  @config = config
15
18
 
16
19
  @objects = []
17
20
  end
18
21
 
22
+ contract C::None => self
19
23
  def freeze
20
24
  @objects.freeze
21
25
  @objects.each(&:freeze)
@@ -23,6 +27,7 @@ module Nanoc::Int
23
27
  super
24
28
  end
25
29
 
30
+ contract C::Any => C::Maybe[C::RespondTo[:identifier]]
26
31
  def [](arg)
27
32
  case arg
28
33
  when Nanoc::Identifier
@@ -36,16 +41,20 @@ module Nanoc::Int
36
41
  end
37
42
  end
38
43
 
44
+ contract C::None => C::ArrayOf[C::RespondTo[:identifier]]
39
45
  def to_a
40
46
  @objects
41
47
  end
42
48
 
49
+ contract C::None => C::Bool
43
50
  def empty?
44
51
  @objects.empty?
45
52
  end
46
53
 
54
+ contract C::Func[C::RespondTo[:identifier] => C::Bool] => self
47
55
  def delete_if(&block)
48
56
  @objects.delete_if(&block)
57
+ self
49
58
  end
50
59
 
51
60
  protected
@@ -1,6 +1,7 @@
1
1
  module Nanoc
2
2
  class Identifier
3
3
  include Comparable
4
+ include Nanoc::Int::ContractsSupport
4
5
 
5
6
  # @api private
6
7
  class InvalidIdentifierError < ::Nanoc::Error
@@ -37,6 +38,7 @@ module Nanoc
37
38
  end
38
39
  end
39
40
 
41
+ contract C::Any => self
40
42
  def self.from(obj)
41
43
  case obj
42
44
  when Nanoc::Identifier
@@ -48,6 +50,7 @@ module Nanoc
48
50
  end
49
51
  end
50
52
 
53
+ contract String, C::KeywordArgs[type: C::Optional[Symbol]] => C::Any
51
54
  def initialize(string, type: :full)
52
55
  @type = type
53
56
 
@@ -64,6 +67,7 @@ module Nanoc
64
67
  end
65
68
  end
66
69
 
70
+ contract C::Any => C::Bool
67
71
  def ==(other)
68
72
  case other
69
73
  when Nanoc::Identifier, String
@@ -74,40 +78,48 @@ module Nanoc
74
78
  end
75
79
  alias eql? ==
76
80
 
81
+ contract C::None => C::Num
77
82
  def hash
78
83
  self.class.hash ^ to_s.hash
79
84
  end
80
85
 
86
+ contract C::Any => C::Maybe[C::Num]
81
87
  def =~(other)
82
88
  Nanoc::Int::Pattern.from(other).match?(to_s) ? 0 : nil
83
89
  end
84
90
 
91
+ contract C::Any => C::Num
85
92
  def <=>(other)
86
93
  to_s <=> other.to_s
87
94
  end
88
95
 
96
+ contract C::None => C::Bool
89
97
  # @return [Boolean] True if this is a full-type identifier (i.e. includes
90
98
  # the extension), false otherwise
91
99
  def full?
92
100
  @type == :full
93
101
  end
94
102
 
103
+ contract C::None => C::Bool
95
104
  # @return [Boolean] True if this is a legacy identifier (i.e. does not
96
105
  # include the extension), false otherwise
97
106
  def legacy?
98
107
  @type == :legacy
99
108
  end
100
109
 
110
+ contract C::None => String
101
111
  # @return [String]
102
112
  def chop
103
113
  to_s.chop
104
114
  end
105
115
 
116
+ contract String => String
106
117
  # @return [String]
107
118
  def +(other)
108
119
  to_s + other
109
120
  end
110
121
 
122
+ contract String => self
111
123
  # @return [Nanoc::Identifier]
112
124
  def prefix(string)
113
125
  if string !~ /\A\//
@@ -116,6 +128,7 @@ module Nanoc
116
128
  Nanoc::Identifier.new(string.sub(/\/+\z/, '') + @string, type: @type)
117
129
  end
118
130
 
131
+ contract C::None => String
119
132
  # @return [String]
120
133
  def without_ext
121
134
  unless full?
@@ -131,7 +144,8 @@ module Nanoc
131
144
  end
132
145
  end
133
146
 
134
- # @return [String] The extension, without a leading dot.
147
+ contract C::None => C::Maybe[String]
148
+ # @return [String, nil] The extension, without a leading dot.
135
149
  def ext
136
150
  unless full?
137
151
  raise UnsupportedLegacyOperationError
@@ -141,6 +155,7 @@ module Nanoc
141
155
  s && s[1..-1]
142
156
  end
143
157
 
158
+ contract C::None => String
144
159
  # @return [String]
145
160
  def without_exts
146
161
  extname = exts.join('.')
@@ -151,6 +166,7 @@ module Nanoc
151
166
  end
152
167
  end
153
168
 
169
+ contract C::None => C::ArrayOf[String]
154
170
  # @return [Array] List of extensions, without a leading dot.
155
171
  def exts
156
172
  unless full?
@@ -161,6 +177,7 @@ module Nanoc
161
177
  s ? s.split('.', -1).drop(1) : []
162
178
  end
163
179
 
180
+ contract C::None => C::ArrayOf[String]
164
181
  def components
165
182
  res = to_s.split('/')
166
183
  if res.empty?
@@ -170,14 +187,17 @@ module Nanoc
170
187
  end
171
188
  end
172
189
 
190
+ contract C::None => String
173
191
  def to_s
174
192
  @string
175
193
  end
176
194
 
195
+ contract C::None => String
177
196
  def to_str
178
197
  @string
179
198
  end
180
199
 
200
+ contract C::None => String
181
201
  def inspect
182
202
  "<Nanoc::Identifier type=#{@type} #{to_s.inspect}>"
183
203
  end
@@ -1,6 +1,8 @@
1
1
  module Nanoc::Int
2
2
  # @api private
3
3
  class ItemRep
4
+ include Nanoc::Int::ContractsSupport
5
+
4
6
  # @return [Hash<Symbol,Nanoc::Int::Content>]
5
7
  attr_accessor :snapshot_contents
6
8
 
@@ -27,6 +29,7 @@ module Nanoc::Int
27
29
  attr_accessor :modified
28
30
  alias modified? modified
29
31
 
32
+ contract Nanoc::Int::Item, Symbol => C::Any
30
33
  # @param [Nanoc::Int::Item] item
31
34
  #
32
35
  # @param [Symbol] name
@@ -45,10 +48,12 @@ module Nanoc::Int
45
48
  @compiled = false
46
49
  end
47
50
 
51
+ contract C::None => C::Bool
48
52
  def binary?
49
53
  @snapshot_contents[:last].binary?
50
54
  end
51
55
 
56
+ contract C::KeywordArgs[snapshot: C::Optional[C::Maybe[Symbol]]] => String
52
57
  # Returns the compiled content from a given snapshot.
53
58
  #
54
59
  # @param [Symbol] snapshot The name of the snapshot from which to
@@ -90,6 +95,7 @@ module Nanoc::Int
90
95
  @snapshot_contents[snapshot_name].string
91
96
  end
92
97
 
98
+ contract Symbol => C::Bool
93
99
  # Checks whether content exists at a given snapshot.
94
100
  #
95
101
  # @return [Boolean] True if content exists for the snapshot with the
@@ -101,6 +107,7 @@ module Nanoc::Int
101
107
  end
102
108
  alias has_snapshot? snapshot?
103
109
 
110
+ contract C::KeywordArgs[snapshot: C::Optional[Symbol]] => C::Maybe[String]
104
111
  # Returns the item rep’s raw path. It includes the path to the output
105
112
  # directory and the full filename.
106
113
  #
@@ -112,6 +119,7 @@ module Nanoc::Int
112
119
  @raw_paths[snapshot]
113
120
  end
114
121
 
122
+ contract C::KeywordArgs[snapshot: C::Optional[Symbol]] => C::Maybe[String]
115
123
  # Returns the item rep’s path, as used when being linked to. It starts
116
124
  # with a slash and it is relative to the output directory. It does not
117
125
  # include the path to the output directory. It will not include the
@@ -125,6 +133,7 @@ module Nanoc::Int
125
133
  @paths[snapshot]
126
134
  end
127
135
 
136
+ contract C::None => nil
128
137
  # Resets the compilation progress for this item representation. This is
129
138
  # necessary when an unmet dependency is detected during compilation.
130
139
  #
@@ -133,6 +142,7 @@ module Nanoc::Int
133
142
  # @return [void]
134
143
  def forget_progress
135
144
  initialize_content
145
+ nil
136
146
  end
137
147
 
138
148
  # Returns an object that can be used for uniquely identifying objects.
@@ -3,6 +3,8 @@ module Nanoc::Int
3
3
  #
4
4
  # @api private
5
5
  class LazyValue
6
+ include Nanoc::Int::ContractsSupport
7
+
6
8
  # @param [Object, Proc] value_or_proc A value or a proc to generate the value
7
9
  def initialize(value_or_proc)
8
10
  @value = { raw: value_or_proc }
@@ -18,6 +20,7 @@ module Nanoc::Int
18
20
  @value[:final]
19
21
  end
20
22
 
23
+ contract C::Func[C::Any => C::Any] => self
21
24
  # Returns a new lazy value that will apply the given transformation when the value is requested.
22
25
  #
23
26
  # @yield resolved value
@@ -27,10 +30,12 @@ module Nanoc::Int
27
30
  Nanoc::Int::LazyValue.new(-> { yield(value) })
28
31
  end
29
32
 
33
+ contract C::None => self
30
34
  # @return [void]
31
35
  def freeze
32
36
  super
33
37
  @value.__nanoc_freeze_recursively unless @value[:raw]
38
+ self
34
39
  end
35
40
  end
36
41
  end
@@ -1,6 +1,9 @@
1
1
  module Nanoc::Int
2
2
  # @api private
3
3
  class Pattern
4
+ include Nanoc::Int::ContractsSupport
5
+
6
+ contract C::Any => self
4
7
  def self.from(obj)
5
8
  case obj
6
9
  when Nanoc::Int::StringPattern, Nanoc::Int::RegexpPattern
@@ -28,41 +31,49 @@ module Nanoc::Int
28
31
  end
29
32
 
30
33
  # @api private
31
- class StringPattern
34
+ class StringPattern < Pattern
32
35
  MATCH_OPTS = File::FNM_PATHNAME | File::FNM_EXTGLOB
33
36
 
37
+ contract String => C::Any
34
38
  def initialize(string)
35
39
  @string = string
36
40
  end
37
41
 
42
+ contract C::Or[Nanoc::Identifier, String] => C::Bool
38
43
  def match?(identifier)
39
44
  File.fnmatch(@string, identifier.to_s, MATCH_OPTS)
40
45
  end
41
46
 
47
+ contract C::Or[Nanoc::Identifier, String] => nil
42
48
  def captures(_identifier)
43
49
  nil
44
50
  end
45
51
 
52
+ contract C::None => String
46
53
  def to_s
47
54
  @string
48
55
  end
49
56
  end
50
57
 
51
58
  # @api private
52
- class RegexpPattern
59
+ class RegexpPattern < Pattern
60
+ contract Regexp => C::Any
53
61
  def initialize(regexp)
54
62
  @regexp = regexp
55
63
  end
56
64
 
65
+ contract C::Or[Nanoc::Identifier, String] => C::Bool
57
66
  def match?(identifier)
58
67
  (identifier.to_s =~ @regexp) != nil
59
68
  end
60
69
 
70
+ contract C::Or[Nanoc::Identifier, String] => C::Maybe[C::ArrayOf[String]]
61
71
  def captures(identifier)
62
72
  matches = @regexp.match(identifier.to_s)
63
73
  matches && matches.captures
64
74
  end
65
75
 
76
+ contract C::None => String
66
77
  def to_s
67
78
  @regexp.to_s
68
79
  end
@@ -1,5 +1,6 @@
1
1
  module Nanoc::Int
2
2
  class RuleMemory
3
+ include Nanoc::Int::ContractsSupport
3
4
  include Enumerable
4
5
 
5
6
  def initialize(item_rep)
@@ -7,41 +8,54 @@ module Nanoc::Int
7
8
  @actions = []
8
9
  end
9
10
 
11
+ contract C::None => Numeric
10
12
  def size
11
13
  @actions.size
12
14
  end
13
15
 
16
+ contract Numeric => C::Maybe[Nanoc::Int::RuleMemoryAction]
14
17
  def [](idx)
15
18
  @actions[idx]
16
19
  end
17
20
 
21
+ contract Symbol, Hash => self
18
22
  def add_filter(filter_name, params)
19
23
  @actions << Nanoc::Int::RuleMemoryActions::Filter.new(filter_name, params)
24
+ self
20
25
  end
21
26
 
27
+ contract String, C::Maybe[Hash] => self
22
28
  def add_layout(layout_identifier, params)
23
29
  @actions << Nanoc::Int::RuleMemoryActions::Layout.new(layout_identifier, params)
30
+ self
24
31
  end
25
32
 
33
+ contract Symbol, C::Bool, C::Maybe[String] => self
26
34
  def add_snapshot(snapshot_name, final, path)
27
35
  will_add_snapshot(snapshot_name) if final
28
36
  @actions << Nanoc::Int::RuleMemoryActions::Snapshot.new(snapshot_name, final, path)
37
+ self
29
38
  end
30
39
 
40
+ contract C::None => C::ArrayOf[Nanoc::Int::RuleMemoryAction]
31
41
  def snapshot_actions
32
42
  @actions.select { |a| a.is_a?(Nanoc::Int::RuleMemoryActions::Snapshot) }
33
43
  end
34
44
 
45
+ contract C::None => C::Bool
35
46
  def any_layouts?
36
47
  @actions.any? { |a| a.is_a?(Nanoc::Int::RuleMemoryActions::Layout) }
37
48
  end
38
49
 
50
+ # TODO: Add contract
39
51
  def serialize
40
52
  map(&:serialize)
41
53
  end
42
54
 
55
+ contract C::Func[Nanoc::Int::RuleMemoryAction => C::Any] => self
43
56
  def each
44
57
  @actions.each { |a| yield(a) }
58
+ self
45
59
  end
46
60
 
47
61
  private
@@ -1,8 +1,11 @@
1
1
  module Nanoc::Int
2
2
  # @api private
3
3
  class Site
4
+ include Nanoc::Int::ContractsSupport
5
+
4
6
  attr_accessor :compiler
5
7
 
8
+ contract C::KeywordArgs[config: Nanoc::Int::Configuration, code_snippets: C::RespondTo[:each], items: C::RespondTo[:each], layouts: C::RespondTo[:each]] => C::Any
6
9
  # @param [Nanoc::Int::Configuration] config
7
10
  # @param [Enumerable<Nanoc::Int::CodeSnippet>] code_snippets
8
11
  # @param [Enumerable<Nanoc::Int::Item>] items
@@ -17,6 +20,7 @@ module Nanoc::Int
17
20
  ensure_identifier_uniqueness(@layouts, 'layout')
18
21
  end
19
22
 
23
+ contract C::None => self
20
24
  # Compiles the site.
21
25
  #
22
26
  # @return [void]
@@ -24,8 +28,10 @@ module Nanoc::Int
24
28
  # @since 3.2.0
25
29
  def compile
26
30
  compiler.run_all
31
+ self
27
32
  end
28
33
 
34
+ contract C::None => Nanoc::Int::Compiler
29
35
  # Returns the compiler for this site. Will create a new compiler if none
30
36
  # exists yet.
31
37
  #
@@ -39,6 +45,7 @@ module Nanoc::Int
39
45
  attr_reader :items
40
46
  attr_reader :layouts
41
47
 
48
+ contract C::None => self
42
49
  # Prevents all further modifications to itself, its items, its layouts etc.
43
50
  #
44
51
  # @return [void]
@@ -47,8 +54,10 @@ module Nanoc::Int
47
54
  items.freeze
48
55
  layouts.freeze
49
56
  code_snippets.__nanoc_freeze_recursively
57
+ self
50
58
  end
51
59
 
60
+ contract C::RespondTo[:each], String => self
52
61
  def ensure_identifier_uniqueness(objects, type)
53
62
  seen = Set.new
54
63
  objects.each do |obj|
@@ -57,6 +66,7 @@ module Nanoc::Int
57
66
  end
58
67
  seen << obj.identifier
59
68
  end
69
+ self
60
70
  end
61
71
  end
62
72
  end
@@ -1,13 +1,17 @@
1
1
  module Nanoc
2
2
  module Int
3
3
  class SnapshotDef
4
+ include Nanoc::Int::ContractsSupport
5
+
4
6
  attr_reader :name
5
7
 
8
+ contract Symbol, C::Bool => C::Any
6
9
  def initialize(name, is_final)
7
10
  @name = name
8
11
  @is_final = is_final
9
12
  end
10
13
 
14
+ contract C::None => C::Bool
11
15
  def final?
12
16
  @is_final
13
17
  end
@@ -15,6 +15,8 @@ module Nanoc::Int
15
15
  end
16
16
  end
17
17
 
18
+ NONE = Object.new
19
+
18
20
  # Memoizes the method with the given name. The modified method will cache
19
21
  # the results of the original method, so that calling a method twice with
20
22
  # the same arguments will short-circuit and return the cached results
@@ -57,12 +59,22 @@ module Nanoc::Int
57
59
  @__memoization_cache[method_name] ||= {}
58
60
  method_cache = @__memoization_cache[method_name]
59
61
 
60
- if method_cache.key?(args) && method_cache[args].weakref_alive?
61
- method_cache[args].value
62
- else
62
+ value = NONE
63
+ if method_cache.key?(args)
64
+ value =
65
+ begin
66
+ method_cache[args].value
67
+ rescue WeakRef::RefError
68
+ NONE
69
+ end
70
+ end
71
+
72
+ if value.equal?(NONE)
63
73
  send(original_method_name, *args).tap do |r|
64
74
  method_cache[args] = WeakRef.new(Wrapper.new(r))
65
75
  end
76
+ else
77
+ value
66
78
  end
67
79
  end
68
80
  end
@@ -44,7 +44,7 @@ module Nanoc::CLI
44
44
  # Asserts that the current working directory contains a site and loads the site into memory.
45
45
  #
46
46
  # @return [void]
47
- def load_site
47
+ def load_site(preprocess: false)
48
48
  print 'Loading site… '
49
49
  $stdout.flush
50
50
 
@@ -52,6 +52,10 @@ module Nanoc::CLI
52
52
  raise ::Nanoc::Int::Errors::GenericTrivial, 'The current working directory does not seem to be a Nanoc site.'
53
53
  end
54
54
 
55
+ if preprocess
56
+ site.compiler.action_provider.preprocess(site)
57
+ end
58
+
55
59
  puts 'done'
56
60
  end
57
61
 
@@ -12,8 +12,7 @@ module Nanoc::CLI::Commands
12
12
  class Check < ::Nanoc::CLI::CommandRunner
13
13
  def run
14
14
  validate_options_and_arguments
15
- load_site
16
- site.compiler.action_provider.preprocess(site)
15
+ load_site(preprocess: true)
17
16
 
18
17
  runner = Nanoc::Extra::Checking::Runner.new(site)
19
18
 
@@ -13,7 +13,7 @@ option :n, :'dry-run', 'show what would be deployed'
13
13
  module Nanoc::CLI::Commands
14
14
  class Deploy < ::Nanoc::CLI::CommandRunner
15
15
  def run
16
- prepare
16
+ load_site(preprocess: true)
17
17
 
18
18
  if options[:'list-deployers']
19
19
  list_deployers
@@ -26,12 +26,6 @@ module Nanoc::CLI::Commands
26
26
 
27
27
  private
28
28
 
29
- def prepare
30
- load_site
31
- # FIXME: ugly to preprocess here
32
- site.compiler.action_provider.preprocess(site)
33
- end
34
-
35
29
  def list_deployers
36
30
  deployers = Nanoc::Int::PluginRegistry.instance.find_all(Nanoc::Extra::Deployer)
37
31
  deployer_names = deployers.keys.sort_by(&:to_s)
@@ -15,9 +15,7 @@ flag :n, :'dry-run', 'print files to be deleted instead of actually deleting the
15
15
  module Nanoc::CLI::Commands
16
16
  class Prune < ::Nanoc::CLI::CommandRunner
17
17
  def run
18
- load_site
19
- # FIXME: ugly to preprocess here
20
- site.compiler.action_provider.preprocess(site)
18
+ load_site(preprocess: true)
21
19
  site.compiler.build_reps
22
20
 
23
21
  if options.key?(:yes)
@@ -9,7 +9,7 @@ EOS
9
9
  module Nanoc::CLI::Commands
10
10
  class ShowData < ::Nanoc::CLI::CommandRunner
11
11
  def run
12
- load_site
12
+ load_site(preprocess: true)
13
13
 
14
14
  # Get data
15
15
  items = site.items
@@ -1,4 +1,4 @@
1
1
  module Nanoc
2
2
  # The current Nanoc version.
3
- VERSION = '4.2.0'.freeze
3
+ VERSION = '4.2.1'.freeze
4
4
  end
@@ -17,7 +17,7 @@ namespace :test do
17
17
  end
18
18
 
19
19
  RSpec::Core::RakeTask.new(:spec) do |t|
20
- t.rspec_opts = '-r ./spec/spec_helper.rb --color'
20
+ t.rspec_opts = '-r ./spec/spec_helper.rb --format Fuubar --color'
21
21
  t.verbose = false
22
22
  end
23
23
 
@@ -4,7 +4,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
4
4
  item = Nanoc::Int::Item.new(
5
5
  'blah blah blah', {}, '/'
6
6
  )
7
- rep = Nanoc::Int::ItemRep.new(item, nil)
7
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
8
8
  rep.snapshot_contents = {
9
9
  last: Nanoc::Int::TextualContent.new('last content'),
10
10
  }
@@ -19,7 +19,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
19
19
  item = Nanoc::Int::Item.new(
20
20
  'blah blah blah', {}, '/'
21
21
  )
22
- rep = Nanoc::Int::ItemRep.new(item, nil)
22
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
23
23
  rep.snapshot_contents = {
24
24
  pre: Nanoc::Int::TextualContent.new('pre content'),
25
25
  last: Nanoc::Int::TextualContent.new('last content'),
@@ -35,7 +35,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
35
35
  item = Nanoc::Int::Item.new(
36
36
  'blah blah blah', {}, '/'
37
37
  )
38
- rep = Nanoc::Int::ItemRep.new(item, nil)
38
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
39
39
  rep.snapshot_contents = {
40
40
  pre: Nanoc::Int::TextualContent.new('pre content'),
41
41
  last: Nanoc::Int::TextualContent.new('last content'),
@@ -51,7 +51,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
51
51
  item = Nanoc::Int::Item.new(
52
52
  'blah blah blah', {}, '/'
53
53
  )
54
- rep = Nanoc::Int::ItemRep.new(item, nil)
54
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
55
55
  rep.snapshot_contents = {
56
56
  pre: Nanoc::Int::TextualContent.new('pre content'),
57
57
  last: Nanoc::Int::TextualContent.new('last content'),
@@ -68,7 +68,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
68
68
  item = Nanoc::Int::Item.new(
69
69
  'blah blah', {}, '/'
70
70
  )
71
- rep = Nanoc::Int::ItemRep.new(item, nil)
71
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
72
72
  rep.expects(:compiled?).returns(false)
73
73
 
74
74
  # Check
@@ -82,7 +82,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
82
82
  item = Nanoc::Int::Item.new(
83
83
  'blah blah', {}, '/'
84
84
  )
85
- rep = Nanoc::Int::ItemRep.new(item, nil)
85
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
86
86
  rep.expects(:compiled?).returns(false)
87
87
  rep.snapshot_contents = {
88
88
  pre: Nanoc::Int::TextualContent.new('pre!'),
@@ -100,7 +100,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
100
100
  item = Nanoc::Int::Item.new(
101
101
  'blah blah', {}, '/'
102
102
  )
103
- rep = Nanoc::Int::ItemRep.new(item, nil)
103
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
104
104
  rep.expects(:compiled?).returns(false)
105
105
  rep.snapshot_defs = [
106
106
  Nanoc::Int::SnapshotDef.new(:pre, true),
@@ -120,7 +120,7 @@ class Nanoc::Int::ItemRepTest < Nanoc::TestCase
120
120
  item = Nanoc::Int::Item.new(
121
121
  'blah blah', {}, '/'
122
122
  )
123
- rep = Nanoc::Int::ItemRep.new(item, nil)
123
+ rep = Nanoc::Int::ItemRep.new(item, :donkeys)
124
124
  rep.expects(:compiled?).returns(false)
125
125
  rep.snapshot_defs = [
126
126
  Nanoc::Int::SnapshotDef.new(:pre, false),
@@ -406,7 +406,7 @@ after
406
406
  EOS
407
407
  expected_output = <<EOS
408
408
  before
409
- <pre><code class=\"language-ruby highlight\"> <span class=\"k\">def</span> <span class=\"nf\">foo</span>
409
+ <pre><code class=\"language-ruby\"> <span class=\"k\">def</span> <span class=\"nf\">foo</span>
410
410
  <span class=\"k\">end</span></code></pre>
411
411
  after
412
412
  EOS
@@ -416,31 +416,4 @@ EOS
416
416
  assert_equal(expected_output, actual_output)
417
417
  end
418
418
  end
419
-
420
- def test_rouge_with_css_class
421
- if_have 'rouge', 'nokogiri' do
422
- # Create filter
423
- filter = ::Nanoc::Filters::ColorizeSyntax.new
424
-
425
- # Get input and expected output
426
- input = <<EOS
427
- before
428
- <pre><code class="language-ruby">
429
- def foo
430
- end
431
- </code></pre>
432
- after
433
- EOS
434
- expected_output = <<EOS
435
- before
436
- <pre><code class=\"language-ruby my-class\"> <span class=\"k\">def</span> <span class=\"nf\">foo</span>
437
- <span class=\"k\">end</span></code></pre>
438
- after
439
- EOS
440
-
441
- # Run filter
442
- actual_output = filter.setup_and_run(input, default_colorizer: :rouge, rouge: { css_class: 'my-class' })
443
- assert_equal(expected_output, actual_output)
444
- end
445
- end
446
419
  end
@@ -1,9 +1,8 @@
1
+ $VERBOSE = false
2
+
1
3
  require 'simplecov'
2
4
  SimpleCov.start
3
5
 
4
- require 'minitest/test'
5
- require 'minitest/spec'
6
- require 'minitest/mock'
7
6
  require 'minitest/autorun'
8
7
  require 'mocha/setup'
9
8
  require 'vcr'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-04 00:00:00.000000000 Z
11
+ date: 2016-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cri
@@ -80,6 +80,7 @@ files:
80
80
  - lib/nanoc/base/compilation/outdatedness_checker.rb
81
81
  - lib/nanoc/base/compilation/outdatedness_reasons.rb
82
82
  - lib/nanoc/base/context.rb
83
+ - lib/nanoc/base/contracts_support.rb
83
84
  - lib/nanoc/base/core_ext.rb
84
85
  - lib/nanoc/base/core_ext/array.rb
85
86
  - lib/nanoc/base/core_ext/hash.rb