middleman-core 4.0.0 → 4.1.0.rc.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/features/asset_hash.feature +63 -0
  3. data/features/asset_host.feature +14 -0
  4. data/features/cache_buster.feature +15 -1
  5. data/features/clean_build.feature +16 -0
  6. data/features/cli/preview_server.feature +6 -4
  7. data/features/cli_extension.feature +1 -1
  8. data/features/directory_index.feature +3 -1
  9. data/features/encoding_option.feature +28 -0
  10. data/features/i18n_mixed_sources.feature +39 -0
  11. data/features/ignore.feature +33 -4
  12. data/features/relative_assets.feature +14 -0
  13. data/features/support/env.rb +1 -1
  14. data/fixtures/asset-hash-app/source/index.html.erb +3 -0
  15. data/fixtures/asset-hash-app/source/layout.erb +3 -3
  16. data/fixtures/asset-hash-app/source/other.html.erb +3 -0
  17. data/fixtures/asset-hash-app/source/stylesheets/fragment.css.scss +7 -0
  18. data/fixtures/asset-hash-host-app/source/index.html.erb +3 -0
  19. data/fixtures/asset-hash-host-app/source/layout.erb +3 -3
  20. data/fixtures/asset-hash-host-app/source/other.html.erb +3 -0
  21. data/fixtures/asset-hash-host-app/source/stylesheets/fragment.css.scss +3 -0
  22. data/fixtures/i-8859-1-app/config.rb +1 -0
  23. data/fixtures/i-8859-1-app/source/index.html.erb +1 -0
  24. data/fixtures/i18n-mixed-sources/config.rb +1 -0
  25. data/fixtures/i18n-mixed-sources/locales/en.yml +4 -0
  26. data/fixtures/i18n-mixed-sources/locales/es.yml +4 -0
  27. data/fixtures/i18n-mixed-sources/source/a/sub.html.erb +9 -0
  28. data/fixtures/i18n-mixed-sources/source/b/index.html.erb +9 -0
  29. data/fixtures/i18n-mixed-sources/source/index.html.erb +9 -0
  30. data/fixtures/i18n-mixed-sources/source/localizable/a/index.html.erb +9 -0
  31. data/fixtures/i18n-mixed-sources/source/localizable/b/sub.html.erb +9 -0
  32. data/fixtures/i18n-mixed-sources/source/localizable/index.html.erb +9 -0
  33. data/fixtures/import-app/config.rb +1 -1
  34. data/fixtures/indexable-app/config.rb +1 -0
  35. data/fixtures/indexable-app/source/regex_leave_me_alone2.html +1 -0
  36. data/lib/middleman-core/application.rb +6 -5
  37. data/lib/middleman-core/builder.rb +7 -3
  38. data/lib/middleman-core/core_extensions/collections.rb +3 -1
  39. data/lib/middleman-core/core_extensions/collections/step_context.rb +6 -7
  40. data/lib/middleman-core/core_extensions/default_helpers.rb +2 -2
  41. data/lib/middleman-core/core_extensions/front_matter.rb +1 -0
  42. data/lib/middleman-core/core_extensions/i18n.rb +16 -9
  43. data/lib/middleman-core/core_extensions/routing.rb +1 -1
  44. data/lib/middleman-core/extension.rb +34 -0
  45. data/lib/middleman-core/extensions/asset_hash.rb +2 -0
  46. data/lib/middleman-core/extensions/asset_host.rb +2 -0
  47. data/lib/middleman-core/extensions/cache_buster.rb +2 -0
  48. data/lib/middleman-core/extensions/external_pipeline.rb +0 -2
  49. data/lib/middleman-core/extensions/gzip.rb +1 -1
  50. data/lib/middleman-core/extensions/relative_assets.rb +2 -0
  51. data/lib/middleman-core/load_paths.rb +1 -1
  52. data/lib/middleman-core/meta_pages/sitemap_resource.rb +1 -1
  53. data/lib/middleman-core/middleware/inline_url_rewriter.rb +10 -2
  54. data/lib/middleman-core/sitemap/extensions/ignores.rb +37 -39
  55. data/lib/middleman-core/sitemap/extensions/import.rb +24 -66
  56. data/lib/middleman-core/sitemap/extensions/move_file.rb +9 -38
  57. data/lib/middleman-core/sitemap/extensions/proxies.rb +20 -52
  58. data/lib/middleman-core/sitemap/extensions/traversal.rb +13 -1
  59. data/lib/middleman-core/sitemap/resource.rb +4 -9
  60. data/lib/middleman-core/sitemap/store.rb +10 -9
  61. data/lib/middleman-core/step_definitions/server_steps.rb +4 -0
  62. data/lib/middleman-core/util.rb +22 -24
  63. data/lib/middleman-core/version.rb +1 -1
  64. data/spec/middleman-core/util_spec.rb +10 -1
  65. metadata +34 -4
