middleman-core 4.0.0.alpha.6 → 4.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'active_support/core_ext/class/attribute'
|
2
3
|
require 'middleman-core/configuration'
|
3
4
|
require 'middleman-core/contracts'
|
@@ -81,6 +82,30 @@ module Middleman
|
|
81
82
|
# @return [Array<Module>] a list of all the helper modules this extension provides. Set these using {#helpers}.
|
82
83
|
class_attribute :defined_helpers, instance_reader: false, instance_writer: false
|
83
84
|
|
85
|
+
# @!attribute exposed_to_application
|
86
|
+
# @!scope class
|
87
|
+
# @api private
|
88
|
+
# @return [Hash<Symbol, Symbol>] a list of all the methods modules this extension exposes to app. Set these using {#expose_to_application}.
|
89
|
+
class_attribute :exposed_to_application, instance_reader: false, instance_writer: false
|
90
|
+
|
91
|
+
# @!attribute exposed_to_config
|
92
|
+
# @!scope class
|
93
|
+
# @api private
|
94
|
+
# @return [Hash<Symbol, Symbol>] a list of all the methods modules this extension exposes to config. Set these using {#expose_to_config}.
|
95
|
+
class_attribute :exposed_to_config, instance_reader: false, instance_writer: false
|
96
|
+
|
97
|
+
# @!attribute exposed_to_template
|
98
|
+
# @!scope class
|
99
|
+
# @api private
|
100
|
+
# @return [Hash<Symbol, Symbol>] a list of all the methods modules this extension exposes to templates. Set these using {#expose_to_template}.
|
101
|
+
class_attribute :exposed_to_template, instance_reader: false, instance_writer: false
|
102
|
+
|
103
|
+
# @!attribute exposed_to_template
|
104
|
+
# @!scope class
|
105
|
+
# @api private
|
106
|
+
# @return [Array<Any>] a list of method generators.
|
107
|
+
class_attribute :resources_generators, instance_reader: false, instance_writer: false
|
108
|
+
|
84
109
|
# @!attribute ext_name
|
85
110
|
# @!scope class
|
86
111
|
# @return [Symbol] the name this extension is registered under. This is the symbol used to activate the extension.
|
@@ -110,6 +135,19 @@ module Middleman
|
|
110
135
|
config.define_setting(key, default, description, options)
|
111
136
|
end
|
112
137
|
|
138
|
+
# Short-hand for simple Sitemap manipulation
|
139
|
+
# @example A generator which returns an array of resources
|
140
|
+
# resources :make_resources
|
141
|
+
# @example A generator which maps a path to a method
|
142
|
+
# resources make_resource: :make_it
|
143
|
+
# @example A generator which maps a path to a string
|
144
|
+
# resources make_resource: 'Hello'
|
145
|
+
# @param [Array] generators The generator definitions
|
146
|
+
def resources(*generators)
|
147
|
+
self.resources_generators ||= []
|
148
|
+
self.resources_generators += generators
|
149
|
+
end
|
150
|
+
|
113
151
|
# Declare helpers to be added the global Middleman application.
|
114
152
|
# This accepts either a list of modules to add on behalf
|
115
153
|
# of this extension, or a block whose contents will all
|
@@ -137,6 +175,68 @@ module Middleman
|
|
137
175
|
self.defined_helpers += modules
|
138
176
|
end
|
139
177
|
|
178
|
+
# Takes a method within this extension and exposes it globally
|
179
|
+
# on the main `app` instance. Used for very low-level extensions
|
180
|
+
# which many other extensions depend upon. Such as Data and
|
181
|
+
# File watching.
|
182
|
+
# @example with Hash:
|
183
|
+
# expose_to_application global_name: :local_name
|
184
|
+
# @example with Array:
|
185
|
+
# expose_to_application :method1, :method2
|
186
|
+
# @param [Array<Sumbol>, Hash<Symbol, Symbol>] symbols An optional list of symbols representing instance methods to exposed.
|
187
|
+
# @return [void]
|
188
|
+
def expose_to_application(*symbols)
|
189
|
+
self.exposed_to_application ||= {}
|
190
|
+
|
191
|
+
if symbols.first && symbols.first.is_a?(Hash)
|
192
|
+
self.exposed_to_application.merge!(symbols.first)
|
193
|
+
elsif symbols.is_a? Array
|
194
|
+
symbols.each do |sym|
|
195
|
+
self.exposed_to_application[sym] = sym
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Takes a method within this extension and exposes it inside the scope
|
201
|
+
# of the config.rb sandbox.
|
202
|
+
# @example with Hash:
|
203
|
+
# expose_to_config global_name: :local_name
|
204
|
+
# @example with Array:
|
205
|
+
# expose_to_config :method1, :method2
|
206
|
+
# @param [Array<Sumbol>, Hash<Symbol, Symbol>] symbols An optional list of symbols representing instance methods to exposed.
|
207
|
+
# @return [void]
|
208
|
+
def expose_to_config(*symbols)
|
209
|
+
self.exposed_to_config ||= {}
|
210
|
+
|
211
|
+
if symbols.first && symbols.first.is_a?(Hash)
|
212
|
+
self.exposed_to_config.merge!(symbols.first)
|
213
|
+
elsif symbols.is_a? Array
|
214
|
+
symbols.each do |sym|
|
215
|
+
self.exposed_to_config[sym] = sym
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Takes a method within this extension and exposes it inside the scope
|
221
|
+
# of the templating engine. Like `helpers`, but scoped.
|
222
|
+
# @example with Hash:
|
223
|
+
# expose_to_template global_name: :local_name
|
224
|
+
# @example with Array:
|
225
|
+
# expose_to_template :method1, :method2
|
226
|
+
# @param [Array<Sumbol>, Hash<Symbol, Symbol>] symbols An optional list of symbols representing instance methods to exposed.
|
227
|
+
# @return [void]
|
228
|
+
def expose_to_template(*symbols)
|
229
|
+
self.exposed_to_template ||= {}
|
230
|
+
|
231
|
+
if symbols.first && symbols.first.is_a?(Hash)
|
232
|
+
self.exposed_to_template.merge!(symbols.first)
|
233
|
+
elsif symbols.is_a? Array
|
234
|
+
symbols.each do |sym|
|
235
|
+
self.exposed_to_template[sym] = sym
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
140
240
|
# Reset all {Extension.after_extension_activated} callbacks.
|
141
241
|
# @api private
|
142
242
|
# @return [void]
|
@@ -190,6 +290,7 @@ module Middleman
|
|
190
290
|
@_helpers = []
|
191
291
|
@app = app
|
192
292
|
|
293
|
+
expose_methods
|
193
294
|
setup_options(options_hash, &block)
|
194
295
|
|
195
296
|
# Bind app hooks to local methods
|
@@ -197,6 +298,7 @@ module Middleman
|
|
197
298
|
bind_after_configuration
|
198
299
|
bind_before_build
|
199
300
|
bind_after_build
|
301
|
+
bind_ready
|
200
302
|
end
|
201
303
|
|
202
304
|
# @!method before_configuration
|
@@ -216,6 +318,10 @@ module Middleman
|
|
216
318
|
# Respond to the `after_build` event.
|
217
319
|
# If an `after_build` method is implemented, that method will be run after the builder runs.
|
218
320
|
|
321
|
+
# @!method ready
|
322
|
+
# Respond to the `ready` event.
|
323
|
+
# If an `ready` method is implemented, that method will be run after the app has finished booting up.
|
324
|
+
|
219
325
|
# @!method manipulate_resource_list(resources)
|
220
326
|
# Manipulate the resource list by transforming or adding {Sitemap::Resource}s.
|
221
327
|
# Sitemap manipulation is a powerful way of interacting with a project, since it can modify each {Sitemap::Resource} or generate new {Sitemap::Resources}. This method is used in a pipeline where each sitemap manipulator is run in turn, with each one being fed the output of the previous manipulator. See the source of built-in Middleman extensions like {Middleman::Extensions::DirectoryIndexes} and {Middleman::Extensions::AssetHash} for examples of how to use this.
|
@@ -226,8 +332,28 @@ module Middleman
|
|
226
332
|
# @param [Array<Sitemap::Resource>] resources A list of all the resources known to the sitemap.
|
227
333
|
# @return [Array<Sitemap::Resource>] The transformed list of resources.
|
228
334
|
|
335
|
+
def add_exposed_to_context(context)
|
336
|
+
(self.class.exposed_to_template || {}).each do |k, v|
|
337
|
+
context.define_singleton_method(k, &method(v))
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
229
341
|
private
|
230
342
|
|
343
|
+
def expose_methods
|
344
|
+
(self.class.exposed_to_application || {}).each do |k, v|
|
345
|
+
app.define_singleton_method(k, &method(v))
|
346
|
+
end
|
347
|
+
|
348
|
+
(self.class.exposed_to_config || {}).each do |k, v|
|
349
|
+
app.config_context.define_singleton_method(k, &method(v))
|
350
|
+
end
|
351
|
+
|
352
|
+
(self.class.defined_helpers || []).each do |m|
|
353
|
+
app.template_context_class.send(:include, m)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
231
357
|
# @yield An optional block that can be used to customize options before the extension is activated.
|
232
358
|
# @yieldparam Middleman::Configuration::ConfigurationManager] options Extension options
|
233
359
|
def setup_options(options_hash)
|
@@ -260,6 +386,53 @@ module Middleman
|
|
260
386
|
if ext.respond_to?(:manipulate_resource_list)
|
261
387
|
ext.app.sitemap.register_resource_list_manipulator(ext.class.ext_name, ext, ext.class.resource_list_manipulator_priority)
|
262
388
|
end
|
389
|
+
|
390
|
+
if ext.class.resources_generators && !ext.class.resources_generators.empty?
|
391
|
+
ext.app.sitemap.register_resource_list_manipulator(
|
392
|
+
:"#{ext.class.ext_name}_generator",
|
393
|
+
ext,
|
394
|
+
ext.class.resource_list_manipulator_priority,
|
395
|
+
:generate_resources
|
396
|
+
)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def generate_resources(resources)
|
402
|
+
generator_defs = self.class.resources_generators.reduce({}) do |sum, g|
|
403
|
+
resource_definitions = if g.is_a? Hash
|
404
|
+
g
|
405
|
+
elsif g.is_a? Symbol
|
406
|
+
definition = method(g)
|
407
|
+
|
408
|
+
if definition.arity == 0
|
409
|
+
send(g)
|
410
|
+
else
|
411
|
+
send(g, resources)
|
412
|
+
end
|
413
|
+
else
|
414
|
+
{}
|
415
|
+
end
|
416
|
+
|
417
|
+
sum.merge(resource_definitions)
|
418
|
+
end
|
419
|
+
|
420
|
+
resources + generator_defs.map do |path, g|
|
421
|
+
if g.is_a? Symbol
|
422
|
+
definition = method(g)
|
423
|
+
|
424
|
+
g = if definition.arity == 0
|
425
|
+
send(g)
|
426
|
+
else
|
427
|
+
send(g, resources)
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
::Middleman::Sitemap::StringResource.new(
|
432
|
+
app.sitemap,
|
433
|
+
path,
|
434
|
+
g
|
435
|
+
)
|
263
436
|
end
|
264
437
|
end
|
265
438
|
|
@@ -283,10 +456,16 @@ module Middleman
|
|
283
456
|
@app.after_build do |builder|
|
284
457
|
if ext.method(:after_build).arity == 1
|
285
458
|
ext.after_build(builder)
|
459
|
+
elsif ext.method(:after_build).arity == 2
|
460
|
+
ext.after_build(builder, builder.thor)
|
286
461
|
else
|
287
462
|
ext.after_build
|
288
463
|
end
|
289
464
|
end
|
290
465
|
end
|
466
|
+
|
467
|
+
def bind_ready
|
468
|
+
@app.ready(&method(:ready)) if respond_to?(:ready)
|
469
|
+
end
|
291
470
|
end
|
292
471
|
end
|
@@ -55,7 +55,7 @@ module Middleman
|
|
55
55
|
|
56
56
|
def activate_all
|
57
57
|
logger.debug 'Loaded extensions:'
|
58
|
-
instances = @activated.each_with_object([]) do |(ext_name, ext), sum|
|
58
|
+
@instances = @activated.each_with_object([]) do |(ext_name, ext), sum|
|
59
59
|
if ext.is_a?(Hash)
|
60
60
|
ext.each do |instance_key, instance|
|
61
61
|
logger.debug "== Extension: #{ext_name} #{instance_key}"
|
@@ -67,14 +67,15 @@ module Middleman
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
instances.each do |ext|
|
71
|
-
# Forward Extension helpers to TemplateContext
|
72
|
-
Array(ext.class.defined_helpers).each do |m|
|
73
|
-
@app.template_context_class.send(:include, m)
|
74
|
-
end
|
75
|
-
|
70
|
+
@instances.each do |ext|
|
76
71
|
::Middleman::Extension.activated_extension(ext)
|
77
72
|
end
|
78
73
|
end
|
74
|
+
|
75
|
+
def add_exposed_to_context(context)
|
76
|
+
@instances.each do |ext|
|
77
|
+
ext.add_exposed_to_context(context)
|
78
|
+
end
|
79
|
+
end
|
79
80
|
end
|
80
81
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
require 'addressable/uri'
|
1
2
|
require 'middleman-core/util'
|
2
3
|
|
3
4
|
class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
4
|
-
option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .eot .ttf .svg), 'List of extensions that get asset hashes appended to them.'
|
5
|
+
option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .woff2 .eot .ttf .svg), 'List of extensions that get asset hashes appended to them.'
|
5
6
|
option :ignore, [], 'Regexes of filenames to skip adding asset hashes to'
|
6
7
|
|
7
8
|
def initialize(app, options_hash={}, &block)
|
@@ -9,7 +10,6 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
9
10
|
|
10
11
|
require 'digest/sha1'
|
11
12
|
require 'rack/mock'
|
12
|
-
require 'uri'
|
13
13
|
require 'middleman-core/middleware/inline_url_rewriter'
|
14
14
|
end
|
15
15
|
|
@@ -28,7 +28,8 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
28
28
|
|
29
29
|
Contract String, Or[String, Pathname], Any => Maybe[String]
|
30
30
|
def rewrite_url(asset_path, dirpath, _request_path)
|
31
|
-
|
31
|
+
uri = ::Addressable::URI.parse(asset_path)
|
32
|
+
relative_path = uri.path[0..0] != '/'
|
32
33
|
|
33
34
|
full_asset_path = if relative_path
|
34
35
|
dirpath.join(asset_path).to_s
|
@@ -36,10 +37,11 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
36
37
|
asset_path
|
37
38
|
end
|
38
39
|
|
39
|
-
return unless asset_page = app.sitemap.find_resource_by_path(full_asset_path)
|
40
|
+
return unless asset_page = app.sitemap.find_resource_by_destination_path(full_asset_path) || app.sitemap.find_resource_by_path(full_asset_path)
|
40
41
|
|
41
42
|
replacement_path = "/#{asset_page.destination_path}"
|
42
43
|
replacement_path = Pathname.new(replacement_path).relative_path_from(dirpath).to_s if relative_path
|
44
|
+
|
43
45
|
replacement_path
|
44
46
|
end
|
45
47
|
|
@@ -56,7 +58,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
56
58
|
# This is so by the time we get around to the text files (which may reference
|
57
59
|
# images and fonts) the static assets' hashes are already calculated.
|
58
60
|
resources.sort_by do |a|
|
59
|
-
if %w(.svg).include? a.ext
|
61
|
+
if %w(.svg .svgz).include? a.ext
|
60
62
|
0
|
61
63
|
elsif %w(.js .css).include? a.ext
|
62
64
|
1
|
@@ -73,9 +75,10 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
73
75
|
return if resource.ignored?
|
74
76
|
|
75
77
|
# Render through the Rack interface so middleware and mounted apps get a shot
|
76
|
-
response = @rack_client.get(
|
77
|
-
|
78
|
-
|
78
|
+
response = @rack_client.get(
|
79
|
+
URI.escape(resource.destination_path),
|
80
|
+
'bypass_inline_url_rewriter_asset_hash' => 'true'
|
81
|
+
)
|
79
82
|
|
80
83
|
raise "#{resource.path} should be in the sitemap!" unless response.status == 200
|
81
84
|
|
@@ -87,6 +90,8 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|
87
90
|
|
88
91
|
Contract IsA['Middleman::Sitemap::Resource'] => Bool
|
89
92
|
def ignored_resource?(resource)
|
90
|
-
@ignore.any?
|
93
|
+
@ignore.any? do |ignore|
|
94
|
+
Middleman::Util.path_match(ignore, resource.destination_path)
|
95
|
+
end
|
91
96
|
end
|
92
97
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'addressable/uri'
|
1
2
|
require 'middleman-core/middleware/inline_url_rewriter'
|
2
3
|
|
3
4
|
class Middleman::Extensions::AssetHost < ::Middleman::Extension
|
@@ -18,7 +19,8 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
|
|
18
19
|
|
19
20
|
Contract String, Or[String, Pathname], Any => String
|
20
21
|
def rewrite_url(asset_path, dirpath, _request_path)
|
21
|
-
|
22
|
+
uri = ::Addressable::URI.parse(asset_path)
|
23
|
+
relative_path = uri.path[0..0] != '/'
|
22
24
|
|
23
25
|
full_asset_path = if relative_path
|
24
26
|
dirpath.join(asset_path).to_s
|
@@ -12,6 +12,7 @@
|
|
12
12
|
class Middleman::Extensions::Gzip < ::Middleman::Extension
|
13
13
|
option :exts, %w(.js .css .html .htm), 'File extensions to Gzip when building.'
|
14
14
|
option :ignore, [], 'Patterns to avoid gzipping'
|
15
|
+
option :overwrite, false, 'Overwrite original files instead of adding .gz extension.'
|
15
16
|
|
16
17
|
class NumberHelpers
|
17
18
|
include ::Padrino::Helpers::NumberHelpers
|
@@ -73,11 +74,11 @@ class Middleman::Extensions::Gzip < ::Middleman::Extension
|
|
73
74
|
Contract String => [Maybe[String], Maybe[Num], Maybe[Num]]
|
74
75
|
def gzip_file(path)
|
75
76
|
input_file = File.open(path, 'rb').read
|
76
|
-
output_filename = path + '.gz'
|
77
|
+
output_filename = options.overwrite ? path : path + '.gz'
|
77
78
|
input_file_time = File.mtime(path)
|
78
79
|
|
79
80
|
# Check if the right file's already there
|
80
|
-
if File.exist?(output_filename) && File.mtime(output_filename) == input_file_time
|
81
|
+
if !options.overwrite && File.exist?(output_filename) && File.mtime(output_filename) == input_file_time
|
81
82
|
return [nil, nil, nil]
|
82
83
|
end
|
83
84
|
|
@@ -152,8 +152,8 @@ class Middleman::Extensions::Lorem < ::Middleman::Extension
|
|
152
152
|
color = options[:color]
|
153
153
|
|
154
154
|
if options[:random_color]
|
155
|
-
background_color = hex.
|
156
|
-
color = hex.
|
155
|
+
background_color = hex.sample(6).join
|
156
|
+
color = hex.sample(6).join
|
157
157
|
end
|
158
158
|
|
159
159
|
src << "/#{background_color.sub(/^#/, '')}" if background_color
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
|
1
3
|
# Relative Assets extension
|
2
4
|
class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
3
|
-
option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif .ttf .otf .woff), 'List of extensions that get cache busters strings appended to them.'
|
5
|
+
option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif .ttf .otf .woff .woff2), 'List of extensions that get cache busters strings appended to them.'
|
4
6
|
option :sources, %w(.htm .html .css), 'List of extensions that are searched for relative assets.'
|
5
7
|
option :ignore, [], 'Regexes of filenames to skip adding query strings to'
|
6
8
|
|
@@ -22,7 +24,11 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
|
22
24
|
|
23
25
|
Contract String, Or[String, Pathname], Any => Maybe[String]
|
24
26
|
def rewrite_url(asset_path, dirpath, request_path)
|
25
|
-
|
27
|
+
uri = ::Addressable::URI.parse(asset_path)
|
28
|
+
|
29
|
+
return if uri.path[0..0] != '/'
|
30
|
+
|
31
|
+
relative_path = uri.host.nil?
|
26
32
|
|
27
33
|
full_asset_path = if relative_path
|
28
34
|
dirpath.join(asset_path).to_s
|
@@ -30,9 +36,9 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
|
30
36
|
asset_path
|
31
37
|
end
|
32
38
|
|
33
|
-
return unless !full_asset_path.include?('//') && !asset_path.start_with?('data:')
|
34
|
-
|
35
39
|
current_dir = Pathname(request_path).dirname
|
36
|
-
Pathname(full_asset_path).relative_path_from(current_dir).to_s
|
40
|
+
result = Pathname(full_asset_path).relative_path_from(current_dir).to_s
|
41
|
+
|
42
|
+
result
|
37
43
|
end
|
38
44
|
end
|
@@ -28,7 +28,7 @@ module Middleman
|
|
28
28
|
# @param [Hash] opts
|
29
29
|
# @param [Class] context
|
30
30
|
# @return [String]
|
31
|
-
Contract Hash, Hash, Any, Proc => String
|
31
|
+
Contract Hash, Hash, Any, Maybe[Proc] => String
|
32
32
|
def render(locs={}, opts={}, context, &block)
|
33
33
|
path = @path.dup
|
34
34
|
|
@@ -102,7 +102,7 @@ module Middleman
|
|
102
102
|
# Get the template data from a path
|
103
103
|
# @param [String] path
|
104
104
|
# @return [String]
|
105
|
-
Contract
|
105
|
+
Contract String
|
106
106
|
def template_data_for_file
|
107
107
|
if @app.extensions[:front_matter]
|
108
108
|
@app.extensions[:front_matter].template_data_for_file(@path) || ''
|
@@ -39,7 +39,7 @@ module Middleman
|
|
39
39
|
def call(message, *args)
|
40
40
|
return if @instrumenting.is_a?(String) && @instrumenting != 'instrument' && !message.include?(@instrumenting)
|
41
41
|
|
42
|
-
evt = ActiveSupport::Notifications::Event.new(message, *args)
|
42
|
+
evt = ::ActiveSupport::Notifications::Event.new(message, *args)
|
43
43
|
info "== Instrument (#{evt.name.sub(/.middleman$/, '')}): #{evt.duration}ms\n#{args.last}"
|
44
44
|
end
|
45
45
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'middleman-core/util'
|
2
|
-
require 'middleman-core/contracts'
|
3
1
|
require 'rack'
|
4
2
|
require 'rack/response'
|
3
|
+
require 'addressable/uri'
|
4
|
+
require 'middleman-core/util'
|
5
|
+
require 'middleman-core/contracts'
|
5
6
|
|
6
7
|
module Middleman
|
7
8
|
module Middleware
|
@@ -51,10 +52,13 @@ module Middleman
|
|
51
52
|
|
52
53
|
if path =~ /(^\/$)|(#{@source_exts_regex_text}$)/
|
53
54
|
if body = ::Middleman::Util.extract_response_text(response)
|
55
|
+
|
54
56
|
dirpath = Pathname.new(File.dirname(path))
|
55
57
|
|
56
58
|
rewritten = ::Middleman::Util.rewrite_paths(body, path, @exts) do |asset_path|
|
57
|
-
|
59
|
+
uri = ::Addressable::URI.parse(asset_path)
|
60
|
+
|
61
|
+
relative_path = uri.host.nil?
|
58
62
|
|
59
63
|
full_asset_path = if relative_path
|
60
64
|
dirpath.join(asset_path).to_s
|
@@ -76,7 +80,7 @@ module Middleman
|
|
76
80
|
[status, headers, response]
|
77
81
|
end
|
78
82
|
|
79
|
-
Contract IGNORE_DESCRIPTOR => Bool
|
83
|
+
Contract IGNORE_DESCRIPTOR, String => Bool
|
80
84
|
def should_ignore?(validator, value)
|
81
85
|
if validator.is_a? Regexp
|
82
86
|
# Treat as Regexp
|
@@ -89,6 +93,7 @@ module Middleman
|
|
89
93
|
File.fnmatch(value, validator)
|
90
94
|
else
|
91
95
|
# If some unknown thing, don't ignore
|
96
|
+
false
|
92
97
|
end
|
93
98
|
end
|
94
99
|
end
|
@@ -6,8 +6,6 @@ require 'middleman-core/rack'
|
|
6
6
|
# rubocop:disable GlobalVars
|
7
7
|
module Middleman
|
8
8
|
module PreviewServer
|
9
|
-
DEFAULT_PORT = 4567
|
10
|
-
|
11
9
|
class << self
|
12
10
|
extend Forwardable
|
13
11
|
|
@@ -17,9 +15,7 @@ module Middleman
|
|
17
15
|
# Start an instance of Middleman::Application
|
18
16
|
# @return [void]
|
19
17
|
def start(opts={})
|
20
|
-
@options = opts
|
21
|
-
@host = @options[:host] || '0.0.0.0'
|
22
|
-
@port = @options[:port] || DEFAULT_PORT
|
18
|
+
@options = opts
|
23
19
|
|
24
20
|
mount_instance(new_app)
|
25
21
|
logger.info "== The Middleman is standing watch at #{uri}"
|
@@ -75,6 +71,10 @@ module Middleman
|
|
75
71
|
end
|
76
72
|
|
77
73
|
unmount_instance
|
74
|
+
|
75
|
+
@webrick.shutdown
|
76
|
+
@webrick = nil
|
77
|
+
|
78
78
|
mount_instance(app)
|
79
79
|
|
80
80
|
logger.info '== The Middleman has reloaded'
|
@@ -90,7 +90,7 @@ module Middleman
|
|
90
90
|
private
|
91
91
|
|
92
92
|
def new_app
|
93
|
-
opts = @options
|
93
|
+
opts = @options.dup
|
94
94
|
|
95
95
|
::Middleman::Logger.singleton(
|
96
96
|
opts[:debug] ? 0 : 1,
|
@@ -103,6 +103,9 @@ module Middleman
|
|
103
103
|
config[:watcher_force_polling] = opts[:force_polling]
|
104
104
|
config[:watcher_latency] = opts[:latency]
|
105
105
|
|
106
|
+
config[:host] = opts[:host] if opts[:host]
|
107
|
+
config[:port] = opts[:port] if opts[:port]
|
108
|
+
|
106
109
|
ready do
|
107
110
|
match_against = [
|
108
111
|
%r{^config\.rb$},
|
@@ -114,12 +117,13 @@ module Middleman
|
|
114
117
|
# config.rb
|
115
118
|
files.watch :reload,
|
116
119
|
path: root,
|
117
|
-
|
118
|
-
match_against.none? { |m| file[:relative_path].to_s.match(m) }
|
119
|
-
}
|
120
|
+
only: match_against
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
124
|
+
@host = app.config[:host]
|
125
|
+
@port = app.config[:port]
|
126
|
+
|
123
127
|
app.files.on_change :reload do
|
124
128
|
$mm_reload = true
|
125
129
|
@webrick.stop
|
data/lib/middleman-core/rack.rb
CHANGED
@@ -82,6 +82,7 @@ module Middleman
|
|
82
82
|
request_path.force_encoding('UTF-8')
|
83
83
|
end
|
84
84
|
request_path = ::Middleman::Util.full_path(request_path, @middleman)
|
85
|
+
full_request_path = File.join(env['SCRIPT_NAME'], request_path) # Path including rack mount
|
85
86
|
|
86
87
|
# Run before callbacks
|
87
88
|
@middleman.run_hook :before
|
@@ -90,7 +91,7 @@ module Middleman
|
|
90
91
|
resource = @middleman.sitemap.find_resource_by_destination_path(request_path.gsub(' ', '%20'))
|
91
92
|
|
92
93
|
# Return 404 if not in sitemap
|
93
|
-
return not_found(res,
|
94
|
+
return not_found(res, full_request_path) unless resource && !resource.ignored?
|
94
95
|
|
95
96
|
# If this path is a binary file, send it immediately
|
96
97
|
return send_file(resource, env) if resource.binary?
|
@@ -48,6 +48,12 @@ module Middleman
|
|
48
48
|
# Add haml helpers to context
|
49
49
|
::Middleman::TemplateContext.send :include, ::Haml::Helpers
|
50
50
|
end
|
51
|
+
|
52
|
+
def add_exposed_to_context(context)
|
53
|
+
super
|
54
|
+
|
55
|
+
context.init_haml_helpers if context.respond_to?(:init_haml_helpers)
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
@@ -6,7 +6,7 @@ module Middleman
|
|
6
6
|
class KramdownTemplate < ::Tilt::KramdownTemplate
|
7
7
|
def evaluate(scope, *)
|
8
8
|
@output ||= begin
|
9
|
-
MiddlemanKramdownHTML.scope = ::Middleman::Renderers::Haml.last_haml_scope
|
9
|
+
MiddlemanKramdownHTML.scope = (defined?(::Middleman::Renderers::Haml) && ::Middleman::Renderers::Haml.last_haml_scope) ? ::Middleman::Renderers::Haml.last_haml_scope : scope
|
10
10
|
|
11
11
|
output, warnings = MiddlemanKramdownHTML.convert(@engine.root, @engine.options)
|
12
12
|
@engine.warnings.concat(warnings)
|
@@ -105,7 +105,7 @@ module Middleman
|
|
105
105
|
filename: eval_file,
|
106
106
|
line: line,
|
107
107
|
syntax: syntax,
|
108
|
-
custom: {
|
108
|
+
custom: (options[:custom] || {}).merge(middleman_context: ctx.app)
|
109
109
|
}
|
110
110
|
|
111
111
|
if ctx.is_a?(::Middleman::TemplateContext) && file
|
@@ -3,12 +3,15 @@ module Middleman
|
|
3
3
|
module Extensions
|
4
4
|
# Class to handle managing ignores
|
5
5
|
class Ignores < Extension
|
6
|
+
# Expose `create_ignore` as `app.ignore`
|
7
|
+
expose_to_application ignore: :create_ignore
|
8
|
+
|
9
|
+
# Expose `create_ignore` to config as `ignore`
|
10
|
+
expose_to_config ignore: :create_ignore
|
11
|
+
|
6
12
|
def initialize(app, config={}, &block)
|
7
13
|
super
|
8
14
|
|
9
|
-
@app.add_to_config_context(:ignore, &method(:create_ignore))
|
10
|
-
@app.define_singleton_method(:ignore, &method(:create_ignore))
|
11
|
-
|
12
15
|
# Array of callbacks which can ass ignored
|
13
16
|
@ignored_callbacks = Set.new
|
14
17
|
|
@@ -18,7 +21,7 @@ module Middleman
|
|
18
21
|
# Ignore a path or add an ignore callback
|
19
22
|
# @param [String, Regexp] path Path glob expression, or path regex
|
20
23
|
# @return [void]
|
21
|
-
Contract Maybe[Or[String, Regexp]], Proc => Any
|
24
|
+
Contract Maybe[Or[String, Regexp]], Maybe[Proc] => Any
|
22
25
|
def create_ignore(path=nil, &block)
|
23
26
|
if path.is_a? Regexp
|
24
27
|
@ignored_callbacks << proc { |p| p =~ path }
|