middleman-core 4.0.0.alpha.6 → 4.0.0.beta.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 +4 -4
- data/features/asset_hash.feature +8 -1
- data/features/asset_host.feature +2 -13
- data/features/builder.feature +0 -2
- data/features/cli_init.feature +32 -0
- data/features/collections.feature +50 -0
- data/features/directory_index.feature +4 -5
- data/features/front-matter-neighbor.feature +20 -0
- data/features/helpers_link_to.feature +18 -0
- data/features/image_srcset_paths.feature +7 -0
- data/features/markdown_kramdown_in_haml.feature +2 -1
- data/features/minify_javascript.feature +1 -1
- data/features/multiple-sources.feature +8 -0
- data/fixtures/asset-hash-app/source/slim.html.slim +8 -0
- data/fixtures/asset-hash-app/source/subdir/index.html.erb +10 -1
- data/fixtures/asset-host-app/source/asset_host.html.erb +23 -1
- data/fixtures/collections-app/source/blog2/2011-01-01-new-article.html.markdown +2 -0
- data/fixtures/frontmatter-settings-neighbor-app/config.rb +19 -14
- data/fixtures/image-srcset-paths-app/image-srcset-paths.html.erb +1 -0
- data/fixtures/image-srcset-paths-app/images/blank.gif +0 -0
- data/fixtures/indexable-app/source/evil spaces.html +1 -1
- data/fixtures/large-build-app/config.rb +2 -0
- data/fixtures/large-build-app/source/spaces in file.html.erb +1 -1
- data/fixtures/more-traversal-app/source/layout.erb +1 -1
- data/fixtures/multiple-sources-with-duplicate-file-names-app/config.rb +2 -0
- data/fixtures/multiple-sources-with-duplicate-file-names-app/source/index.html.erb +1 -0
- data/fixtures/multiple-sources-with-duplicate-file-names-app/source2/index.html.erb +1 -0
- data/fixtures/traversal-app/source/.htaccess +0 -0
- data/fixtures/traversal-app/source/layout.erb +1 -1
- data/lib/middleman/rack.rb +1 -0
- data/lib/middleman-core/application.rb +15 -15
- data/lib/middleman-core/builder.rb +11 -7
- data/lib/middleman-core/cli/server.rb +86 -0
- data/lib/middleman-core/config_context.rb +1 -1
- data/lib/middleman-core/contracts.rb +0 -32
- data/lib/middleman-core/core_extensions/collections.rb +19 -17
- data/lib/middleman-core/core_extensions/data.rb +15 -17
- data/lib/middleman-core/core_extensions/default_helpers.rb +22 -1
- data/lib/middleman-core/core_extensions/file_watcher.rb +9 -7
- data/lib/middleman-core/core_extensions/front_matter.rb +2 -2
- data/lib/middleman-core/core_extensions/i18n.rb +11 -9
- data/lib/middleman-core/core_extensions/routing.rb +3 -4
- data/lib/middleman-core/extension.rb +179 -0
- data/lib/middleman-core/extension_manager.rb +8 -7
- data/lib/middleman-core/extensions/asset_hash.rb +14 -9
- data/lib/middleman-core/extensions/asset_host.rb +3 -1
- data/lib/middleman-core/extensions/gzip.rb +3 -2
- data/lib/middleman-core/extensions/lorem.rb +2 -2
- data/lib/middleman-core/extensions/relative_assets.rb +11 -5
- data/lib/middleman-core/file_renderer.rb +2 -2
- data/lib/middleman-core/logger.rb +1 -1
- data/lib/middleman-core/middleware/inline_url_rewriter.rb +9 -4
- data/lib/middleman-core/preview_server.rb +13 -9
- data/lib/middleman-core/rack.rb +2 -1
- data/lib/middleman-core/renderers/haml.rb +6 -0
- data/lib/middleman-core/renderers/kramdown.rb +1 -1
- data/lib/middleman-core/renderers/redcarpet.rb +1 -0
- data/lib/middleman-core/renderers/sass.rb +1 -1
- data/lib/middleman-core/renderers/slim.rb +1 -0
- data/lib/middleman-core/sitemap/extensions/ignores.rb +7 -4
- data/lib/middleman-core/sitemap/extensions/on_disk.rb +1 -1
- data/lib/middleman-core/sitemap/extensions/proxies.rb +13 -10
- data/lib/middleman-core/sitemap/extensions/redirects.rb +8 -7
- data/lib/middleman-core/sitemap/extensions/request_endpoints.rb +7 -6
- data/lib/middleman-core/sitemap/extensions/traversal.rb +3 -1
- data/lib/middleman-core/sitemap/resource.rb +14 -15
- data/lib/middleman-core/sitemap/store.rb +6 -5
- data/lib/middleman-core/sources/source_watcher.rb +29 -16
- data/lib/middleman-core/sources.rb +19 -21
- data/lib/middleman-core/step_definitions/builder_steps.rb +1 -1
- data/lib/middleman-core/step_definitions/server_steps.rb +3 -3
- data/lib/middleman-core/template_context.rb +8 -7
- data/lib/middleman-core/template_renderer.rb +2 -2
- data/lib/middleman-core/util.rb +57 -21
- data/lib/middleman-core/version.rb +1 -1
- data/lib/middleman-core.rb +2 -1
- data/middleman-core.gemspec +4 -1
- data/spec/middleman-core/core_extensions/data_spec.rb +41 -0
- data/spec/middleman-core/util_spec.rb +96 -0
- metadata +38 -8
- data/lib/middleman-core/util/hash_with_indifferent_access.rb +0 -103
- data/spec/middleman-core/binary_spec.rb +0 -15
- data/spec/middleman-core/path_match_spec.rb +0 -37
|
@@ -7,12 +7,15 @@ module Middleman
|
|
|
7
7
|
# Manages the list of proxy configurations and manipulates the sitemap
|
|
8
8
|
# to include new resources based on those configurations
|
|
9
9
|
class Proxies < Extension
|
|
10
|
+
# Expose `create_proxy` as `app.proxy`
|
|
11
|
+
expose_to_application proxy: :create_proxy
|
|
12
|
+
|
|
13
|
+
# Expose `create_proxy` to config as `proxy`
|
|
14
|
+
expose_to_config proxy: :create_proxy
|
|
15
|
+
|
|
10
16
|
def initialize(app, config={}, &block)
|
|
11
17
|
super
|
|
12
18
|
|
|
13
|
-
@app.add_to_config_context(:proxy, &method(:create_proxy))
|
|
14
|
-
@app.define_singleton_method(:proxy, &method(:create_proxy))
|
|
15
|
-
|
|
16
19
|
@proxy_configs = Set.new
|
|
17
20
|
@post_config = false
|
|
18
21
|
end
|
|
@@ -71,10 +74,10 @@ module Middleman
|
|
|
71
74
|
ProxyResource.new(app.sitemap, path, target).tap do |p|
|
|
72
75
|
md = metadata.dup
|
|
73
76
|
p.add_metadata(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
locals: md.delete(:locals) || {},
|
|
78
|
+
page: md.delete(:data) || {},
|
|
79
|
+
options: md
|
|
80
|
+
)
|
|
78
81
|
end
|
|
79
82
|
end
|
|
80
83
|
end
|
|
@@ -96,7 +99,7 @@ module Middleman
|
|
|
96
99
|
# The resource for the page this page is proxied to. Throws an exception
|
|
97
100
|
# if there is no resource.
|
|
98
101
|
# @return [Sitemap::Resource]
|
|
99
|
-
Contract
|
|
102
|
+
Contract IsA['Middleman::Sitemap::Resource']
|
|
100
103
|
def target_resource
|
|
101
104
|
resource = @store.find_resource_by_path(@target)
|
|
102
105
|
|
|
@@ -111,12 +114,12 @@ module Middleman
|
|
|
111
114
|
resource
|
|
112
115
|
end
|
|
113
116
|
|
|
114
|
-
Contract
|
|
117
|
+
Contract IsA['Middleman::SourceFile']
|
|
115
118
|
def source_file
|
|
116
119
|
target_resource.source_file
|
|
117
120
|
end
|
|
118
121
|
|
|
119
|
-
Contract
|
|
122
|
+
Contract Maybe[String]
|
|
120
123
|
def content_type
|
|
121
124
|
mime_type = super
|
|
122
125
|
return mime_type if mime_type
|
|
@@ -7,18 +7,19 @@ module Middleman
|
|
|
7
7
|
# Manages the list of proxy configurations and manipulates the sitemap
|
|
8
8
|
# to include new resources based on those configurations
|
|
9
9
|
class Redirects < Extension
|
|
10
|
+
# Expose `create_redirect` to config as `redirect`
|
|
11
|
+
expose_to_config redirect: :create_redirect
|
|
12
|
+
|
|
10
13
|
def initialize(app, config={}, &block)
|
|
11
14
|
super
|
|
12
15
|
|
|
13
|
-
@app.add_to_config_context(:redirect, &method(:create_redirect))
|
|
14
|
-
|
|
15
16
|
@redirects = {}
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
# Setup a redirect from a path to a target
|
|
19
20
|
# @param [String] path
|
|
20
21
|
# @param [Hash] opts The :to value gives a target path
|
|
21
|
-
Contract String, ({ to: Or[String, IsA['Middleman::Sitemap::Resource']] }), Proc => Any
|
|
22
|
+
Contract String, ({ to: Or[String, IsA['Middleman::Sitemap::Resource']] }), Maybe[Proc] => Any
|
|
22
23
|
def create_redirect(path, opts={}, &block)
|
|
23
24
|
opts[:template] = block if block_given?
|
|
24
25
|
|
|
@@ -44,7 +45,7 @@ module Middleman
|
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
class RedirectResource < ::Middleman::Sitemap::Resource
|
|
47
|
-
Contract
|
|
48
|
+
Contract Maybe[Proc]
|
|
48
49
|
attr_accessor :output
|
|
49
50
|
|
|
50
51
|
def initialize(store, path, target)
|
|
@@ -53,7 +54,7 @@ module Middleman
|
|
|
53
54
|
super(store, path)
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
Contract
|
|
57
|
+
Contract Bool
|
|
57
58
|
def template?
|
|
58
59
|
true
|
|
59
60
|
end
|
|
@@ -63,7 +64,7 @@ module Middleman
|
|
|
63
64
|
url = ::Middleman::Util.url_for(@store.app, @request_path,
|
|
64
65
|
relative: false,
|
|
65
66
|
find_resource: true
|
|
66
|
-
|
|
67
|
+
)
|
|
67
68
|
|
|
68
69
|
if output
|
|
69
70
|
output.call(path, url)
|
|
@@ -82,7 +83,7 @@ module Middleman
|
|
|
82
83
|
end
|
|
83
84
|
end
|
|
84
85
|
|
|
85
|
-
Contract
|
|
86
|
+
Contract Bool
|
|
86
87
|
def ignored?
|
|
87
88
|
false
|
|
88
89
|
end
|
|
@@ -4,13 +4,14 @@ module Middleman
|
|
|
4
4
|
module Sitemap
|
|
5
5
|
module Extensions
|
|
6
6
|
class RequestEndpoints < Extension
|
|
7
|
+
# Expose `create_endpoint` to config as `endpoint`
|
|
8
|
+
expose_to_config endpoint: :create_endpoint
|
|
9
|
+
|
|
7
10
|
# Manages the list of proxy configurations and manipulates the sitemap
|
|
8
11
|
# to include new resources based on those configurations
|
|
9
12
|
def initialize(app, config={}, &block)
|
|
10
13
|
super
|
|
11
14
|
|
|
12
|
-
@app.add_to_config_context(:endpoint, &method(:create_endpoint))
|
|
13
|
-
|
|
14
15
|
@endpoints = {}
|
|
15
16
|
end
|
|
16
17
|
|
|
@@ -52,7 +53,7 @@ module Middleman
|
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
class EndpointResource < ::Middleman::Sitemap::Resource
|
|
55
|
-
Contract
|
|
56
|
+
Contract Maybe[Proc]
|
|
56
57
|
attr_accessor :output
|
|
57
58
|
|
|
58
59
|
def initialize(store, path, request_path)
|
|
@@ -60,10 +61,10 @@ module Middleman
|
|
|
60
61
|
@request_path = ::Middleman::Util.normalize_path(request_path)
|
|
61
62
|
end
|
|
62
63
|
|
|
63
|
-
Contract
|
|
64
|
+
Contract String
|
|
64
65
|
attr_reader :request_path
|
|
65
66
|
|
|
66
|
-
Contract
|
|
67
|
+
Contract Bool
|
|
67
68
|
def template?
|
|
68
69
|
true
|
|
69
70
|
end
|
|
@@ -73,7 +74,7 @@ module Middleman
|
|
|
73
74
|
return output.call if output
|
|
74
75
|
end
|
|
75
76
|
|
|
76
|
-
Contract
|
|
77
|
+
Contract Bool
|
|
77
78
|
def ignored?
|
|
78
79
|
false
|
|
79
80
|
end
|
|
@@ -9,7 +9,9 @@ module Middleman
|
|
|
9
9
|
tail = parts.pop
|
|
10
10
|
is_index = (tail == @app.config[:index_file])
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
if parts.empty?
|
|
13
|
+
return is_index ? nil : @store.find_resource_by_path(@app.config[:index_file])
|
|
14
|
+
end
|
|
13
15
|
|
|
14
16
|
test_expr = parts.join('\\/')
|
|
15
17
|
# eponymous reverse-lookup
|
|
@@ -23,7 +23,7 @@ module Middleman
|
|
|
23
23
|
|
|
24
24
|
# The on-disk source file for this resource, if there is one
|
|
25
25
|
# @return [String]
|
|
26
|
-
Contract
|
|
26
|
+
Contract Maybe[IsA['Middleman::SourceFile']]
|
|
27
27
|
attr_reader :source_file
|
|
28
28
|
|
|
29
29
|
# The path to use when requesting this resource. Normally it's
|
|
@@ -35,7 +35,7 @@ module Middleman
|
|
|
35
35
|
|
|
36
36
|
# The metadata for this resource
|
|
37
37
|
# @return [Hash]
|
|
38
|
-
Contract
|
|
38
|
+
Contract METADATA_HASH
|
|
39
39
|
attr_reader :metadata
|
|
40
40
|
|
|
41
41
|
# Initialize resource with parent store and URL
|
|
@@ -46,7 +46,7 @@ module Middleman
|
|
|
46
46
|
def initialize(store, path, source_file=nil)
|
|
47
47
|
@store = store
|
|
48
48
|
@app = @store.app
|
|
49
|
-
@path = path
|
|
49
|
+
@path = path
|
|
50
50
|
|
|
51
51
|
if source_file && source_file.is_a?(String)
|
|
52
52
|
source_file = Pathname(source_file)
|
|
@@ -69,7 +69,7 @@ module Middleman
|
|
|
69
69
|
|
|
70
70
|
# Whether this resource has a template file
|
|
71
71
|
# @return [Boolean]
|
|
72
|
-
Contract
|
|
72
|
+
Contract Bool
|
|
73
73
|
def template?
|
|
74
74
|
return false if source_file.nil?
|
|
75
75
|
!::Tilt[source_file[:full_path].to_s].nil?
|
|
@@ -87,31 +87,30 @@ module Middleman
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
# Data about this resource, populated from frontmatter or extensions.
|
|
90
|
-
# @return [
|
|
91
|
-
Contract
|
|
90
|
+
# @return [IndifferentHash]
|
|
91
|
+
Contract IsA['Middleman::Util::IndifferentHash']
|
|
92
92
|
def data
|
|
93
|
-
# TODO: Should this really be a HashWithIndifferentAccess?
|
|
94
93
|
::Middleman::Util.recursively_enhance(metadata[:page])
|
|
95
94
|
end
|
|
96
95
|
|
|
97
96
|
# Options about how this resource is rendered, such as its :layout,
|
|
98
97
|
# :renderer_options, and whether or not to use :directory_indexes.
|
|
99
98
|
# @return [Hash]
|
|
100
|
-
Contract
|
|
99
|
+
Contract Hash
|
|
101
100
|
def options
|
|
102
101
|
metadata[:options]
|
|
103
102
|
end
|
|
104
103
|
|
|
105
104
|
# Local variable mappings that are used when rendering the template for this resource.
|
|
106
105
|
# @return [Hash]
|
|
107
|
-
Contract
|
|
106
|
+
Contract Hash
|
|
108
107
|
def locals
|
|
109
108
|
metadata[:locals]
|
|
110
109
|
end
|
|
111
110
|
|
|
112
111
|
# Extension of the path (i.e. '.js')
|
|
113
112
|
# @return [String]
|
|
114
|
-
Contract
|
|
113
|
+
Contract String
|
|
115
114
|
def ext
|
|
116
115
|
File.extname(path)
|
|
117
116
|
end
|
|
@@ -141,7 +140,7 @@ module Middleman
|
|
|
141
140
|
# A path without the directory index - so foo/index.html becomes
|
|
142
141
|
# just foo. Best for linking.
|
|
143
142
|
# @return [String]
|
|
144
|
-
Contract
|
|
143
|
+
Contract String
|
|
145
144
|
def url
|
|
146
145
|
url_path = destination_path
|
|
147
146
|
if @app.config[:strip_index_file]
|
|
@@ -154,7 +153,7 @@ module Middleman
|
|
|
154
153
|
# Whether the source file is binary.
|
|
155
154
|
#
|
|
156
155
|
# @return [Boolean]
|
|
157
|
-
Contract
|
|
156
|
+
Contract Bool
|
|
158
157
|
def binary?
|
|
159
158
|
!source_file.nil? && ::Middleman::Util.binary?(source_file[:full_path].to_s)
|
|
160
159
|
end
|
|
@@ -162,14 +161,14 @@ module Middleman
|
|
|
162
161
|
# Ignore a resource directly, without going through the whole
|
|
163
162
|
# ignore filter stuff.
|
|
164
163
|
# @return [void]
|
|
165
|
-
Contract
|
|
164
|
+
Contract Any
|
|
166
165
|
def ignore!
|
|
167
166
|
@ignored = true
|
|
168
167
|
end
|
|
169
168
|
|
|
170
169
|
# Whether the Resource is ignored
|
|
171
170
|
# @return [Boolean]
|
|
172
|
-
Contract
|
|
171
|
+
Contract Bool
|
|
173
172
|
def ignored?
|
|
174
173
|
return true if @ignored
|
|
175
174
|
# Ignore based on the source path (without template extensions)
|
|
@@ -184,7 +183,7 @@ module Middleman
|
|
|
184
183
|
|
|
185
184
|
# The preferred MIME content type for this resource based on extension or metadata
|
|
186
185
|
# @return [String] MIME type for this resource
|
|
187
|
-
Contract
|
|
186
|
+
Contract Maybe[String]
|
|
188
187
|
def content_type
|
|
189
188
|
options[:content_type] || ::Rack::Mime.mime_type(ext, nil)
|
|
190
189
|
end
|
|
@@ -74,12 +74,13 @@ module Middleman
|
|
|
74
74
|
# @param [Symbol] name Name of the manipulator for debugging
|
|
75
75
|
# @param [#manipulate_resource_list] manipulator Resource list manipulator
|
|
76
76
|
# @param [Numeric] priority Sets the order of this resource list manipulator relative to the rest. By default this is 50, and manipulators run in the order they are registered, but if a priority is provided then this will run ahead of or behind other manipulators.
|
|
77
|
+
# @param [Symbol] custom_name The method name to execute.
|
|
77
78
|
# @return [void]
|
|
78
|
-
Contract Symbol, RespondTo['manipulate_resource_list'], Maybe[Num] => Any
|
|
79
|
-
def register_resource_list_manipulator(name, manipulator, priority=50)
|
|
79
|
+
Contract Symbol, RespondTo['manipulate_resource_list'], Maybe[Num], Maybe[Symbol] => Any
|
|
80
|
+
def register_resource_list_manipulator(name, manipulator, priority=50, custom_name=nil)
|
|
80
81
|
# The third argument used to be a boolean - handle those who still pass one
|
|
81
82
|
priority = 50 unless priority.is_a? Numeric
|
|
82
|
-
@resource_list_manipulators << [name, manipulator, priority]
|
|
83
|
+
@resource_list_manipulators << [name, manipulator, priority, custom_name]
|
|
83
84
|
# The index trick is used so that the sort is stable - manipulators with the same priority
|
|
84
85
|
# will always be ordered in the same order as they were registered.
|
|
85
86
|
n = 0
|
|
@@ -177,8 +178,8 @@ module Middleman
|
|
|
177
178
|
|
|
178
179
|
@app.logger.debug '== Rebuilding resource list'
|
|
179
180
|
|
|
180
|
-
@resources = @resource_list_manipulators.reduce([]) do |result, (_, manipulator, _)|
|
|
181
|
-
newres = manipulator.manipulate_resource_list
|
|
181
|
+
@resources = @resource_list_manipulators.reduce([]) do |result, (_, manipulator, _, custom_name)|
|
|
182
|
+
newres = manipulator.send(custom_name || :manipulate_resource_list, result)
|
|
182
183
|
|
|
183
184
|
# Reset lookup cache
|
|
184
185
|
reset_lookup_cache!
|
|
@@ -17,15 +17,15 @@ module Middleman
|
|
|
17
17
|
def_delegator :app, :logger
|
|
18
18
|
|
|
19
19
|
# The type this watcher is representing
|
|
20
|
-
Contract
|
|
20
|
+
Contract Symbol
|
|
21
21
|
attr_reader :type
|
|
22
22
|
|
|
23
23
|
# The directory that is being watched
|
|
24
|
-
Contract
|
|
24
|
+
Contract Pathname
|
|
25
25
|
attr_reader :directory
|
|
26
26
|
|
|
27
27
|
# Options for configuring the watcher
|
|
28
|
-
Contract
|
|
28
|
+
Contract Hash
|
|
29
29
|
attr_reader :options
|
|
30
30
|
|
|
31
31
|
# Construct a new SourceWatcher
|
|
@@ -47,6 +47,7 @@ module Middleman
|
|
|
47
47
|
|
|
48
48
|
@validator = options.fetch(:validator, proc { true })
|
|
49
49
|
@ignored = options.fetch(:ignored, proc { false })
|
|
50
|
+
@only = Array(options.fetch(:only, []))
|
|
50
51
|
|
|
51
52
|
@disable_watcher = app.build? || @parent.options.fetch(:disable_watcher, false)
|
|
52
53
|
@force_polling = @parent.options.fetch(:force_polling, false)
|
|
@@ -79,7 +80,7 @@ module Middleman
|
|
|
79
80
|
# Stop watching.
|
|
80
81
|
#
|
|
81
82
|
# @return [void]
|
|
82
|
-
Contract
|
|
83
|
+
Contract Any
|
|
83
84
|
def unwatch
|
|
84
85
|
stop_listener!
|
|
85
86
|
end
|
|
@@ -87,7 +88,7 @@ module Middleman
|
|
|
87
88
|
# All the known files in this watcher.
|
|
88
89
|
#
|
|
89
90
|
# @return [Array<Middleman::SourceFile>]
|
|
90
|
-
Contract
|
|
91
|
+
Contract ArrayOf[IsA['Middleman::SourceFile']]
|
|
91
92
|
def files
|
|
92
93
|
@files.values
|
|
93
94
|
end
|
|
@@ -123,21 +124,27 @@ module Middleman
|
|
|
123
124
|
# Start the `listen` gem Listener.
|
|
124
125
|
#
|
|
125
126
|
# @return [void]
|
|
126
|
-
Contract
|
|
127
|
+
Contract Any
|
|
127
128
|
def listen!
|
|
128
129
|
return if @disable_watcher || @listener || @waiting_for_existence
|
|
129
130
|
|
|
130
|
-
config = {
|
|
131
|
+
config = {
|
|
132
|
+
force_polling: @force_polling,
|
|
133
|
+
wait_for_delay: 0.5
|
|
134
|
+
}
|
|
135
|
+
|
|
131
136
|
config[:latency] = @latency if @latency
|
|
132
137
|
|
|
133
138
|
@listener = ::Listen.to(@directory.to_s, config, &method(:on_listener_change))
|
|
134
139
|
@listener.start
|
|
140
|
+
|
|
141
|
+
@listener.only(@only) unless @only.empty?
|
|
135
142
|
end
|
|
136
143
|
|
|
137
144
|
# Stop the listener.
|
|
138
145
|
#
|
|
139
146
|
# @return [void]
|
|
140
|
-
Contract
|
|
147
|
+
Contract Any
|
|
141
148
|
def stop_listener!
|
|
142
149
|
return unless @listener
|
|
143
150
|
|
|
@@ -148,7 +155,7 @@ module Middleman
|
|
|
148
155
|
# Manually trigger update events.
|
|
149
156
|
#
|
|
150
157
|
# @return [void]
|
|
151
|
-
Contract
|
|
158
|
+
Contract Any
|
|
152
159
|
def poll_once!
|
|
153
160
|
removed = @files.keys
|
|
154
161
|
|
|
@@ -247,10 +254,9 @@ module Middleman
|
|
|
247
254
|
@extensionless_files.delete(strip_extensions(f[:full_path]))
|
|
248
255
|
end
|
|
249
256
|
|
|
257
|
+
Contract Pathname => Pathname
|
|
250
258
|
def strip_extensions(p)
|
|
251
|
-
while ::Tilt[p.to_s] || p.extname
|
|
252
|
-
p = p.sub_ext('')
|
|
253
|
-
end
|
|
259
|
+
p = p.sub_ext('') while ::Tilt[p.to_s] || p.extname == '.html'
|
|
254
260
|
Pathname(p.to_s + '.*')
|
|
255
261
|
end
|
|
256
262
|
|
|
@@ -260,9 +266,13 @@ module Middleman
|
|
|
260
266
|
# @return [Boolean]
|
|
261
267
|
Contract IsA['Middleman::SourceFile'] => Bool
|
|
262
268
|
def valid?(file)
|
|
263
|
-
@validator.call(file) &&
|
|
264
|
-
|
|
269
|
+
return false unless @validator.call(file) && !globally_ignored?(file)
|
|
270
|
+
|
|
271
|
+
if @only.empty?
|
|
265
272
|
!@ignored.call(file)
|
|
273
|
+
else
|
|
274
|
+
@only.any? { |reg| reg.match(file[:relative_path].to_s) }
|
|
275
|
+
end
|
|
266
276
|
end
|
|
267
277
|
|
|
268
278
|
# Convert a path to a file resprentation.
|
|
@@ -273,8 +283,11 @@ module Middleman
|
|
|
273
283
|
def path_to_source_file(path)
|
|
274
284
|
types = Set.new([@type])
|
|
275
285
|
|
|
276
|
-
|
|
277
|
-
|
|
286
|
+
relative_path = path.relative_path_from(@directory)
|
|
287
|
+
destination_dir = @options.fetch(:destination_dir, false)
|
|
288
|
+
relative_path = File.join(destination_dir, relative_path) if destination_dir
|
|
289
|
+
|
|
290
|
+
::Middleman::SourceFile.new(Pathname(relative_path), path, @directory, types)
|
|
278
291
|
end
|
|
279
292
|
|
|
280
293
|
# Notify callbacks for a file given an array of callbacks
|
|
@@ -14,15 +14,17 @@ module Middleman
|
|
|
14
14
|
extend Forwardable
|
|
15
15
|
include Contracts
|
|
16
16
|
|
|
17
|
+
Matcher = Or[Regexp, RespondTo[:call]]
|
|
18
|
+
|
|
17
19
|
# A reference to the current app.
|
|
18
|
-
Contract
|
|
20
|
+
Contract IsA['Middleman::Application']
|
|
19
21
|
attr_reader :app
|
|
20
22
|
|
|
21
23
|
# Duck-typed definition of a valid source watcher
|
|
22
24
|
HANDLER = RespondTo[:on_change]
|
|
23
25
|
|
|
24
26
|
# Config
|
|
25
|
-
Contract
|
|
27
|
+
Contract Hash
|
|
26
28
|
attr_reader :options
|
|
27
29
|
|
|
28
30
|
# Reference to the global logger.
|
|
@@ -125,7 +127,7 @@ module Middleman
|
|
|
125
127
|
end
|
|
126
128
|
|
|
127
129
|
# A list of registered watchers
|
|
128
|
-
Contract
|
|
130
|
+
Contract ArrayOf[HANDLER]
|
|
129
131
|
def watchers
|
|
130
132
|
@sorted_watchers
|
|
131
133
|
end
|
|
@@ -155,7 +157,7 @@ module Middleman
|
|
|
155
157
|
# Get all files for this collection of watchers.
|
|
156
158
|
#
|
|
157
159
|
# @return [Array<Middleman::SourceFile>]
|
|
158
|
-
Contract
|
|
160
|
+
Contract ArrayOf[SourceFile]
|
|
159
161
|
def files
|
|
160
162
|
watchers.flat_map(&:files).uniq { |f| f[:relative_path] }
|
|
161
163
|
end
|
|
@@ -204,7 +206,7 @@ module Middleman
|
|
|
204
206
|
# Manually poll all watchers for new content.
|
|
205
207
|
#
|
|
206
208
|
# @return [void]
|
|
207
|
-
Contract
|
|
209
|
+
Contract Any
|
|
208
210
|
def find_new_files!
|
|
209
211
|
return unless @update_count != @last_update_count
|
|
210
212
|
|
|
@@ -215,7 +217,7 @@ module Middleman
|
|
|
215
217
|
# Start up all listeners.
|
|
216
218
|
#
|
|
217
219
|
# @return [void]
|
|
218
|
-
Contract
|
|
220
|
+
Contract Any
|
|
219
221
|
def start!
|
|
220
222
|
watchers.each(&:listen!)
|
|
221
223
|
@running = true
|
|
@@ -224,7 +226,7 @@ module Middleman
|
|
|
224
226
|
# Stop the watchers.
|
|
225
227
|
#
|
|
226
228
|
# @return [void]
|
|
227
|
-
Contract
|
|
229
|
+
Contract Any
|
|
228
230
|
def stop!
|
|
229
231
|
watchers.each(&:stop_listener!)
|
|
230
232
|
@running = false
|
|
@@ -246,28 +248,24 @@ module Middleman
|
|
|
246
248
|
# Backwards compatible change handler.
|
|
247
249
|
#
|
|
248
250
|
# @param [nil,Regexp] matcher A Regexp to match the change path against
|
|
249
|
-
|
|
251
|
+
Contract Maybe[Matcher] => Any
|
|
250
252
|
def changed(matcher=nil, &block)
|
|
251
253
|
on_change :source do |updated, _removed|
|
|
252
|
-
updated
|
|
253
|
-
matcher.nil? ? true : matches?(matcher, f)
|
|
254
|
-
|
|
255
|
-
block.call(f[:relative_path])
|
|
256
|
-
end
|
|
254
|
+
updated
|
|
255
|
+
.select { |f| matcher.nil? ? true : matches?(matcher, f) }
|
|
256
|
+
.each { |f| block.call(f[:relative_path]) }
|
|
257
257
|
end
|
|
258
258
|
end
|
|
259
259
|
|
|
260
260
|
# Backwards compatible delete handler.
|
|
261
261
|
#
|
|
262
262
|
# @param [nil,Regexp] matcher A Regexp to match the change path against
|
|
263
|
-
|
|
263
|
+
Contract Maybe[Matcher] => Any
|
|
264
264
|
def deleted(matcher=nil, &block)
|
|
265
265
|
on_change :source do |_updated, removed|
|
|
266
|
-
removed
|
|
267
|
-
matcher.nil? ? true : matches?(matcher, f)
|
|
268
|
-
|
|
269
|
-
block.call(f[:relative_path])
|
|
270
|
-
end
|
|
266
|
+
removed
|
|
267
|
+
.select { |f| matcher.nil? ? true : matches?(matcher, f) }
|
|
268
|
+
.each { |f| block.call(f[:relative_path]) }
|
|
271
269
|
end
|
|
272
270
|
end
|
|
273
271
|
|
|
@@ -287,7 +285,7 @@ module Middleman
|
|
|
287
285
|
# @param [Regexp, #call] validator The match validator.
|
|
288
286
|
# @param [Middleman::SourceFile] file The file to check.
|
|
289
287
|
# @return [Boolean]
|
|
290
|
-
Contract
|
|
288
|
+
Contract Matcher, SourceFile => Bool
|
|
291
289
|
def matches?(validator, file)
|
|
292
290
|
path = file[:relative_path]
|
|
293
291
|
if validator.is_a? Regexp
|
|
@@ -300,7 +298,7 @@ module Middleman
|
|
|
300
298
|
# Increment the internal counter for changes.
|
|
301
299
|
#
|
|
302
300
|
# @return [void]
|
|
303
|
-
Contract
|
|
301
|
+
Contract Any
|
|
304
302
|
def bump_count
|
|
305
303
|
@update_count += 1
|
|
306
304
|
end
|
|
@@ -69,7 +69,7 @@ end
|
|
|
69
69
|
|
|
70
70
|
# Provide this Aruba overload in case we're matching something with quotes in it
|
|
71
71
|
Then /^the file "([^"]*)" should contain '([^']*)'$/ do |file, partial_content|
|
|
72
|
-
check_file_content(file, partial_content, true)
|
|
72
|
+
check_file_content(file, Regexp.new(Regexp.escape(partial_content)), true)
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
And /the file "(.*)" should be gzipped/ do |file|
|
|
@@ -70,7 +70,7 @@ end
|
|
|
70
70
|
|
|
71
71
|
When /^I go to "([^\"]*)"$/ do |url|
|
|
72
72
|
in_current_dir do
|
|
73
|
-
@last_response = @browser.get(URI.
|
|
73
|
+
@last_response = @browser.get(URI.encode(url))
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
|
|
@@ -78,8 +78,8 @@ Then /^going to "([^\"]*)" should not raise an exception$/ do |url|
|
|
|
78
78
|
in_current_dir do
|
|
79
79
|
last_response = nil
|
|
80
80
|
expect {
|
|
81
|
-
last_response = @browser.get(URI.
|
|
82
|
-
}.to_not
|
|
81
|
+
last_response = @browser.get(URI.encode(url))
|
|
82
|
+
}.to_not raise_exception
|
|
83
83
|
@last_response = last_response
|
|
84
84
|
end
|
|
85
85
|
end
|
|
@@ -100,7 +100,7 @@ module Middleman
|
|
|
100
100
|
def render(_, name, options={}, &block)
|
|
101
101
|
name = name.to_s
|
|
102
102
|
|
|
103
|
-
partial_file = locate_partial(name)
|
|
103
|
+
partial_file = locate_partial(name, false) || locate_partial(name, true)
|
|
104
104
|
|
|
105
105
|
return '' unless partial_file
|
|
106
106
|
raise ::Middleman::TemplateRenderer::TemplateNotFound, "Could not locate partial: #{name}" unless partial_file
|
|
@@ -123,8 +123,8 @@ module Middleman
|
|
|
123
123
|
# @api private
|
|
124
124
|
# @param [String] partial_path
|
|
125
125
|
# @return [String]
|
|
126
|
-
Contract String => Maybe[IsA['Middleman::SourceFile']]
|
|
127
|
-
def locate_partial(partial_path)
|
|
126
|
+
Contract String, Maybe[Bool] => Maybe[IsA['Middleman::SourceFile']]
|
|
127
|
+
def locate_partial(partial_path, try_static=true)
|
|
128
128
|
return unless resource = sitemap.find_resource_by_destination_path(current_path)
|
|
129
129
|
|
|
130
130
|
# Look for partials relative to the current path
|
|
@@ -140,9 +140,9 @@ module Middleman
|
|
|
140
140
|
[
|
|
141
141
|
[relative_dir.to_s, { preferred_engine: resource.source_file[:relative_path].extname[1..-1].to_sym }],
|
|
142
142
|
[non_root],
|
|
143
|
-
[non_root, { try_static:
|
|
144
|
-
[relative_dir_no_underscore.to_s, { try_static:
|
|
145
|
-
[non_root_no_underscore, { try_static:
|
|
143
|
+
[non_root, { try_static: try_static }],
|
|
144
|
+
[relative_dir_no_underscore.to_s, { try_static: try_static }],
|
|
145
|
+
[non_root_no_underscore, { try_static: try_static }]
|
|
146
146
|
].each do |args|
|
|
147
147
|
partial_file = ::Middleman::TemplateRenderer.resolve_template(@app, *args)
|
|
148
148
|
break if partial_file
|
|
@@ -161,11 +161,12 @@ module Middleman
|
|
|
161
161
|
# @param [Hash] opts Template options.
|
|
162
162
|
# @param [Proc] block A block will be evaluated to return internal contents.
|
|
163
163
|
# @return [String] The resulting content string.
|
|
164
|
-
Contract IsA['Middleman::SourceFile'], Hash, Hash, Proc => String
|
|
164
|
+
Contract IsA['Middleman::SourceFile'], Hash, Hash, Maybe[Proc] => String
|
|
165
165
|
def render_file(file, locs, opts, &block)
|
|
166
166
|
_render_with_all_renderers(file[:relative_path].to_s, locs, self, opts, &block)
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
Contract String, Hash, Any, Hash, Maybe[Proc] => String
|
|
169
170
|
def _render_with_all_renderers(path, locs, context, opts, &block)
|
|
170
171
|
# Keep rendering template until we've used up all extensions. This
|
|
171
172
|
# handles cases like `style.css.sass.erb`
|
|
@@ -58,8 +58,8 @@ module Middleman
|
|
|
58
58
|
# Sandboxed class for template eval
|
|
59
59
|
context = @app.template_context_class.new(@app, locals, options)
|
|
60
60
|
|
|
61
|
-
#
|
|
62
|
-
|
|
61
|
+
# Add extension helpers to context.
|
|
62
|
+
@app.extensions.add_exposed_to_context(context)
|
|
63
63
|
|
|
64
64
|
content = _render_with_all_renderers(path, locs, context, opts, &block)
|
|
65
65
|
|