@@ -1,2 +1,5 @@
1
1
  <h2>Image url:</h2>
2
2
  <img src="<%= image_path('100px.jpg') %>">
3
+ <img src="<%= image_path('100px.jpg?test') %>">
4
+ <img src="<%= image_path('100px.jpg?#test') %>">
5
+ <img src="<%= image_path('100px.jpg#test') %>">
@@ -0,0 +1,7 @@
1
+ #main {
2
+ padding: 50px;
3
+ background-image: image-url('100px.jpg');
4
+ background-image: image-url('100px.jpg?test');
5
+ background-image: image-url('100px.jpg?#test');
6
+ background-image: image-url('100px.jpg#test');
7
+ }
@@ -4,3 +4,6 @@
4
4
 
5
5
  <h2>Image url:</h2>
6
6
  <%= image_tag('100px.jpg') %>
7
+ <%= image_tag('100px.jpg?test') %>
8
+ <%= image_tag('100px.jpg?#test') %>
9
+ <%= image_tag('100px.jpg#test') %>
@@ -3,15 +3,15 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
 
6
- <%= stylesheet_link_tag "site" %>
6
+ <%= stylesheet_link_tag "site", "fragment" %>
7
7
  <%= yield_content :head %>
8
8
  </head>
9
-
9
+
10
10
  <body class="<%= page_classes %>">
11
11
 
12
12
  <div id="main" role="main">
13
13
  <%= yield %>
14
14
  </div>
15
-
15
+
16
16
  </body>
17
17
  </html>
@@ -1,2 +1,5 @@
1
1
  <h2>Image url:</h2>
2
2
  <img src="<%= image_path('100px.jpg') %>">
3
+ <img src="<%= image_path('100px.jpg?test') %>">
4
+ <img src="<%= image_path('100px.jpg?#test') %>">
5
+ <img src="<%= image_path('100px.jpg#test') %>">
@@ -1,4 +1,7 @@
1
1
  #main {
2
2
  padding: 50px;
3
+ background-image: image-url('100px.jpg');
4
+ background-image: image-url('100px.jpg?test');
5
+ background-image: image-url('100px.jpg?#test');
3
6
  background-image: image-url('100px.jpg#test');
4
7
  }
@@ -0,0 +1 @@
1
+ set :encoding, "ISO-8859-1"
@@ -0,0 +1 @@
1
+ ���
@@ -0,0 +1 @@
1
+ activate :i18n, mount_at_root: :en, langs: [:en, :es]
@@ -0,0 +1,4 @@
1
+ ---
2
+ en:
3
+ greetings: "Howdy"
4
+ hi: "Hello"
@@ -0,0 +1,4 @@
1
+ ---
2
+ es:
3
+ greetings: "Como Esta?"
4
+ hi: "Hola"
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: a/sub.html.erb
3
+ ---
4
+ Current locale: <%= I18n.locale %>
5
+ path: <%=
6
+ hierarchy = [current_page]
7
+ hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent
8
+ hierarchy.collect {|page| page.data.title }.join(" # ")
9
+ %>
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: b/index.html.erb
3
+ ---
4
+ Current locale: <%= I18n.locale %>
5
+ path: <%=
6
+ hierarchy = [current_page]
7
+ hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent
8
+ hierarchy.collect {|page| page.data.title }.join(" # ")
9
+ %>
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: non-localized Home
3
+ ---
4
+ Current locale: <%= I18n.locale %>
5
+ path: <%=
6
+ hierarchy = [current_page]
7
+ hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent
8
+ hierarchy.collect {|page| page.data.title }.join(" # ")
9
+ %>
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: a/index.html.erb
3
+ ---
4
+ Current locale: <%= I18n.locale %>
5
+ path: <%=
6
+ hierarchy = [current_page]
7
+ hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent
8
+ hierarchy.collect {|page| page.data.title }.join(" # ")
9
+ %>
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: b/sub.html.erb
3
+ ---
4
+ Current locale: <%= I18n.locale %>
5
+ path: <%=
6
+ hierarchy = [current_page]
7
+ hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent
8
+ hierarchy.collect {|page| page.data.title }.join(" # ")
9
+ %>
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: is-localized Home
3
+ ---
4
+ Current locale: <%= I18n.locale %>
5
+ path: <%=
6
+ hierarchy = [current_page]
7
+ hierarchy.unshift hierarchy.first.parent while hierarchy.first.parent
8
+ hierarchy.collect {|page| page.data.title }.join(" # ")
9
+ %>
@@ -4,4 +4,4 @@ import_path File.expand_path("bower_components/", root)
4
4
 
