nanoc 4.2.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
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