5
5
  import_path File.expand_path("bower_components", root) do |target_path, original_path|
6
6
  target_path.sub('bower_components', 'bower_components2')
7
- end
7
+ end
@@ -2,3 +2,4 @@ activate :directory_indexes
2
2
  page "/leave_me_alone.html", directory_index: false
3
3
 
4
4
  page "/wildcard*", directory_index: false
5
+ page /regex_.*/, directory_index: false
@@ -0,0 +1 @@
1
+ Stay away, wildcards!
@@ -191,6 +191,8 @@ module Middleman
191
191
  yaml: [%w(--- ---), %w(--- ...)]
192
192
  }, 'Allowed frontmatter delimiters'
193
193
 
194
+ define_setting :skip_build_clean, proc { |p| [/\.git/].any? { |r| r.match(p) } }, 'Whether some paths should not be removed during a clean build.'
195
+
194
196
  define_setting :watcher_disable, false, 'If the Listen watcher should not run'
195
197
  define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode'
196
198
  define_setting :watcher_latency, nil, 'The Listen watcher latency'
@@ -253,11 +255,6 @@ module Middleman
253
255
  # Initialize the Sitemap
254
256
  @sitemap = ::Middleman::Sitemap::Store.new(self)
255
257
 
256
- if Object.const_defined?(:Encoding)
257
- Encoding.default_internal = config[:encoding]
258
- Encoding.default_external = config[:encoding]
259
- end
260
-
261
258
  ::Middleman::Extension.clear_after_extension_callbacks
262
259
 
263
260
  after_configuration_eval(&method(:prune_tilt_templates))
@@ -276,6 +273,10 @@ module Middleman
276
273
  # Eval config.
277
274
  evaluate_configuration!
278
275
 
276
+ if Object.const_defined?(:Encoding)
277
+ Encoding.default_external = config[:encoding]
278
+ end
279
+
279
280
  # Run any `configure` blocks for the current environment.
280
281
  execute_callbacks([:configure, config[:environment]])
281
282
 
@@ -58,7 +58,7 @@ module Middleman
58
58
  prerender_css
59
59
  output_files
60
60
 
61
- clean if @cleaning
61
+ clean! if @cleaning
62
62
 
63
63
  ::Middleman::Profiling.report('build')
64
64
 
@@ -219,8 +219,12 @@ module Middleman
219
219
 
220
220
  # Remove files which were not built in this cycle
221
221
  Contract ArrayOf[Pathname]
222
- def clean
223
- @to_clean.each do |f|
222
+ def clean!
223
+ to_remove = @to_clean.reject do |f|
224
+ app.config[:skip_build_clean].call(f.to_s)
225
+ end
226
+
227
+ to_remove.each do |f|
224
228
  FileUtils.rm(f)
225
229
  trigger(:deleted, f)
226
230
  end
@@ -100,7 +100,9 @@ module Middleman
100
100
  end
101
101
 
102
102
  # Inject descriptors
103
- resources + ctx.descriptors.map { |d| d.to_resource(app) }
103
+ ctx.descriptors.reduce(resources) do |sum, d|
104
+ d.execute_descriptor(app, sum)
105
+ end
104
106
  end
105
107
  end
106
108
  end
@@ -1,5 +1,3 @@
1
- require 'hamster'
2
-
3
1
  module Middleman
4
2
  module CoreExtensions
5
3
  module Collections
@@ -11,15 +9,16 @@ module Middleman
11
9
  attr_reader :descriptors
12
10
 
13
11
  def initialize
14
- @descriptors = ::Hamster::Set.empty
12
+ @descriptors = []
15
13
  end
16
14
 
17
15
  def method_missing(name, *args, &block)
18
16
  internal = :"_internal_#{name}"
19
- if respond_to?(internal)
20
- @descriptors = @descriptors.add(send(internal, *args, &block))
21
- else
22
- super
17
+
18
+ return super unless respond_to?(internal)
19
+
20
+ send(internal, *args, &block).tap do |r|
21
+ @descriptors << r if r.respond_to?(:execute_descriptor)
23
22
  end
24
23
  end
25
24
  end
@@ -201,9 +201,9 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension
201
201
  # @param [String] prefix The type prefix (such as "images")
202
202
  # @param [Hash] options Additional options.
203
203
  # @return [String] The fully qualified asset url
204
- def asset_url(_path, prefix='', options={})
204
+ def asset_url(path, prefix='', options={})
205
205
  options_with_resource = options.merge(current_resource: current_resource)
206
- ::Middleman::Util.asset_url(app, prefix, options_with_resource)
206
+ ::Middleman::Util.asset_url(app, path, prefix, options_with_resource)
207
207
  end
208
208
 
209
209
  # Given a source path (referenced either absolutely or relatively)
@@ -28,6 +28,7 @@ module Middleman::CoreExtensions
28
28
  Contract ResourceList => ResourceList
29
29
  def manipulate_resource_list(resources)
30
30
  resources.each do |resource|
31
+ next if resource.ignored?
31
32
  next if resource.file_descriptor.nil?
32
33
 
33
34
  fmdata = data(resource.file_descriptor[:full_path].to_s).first.dup
@@ -185,7 +185,9 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
185
185
  sum[abs_path][desc.locale] = '/' + desc.path
186
186
  end
187
187
 
188
- resources + new_resources.map { |r| r.to_resource(app) }
188
+ new_resources.reduce(resources) do |sum, r|
189
+ r.execute_descriptor(app, sum)
190
+ end
189
191
  end
190
192
 
191
193
  Contract String, Symbol => String
@@ -196,6 +198,16 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
196
198
  @lookup[lookup_path] && @lookup[lookup_path][locale]
197
199
  end
198
200
 
201
+ Contract Symbol => String
202
+ def path_root(locale)
203
+ if (options[:mount_at_root] == locale) || (options[:mount_at_root].nil? && locales[0] == locale)
204
+ '/'
205
+ else
206
+ replacement = options[:locale_map].fetch(locale, locale)
207
+ options[:path].sub(':locale', replacement.to_s).sub(':lang', replacement.to_s) # Backward compat
208
+ end
209
+ end
210
+
199
211
  private
200
212
 
201
213
  def on_file_changed(_updated_files, _removed_files)
@@ -245,10 +257,10 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
245
257
  end
246
258
 
247
259
  LocalizedPageDescriptor = Struct.new(:path, :source_path, :locale) do
248
- def to_resource(app)
260
+ def execute_descriptor(app, resources)
249
261
  r = ::Middleman::Sitemap::ProxyResource.new(app.sitemap, path, source_path)
250
262
  r.add_metadata options: { locale: locale }
251
- r
263
+ resources + [r]
252
264
  end
253
265
  end
254
266
 
@@ -267,12 +279,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
267
279
 
268
280
  path = "#{partially_localized_path}/#{File.basename(path)}"
269
281
 
270
- prefix = if (options[:mount_at_root] == locale) || (options[:mount_at_root].nil? && locales[0] == locale)
271
- '/'
272
- else
273
- replacement = options[:locale_map].fetch(locale, locale)
274
- options[:path].sub(':locale', replacement.to_s).sub(':lang', replacement.to_s) # Backward compat
275
- end
282
+ prefix = path_root(locale)
276
283
 
277
284
  # path needs to be changed if file has a localizable extension. (options[mount_at_root] == locale)
278
285
  path = ::Middleman::Util.normalize_path(
@@ -44,7 +44,7 @@ module Middleman
44
44
  # @option opts [Hash] locals Local variables for the template. These will be available when the template renders.
45
45
  # @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}.
46
46
  # @return [void]
47
- Contract String, Hash => Any
47
+ Contract Or[String, Regexp], Hash => Any
48
48
  def page(path, opts={})
49
49
  options = opts.dup
50
50
 
@@ -469,4 +469,38 @@ module Middleman
469
469
  @app.ready(&method(:ready)) if respond_to?(:ready)
470
470
  end
471
471
  end
472
+
473
+ class ConfigExtension < Extension
474
+ def initialize(app, config={}, &block)
475
+ @descriptors = {}
476
+ @wrapped = {}
477
+
478
+ self.class.exposed_to_config.each do |k, v|
479
+ @descriptors[k] = []
480
+
481
+ define_singleton_method(:"__original_#{v}", &method(v))
482
+ define_singleton_method(v) do |*args, &block|
483
+ @descriptors[k] << method(:"__original_#{v}").call(*args, &block)
484
+ @app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}")
485
+ end
486
+ end
487
+
488
+ super
489
+ end
490
+
491
+ def after_configuration
492
+ self.class.exposed_to_config.each do |k, v|
493
+ ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(k, &method(:"__original_#{v}"))
494
+ end
495
+ end
496
+
497
+ # Update the main sitemap resource list
498
+ # @return Array<Middleman::Sitemap::Resource>
499
+ Contract ResourceList => ResourceList
500
+ def manipulate_resource_list(resources)
501
+ @descriptors.values.flatten.reduce(resources) do |sum, c|
502
+ c.execute_descriptor(app, sum)
503
+ end
504
+ end
505
+ end
472
506
  end
@@ -5,6 +5,7 @@ require 'middleman-core/rack'
5
5
  class Middleman::Extensions::AssetHash < ::Middleman::Extension
6
6
  option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .woff2 .eot .ttf .svg .svgz), 'List of extensions that get asset hashes appended to them.'
7
7
  option :ignore, [], 'Regexes of filenames to skip adding asset hashes to'
8
+ option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
8
9
 
9
10
  def initialize(app, options_hash={}, &block)
10
11
  super
@@ -23,6 +24,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
23
24
  url_extensions: options.exts.sort.reverse,
24
25
  source_extensions: %w(.htm .html .php .css .js),
25
26
  ignore: @ignore,
27
+ rewrite_ignore: options.rewrite_ignore,
26
28
  middleman_app: app,
27
29
  proc: method(:rewrite_url)
28
30
  end
@@ -6,6 +6,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
6
6
  option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif), 'List of extensions that get cache busters strings appended to them.'
7
7
  option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.'
8
8
  option :ignore, [], 'Regexes of filenames to skip adding query strings to'
9
+ option :rewrite_ignore, [], 'Regexes of filenames to skip processing for host rewrites'
9
10
 
10
11
  def ready
11
12
  app.use ::Middleman::Middleware::InlineURLRewriter,
@@ -13,6 +14,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
13
14
  url_extensions: options.exts,
14
15
  source_extensions: options.sources,
15
16
  ignore: options.ignore,
17
+ rewrite_ignore: options.rewrite_ignore,
16
18
  middleman_app: app,
17
19
  proc: method(:rewrite_url)
18
20
  end
@@ -3,6 +3,7 @@ class Middleman::Extensions::CacheBuster < ::Middleman::Extension
3
3
  option :exts, %w(.css .png .jpg .jpeg .webp .svg .svgz .js .gif), 'List of extensions that get cache busters strings appended to them.'
4
4
  option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.'
5
5
  option :ignore, [], 'Regexes of filenames to skip adding query strings to'
6
+ option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
6
7
 
7
8
  def initialize(app, options_hash={}, &block)
8
9
  super
@@ -16,6 +17,7 @@ class Middleman::Extensions::CacheBuster < ::Middleman::Extension
16
17
  url_extensions: options.exts,
17
18
  source_extensions: options.sources,
18
19
  ignore: options.ignore,
20
+ rewrite_ignore: options.rewrite_ignore,
19
21
  middleman_app: app,
20
22
  proc: method(:rewrite_url)
21
23
  end
@@ -15,9 +15,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
15
15
  @watcher = app.files.watch :source,
16
16
  path: File.expand_path(options[:source], app.root),
17
17
  latency: options[:latency]
18
- end
19
18
 
20
- def ready
21
19
  logger.info "== Executing: `#{options[:command]}`"
22
20
 
23
21
  if app.build? || options[:disable_background_execution]