middleman-core 4.1.1 → 4.1.2

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/features/asset_hash.feature +14 -0
  3. data/features/builder.feature +8 -4
  4. data/features/custom_layouts.feature +17 -1
  5. data/features/page-id.feature +26 -0
  6. data/features/partials.feature +7 -0
  7. data/fixtures/asset-hash-source-map/config.rb +6 -0
  8. data/fixtures/asset-hash-source-map/lib/middleware.rb +16 -0
  9. data/fixtures/asset-hash-source-map/source/index.html.erb +6 -0
  10. data/fixtures/asset-hash-source-map/source/javascripts/application.js +2 -0
  11. data/fixtures/asset-hash-source-map/source/javascripts/application.js.map +1 -0
  12. data/fixtures/asset-hash-source-map/source/layout.erb +17 -0
  13. data/fixtures/external-pipeline-error/config.rb +5 -0
  14. data/fixtures/external-pipeline-error/source/javascripts/file.js +0 -0
  15. data/fixtures/page-id-app/config.rb +5 -0
  16. data/fixtures/page-id-app/source/fm.html.erb +5 -0
  17. data/fixtures/page-id-app/source/index.html.erb +6 -0
  18. data/fixtures/page-id-app/source/overwrites/from-default.html.erb +1 -0
  19. data/fixtures/page-id-app/source/overwrites/from-frontmatter.html.erb +5 -0
  20. data/fixtures/partials-app/source/_block.erb +3 -0
  21. data/fixtures/partials-app/source/block.html.erb +3 -0
  22. data/lib/middleman-core/application.rb +2 -2
  23. data/lib/middleman-core/builder.rb +1 -1
  24. data/lib/middleman-core/configuration.rb +1 -1
  25. data/lib/middleman-core/core_extensions/data.rb +2 -2
  26. data/lib/middleman-core/core_extensions/i18n.rb +1 -1
  27. data/lib/middleman-core/core_extensions/routing.rb +6 -3
  28. data/lib/middleman-core/extension.rb +2 -2
  29. data/lib/middleman-core/extensions/asset_hash.rb +1 -1
  30. data/lib/middleman-core/extensions/external_pipeline.rb +6 -1
  31. data/lib/middleman-core/load_paths.rb +3 -1
  32. data/lib/middleman-core/logger.rb +1 -1
  33. data/lib/middleman-core/meta_pages/templates/index.html.erb +3 -1
  34. data/lib/middleman-core/rack.rb +2 -0
  35. data/lib/middleman-core/renderers/redcarpet.rb +2 -2
  36. data/lib/middleman-core/sitemap/extensions/proxies.rb +4 -1
  37. data/lib/middleman-core/sitemap/resource.rb +13 -3
  38. data/lib/middleman-core/sitemap/store.rb +21 -1
  39. data/lib/middleman-core/template_context.rb +2 -1
  40. data/lib/middleman-core/util/data.rb +1 -1
  41. data/lib/middleman-core/util/files.rb +5 -16
  42. data/lib/middleman-core/util/paths.rb +6 -1
  43. data/lib/middleman-core/util/rack.rb +1 -1
  44. data/lib/middleman-core/version.rb +1 -1
  45. data/middleman-core.gemspec +2 -2
  46. data/spec/middleman-core/core_extensions/data_spec.rb +107 -1
  47. metadata +38 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7bf6cdbd67953b3d7195092beb23c4c05881a64a
4
- data.tar.gz: 9cd56c0edca32368b9a5571cf2eee67a5b4538b0
3
+ metadata.gz: 56d4346f7e637375c81e78637eb685379d71afdc
4
+ data.tar.gz: 49168cf55df8f81be1c53ccff538bd36916089a4
5
5
  SHA512:
6
- metadata.gz: 7d09604286c7f77eaa0afe637a9ced84bc130ba4cd7e83816c83015097988cb4f83f2cebc18da59471b8d88e26878a7f94535225e8d5c8ddeaf49ae144f36cf3
7
- data.tar.gz: 251ce00d297f8c3b92f80fd7660febdafa81cfcd7b40958b96136296fe1fe6a8ad482b3fc33430f28dc7c1f540b5861fc0b1a8ba9608696c65b6c5a45681841e
6
+ metadata.gz: 3b13b9ee36f2d9e64a56569d167d81d5b4fc8cfd3fb71d653640cd9ec59ef352ba80f01ed6bb353a413d96ea96b747b1a2fe7a258491ef81174228ef3a0d0f2b
7
+ data.tar.gz: af98ca1aa0717fa1d25258324e42a3cafc38e8f4d813ae9286321b24fed8a18a0a884d6738de5db9b1a692a0753da725468f6d4490403d9e9a3c2136f5f2daf7
@@ -285,3 +285,17 @@ Feature: Assets get file hashes appended to them and references to them are upda
285
285
  | javascripts/jquery.min-276c87ff.js |
286
286
  And the following files should not exist:
287
287
  | javascripts/jquery.min.js |
288
+
289
+ Scenario: Source map paths include the hash
290
+ Given a successfully built app at "asset-hash-source-map"
291
+ When I cd to "build"
292
+ Then the following files should exist:
293
+ | index.html |
294
+ | javascripts/application-4553338c.js |
295
+ | javascripts/application.js-22cc2b5f.map |
296
+ | index.html |
297
+ And the following files should not exist:
298
+ | javascripts/application.js |
299
+ | javascripts/application.js.map |
300
+
301
+ And the file "javascripts/application-4553338c.js" should contain "//# sourceMappingURL=application.js-22cc2b5f.map"
@@ -20,13 +20,13 @@ Feature: Builder
20
20
  | layout |
21
21
  | layouts/custom |
22
22
  | layouts/content_for |
23
-
23
+
24
24
  And the file "index.html" should contain "Comment in layout"
25
25
  And the file "index.html" should contain "<h1>Welcome</h1>"
26
26
  And the file "static.html" should contain "Static, no code!"
27
27
  And the file "services/index.html" should contain "Services"
28
28
  And the file "stylesheets/static.css" should contain "body"
29
-
29
+
30
30
  Scenario: Build glob
31
31
  Given a successfully built app at "glob-app" with flags "--glob '*.css'"
32
32
  When I cd to "build"
@@ -34,15 +34,19 @@ Feature: Builder
34
34
  | index.html |
35
35
  Then the following files should exist:
36
36
  | stylesheets/site.css |
37
-
37
+
38
38
  Scenario: Build with errors
39
39
  Given a built app at "build-with-errors-app"
40
40
  Then the exit status should be 1
41
-
41
+
42
42
  Scenario: Build empty errors
43
43
  Given a built app at "empty-app"
44
44
  Then the exit status should be 1
45
45
 
46
+ Scenario: Build external_pipeline errors
47
+ Given a built app at "external-pipeline-error"
48
+ Then the exit status should be 1
49
+
46
50
  Scenario: Build alias (b)
47
51
  Given a fixture app "large-build-app"
48
52
  When I run `middleman b`
@@ -11,6 +11,22 @@ Feature: Custom layouts
11
11
  When I go to "/custom-layout.html"
12
12
  Then I should see "Custom Layout"
13
13
 
14
+ Scenario: Using custom :layout attribute with proxy
15
+ Given a fixture app "custom-layout-app2"
16
+ And a file named "config.rb" with:
17
+ """
18
+ page '/test/*', layout: :custom
19
+ proxy "/test/me.html", "/custom-layout.html"
20
+ live { %w(you) }.each do |who|
21
+ proxy "/test/#{who}.html", "/custom-layout.html"
22
+ end
23
+ """
24
+ And the Server is running at "custom-layout-app2"
25
+ When I go to "/test/me.html"
26
+ Then I should see "Custom Layout"
27
+ When I go to "/test/you.html"
28
+ Then I should see "Custom Layout"
29
+
14
30
  Scenario: Using custom :layout attribute with folders
15
31
  Given a fixture app "custom-layout-app2"
16
32
  And a file named "config.rb" with:
@@ -65,4 +81,4 @@ Feature: Custom layouts
65
81
  When I go to "/path/index.html"
66
82
  Then I should see "Alt"
67
83
  And I should see "Monde"
68
- And I should not see "Hello"
84
+ And I should not see "Hello"
@@ -0,0 +1,26 @@
1
+ Feature: Page IDs
2
+
3
+ Scenario: link_to works with blocks (erb)
4
+ Given the Server is running at "page-id-app"
5
+ When I go to "/index.html"
6
+ Then I should see "I am: index.html"
7
+ And I should see "URL1: /fm.html"
8
+ And I should see "URL2: /2.html"
9
+ And I should see 'URL3: <a href="/3.html">Hi</a>'
10
+ And I should see 'URL4: <a href="/overwrites/from-default.html">Sym</a>'
11
+
12
+ When I go to "/fm.html"
13
+ Then I should see "I am: frontmatter"
14
+
15
+ When I go to "/1.html"
16
+ Then I should see "I am: page1"
17
+ When I go to "/2.html"
18
+ Then I should see "I am: page2"
19
+ When I go to "/3.html"
20
+ Then I should see "I am: page3"
21
+
22
+ When I go to "/overwrites/from-default.html"
23
+ Then I should see "I am: something-else"
24
+
25
+ When I go to "/overwrites/from-frontmatter.html"
26
+ Then I should see "I am: from_frontmatter"
@@ -50,3 +50,10 @@ Feature: Provide Sane Defaults for Partial Behavior
50
50
  Then I should see "File Not Found"
51
51
  When I go to "/_code_snippet.html"
52
52
  Then I should see "File Not Found"
53
+
54
+ Scenario: Works with blocks
55
+ Given the Server is running at "partials-app"
56
+ When I go to "/block.html"
57
+ Then I should see "Start"
58
+ And I should see "Contents"
59
+ And I should see "End"
@@ -0,0 +1,6 @@
1
+
2
+ activate :asset_hash
3
+
4
+ activate :relative_assets
5
+
6
+ activate :directory_indexes
@@ -0,0 +1,16 @@
1
+ class Middleware
2
+ def initialize(app)
3
+ @app = app
4
+ end
5
+
6
+ def call(env)
7
+ status, headers, response = @app.call(env)
8
+ body = ''
9
+ response.each {|part| body += part }
10
+ if (env["PATH_INFO"] =~ /css$/)
11
+ body += "\n/* Added by Rack filter */"
12
+ status, headers, response = Rack::Response.new(body, status, headers).finish
13
+ end
14
+ [status, headers, response]
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ <% content_for :head do %>
2
+ <title>The Middleman!</title>
3
+ <% end %>
4
+
5
+ <h1>Testing the sitemap hashing</h1>
6
+ <br /><br /><br />
@@ -0,0 +1,2 @@
1
+ function foo(){var message="HEY THERE FRIEND!";var para=document.createElement("p");para.innerHTML=message;var body=document.getElementsByTagName("body")[0];body.insertBefore(para,body.firstChild)}window.onload=foo;
2
+ //# sourceMappingURL=application.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["source/javascripts/application.js"],"names":["foo","message","para","document","createElement","innerHTML","body","getElementsByTagName","insertBefore","firstChild","window","onload"],"mappings":"AAAA,QAASA,OACP,GAAIC,SAAU,mBACd,IAAIC,MAAOC,SAASC,cAAc,IAClCF,MAAKG,UAAYJ,OACb,IAAIK,MAAOH,SAASI,qBAAqB,QAAQ,EAC/CD,MAAKE,aAAaN,KAAMI,KAAKG,YAGpCC,OAAOC,OAASX"}
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+
6
+ <%= javascript_include_tag "application" %>
7
+ <%= yield_content :head %>
8
+ </head>
9
+
10
+ <body class="<%= page_classes %>">
11
+
12
+ <div id="main" role="main">
13
+ <%= yield %>
14
+ </div>
15
+
16
+ </body>
17
+ </html>
@@ -0,0 +1,5 @@
1
+ activate :external_pipeline,
2
+ name: :failing,
3
+ command: "mv does-not-exist tmp/file.js",
4
+ source: "tmp",
5
+ latency: 2
@@ -0,0 +1,5 @@
1
+ %w(1 2 3).each do |n|
2
+ proxy "/#{n}.html", "/index.html", id: "page#{n}"
3
+ end
4
+
5
+ page "/overwrites/*", id: :"something-else"
@@ -0,0 +1,5 @@
1
+ ---
2
+ id: frontmatter
3
+ ---
4
+
5
+ I am: <%= current_resource.page_id %>
@@ -0,0 +1,6 @@
1
+ I am: <%= current_resource.page_id %>
2
+
3
+ URL1: <%= url_for "frontmatter" %>
4
+ URL2: <%= url_for "page2" %>
5
+ URL3: <%= link_to "Hi", "page3" %>
6
+ URL4: <%= link_to "Sym", :"something-else" %>
@@ -0,0 +1 @@
1
+ I am: <%= current_resource.page_id %>
@@ -0,0 +1,5 @@
1
+ ---
2
+ id: from_frontmatter
3
+ ---
4
+
5
+ I am: <%= current_resource.page_id %>
@@ -0,0 +1,3 @@
1
+ Start
2
+ <%= yield %>
3
+ End
@@ -0,0 +1,3 @@
1
+ <% partial "block" do %>
2
+ Contents
3
+ <% end %>
@@ -183,8 +183,8 @@ module Middleman
183
183
  ignored
184
184
  end,
185
185
 
186
- layout: proc do |file, _sitemap_app|
187
- file[:relative_path].to_s.start_with?('layout.', 'layouts/')
186
+ layout: proc do |file, app|
187
+ file[:relative_path].to_s.start_with?('layout.', app.config[:layouts_dir] + '/')
188
188
  end
189
189
  }, 'Callbacks that can exclude paths from the sitemap'
190
190
 
@@ -97,7 +97,7 @@ module Middleman
97
97
 
98
98
  ::Middleman::Util.instrument 'builder.prerender.check-files' do
99
99
  # Double-check for compass sprites
100
- if @app.files.find_new_files!.length > 0
100
+ unless @app.files.find_new_files!.empty?
101
101
  logger.debug '== Checking for Compass sprites'
102
102
  @app.sitemap.ensure_resource_list_updated!
103
103
  end
@@ -40,7 +40,7 @@ module Middleman
40
40
 
41
41
  # Allow configuration settings to be read and written via methods
42
42
  def method_missing(method, *args)
43
- if defines_setting?(method) && args.size == 0
43
+ if defines_setting?(method) && args.empty?
44
44
  self[method]
45
45
  elsif method.to_s =~ /^(\w+)=$/ && args.size == 1
46
46
  self[$1.to_sym] = args[0]
@@ -67,7 +67,7 @@ module Middleman
67
67
  # @param [Symbol] name Name of the data, used for namespacing
68
68
  # @param [Hash] content The content for this data
69
69
  # @return [Hash]
70
- Contract Symbol, Hash => Hash
70
+ Contract Symbol, Or[Hash, Array] => Hash
71
71
  def store(name=nil, content=nil)
72
72
  @local_sources[name.to_s] = content unless name.nil? || content.nil?
73
73
  @local_sources
@@ -148,7 +148,7 @@ module Middleman
148
148
  #
149
149
  # @param [String, Symbol] path The name of the data namespace
150
150
  # @return [Hash, nil]
151
- Contract Or[String, Symbol] => Maybe[Hash]
151
+ Contract Or[String, Symbol] => Maybe[Or[Array, IsA['Middleman::Util::EnhancedHash']]]
152
152
  def data_for_path(path)
153
153
  response = if store.key?(path.to_s)
154
154
  store[path.to_s]
@@ -102,7 +102,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
102
102
  locale_suffix = ::I18n.locale
103
103
 
104
104
  extname = File.extname(partial_name)
105
- maybe_static = extname.length > 0
105
+ maybe_static = !extname.empty?
106
106
  suffixed_partial_name = if maybe_static
107
107
  partial_name.sub(extname, ".#{locale_suffix}#{extname}")
108
108
  else
@@ -4,7 +4,7 @@ module Middleman
4
4
  class Routing < ConfigExtension
5
5
  # This should always run late, but not as late as :directory_indexes,
6
6
  # so it can add metadata to any pages generated by other extensions
7
- self.resource_list_manipulator_priority = 10
7
+ self.resource_list_manipulator_priority = [10, 130]
8
8
 
9
9
  # Expose the `page` method to config.
10
10
  expose_to_config :page
@@ -25,7 +25,7 @@ module Middleman
25
25
 
26
26
  resources
27
27
  .select { |r| ::Middleman::Util.path_match(normalized_path, "/#{r.path}") }
28
- .each { |r| r.add_metadata(metadata) }
28
+ .each { |r| r.add_metadata(metadata, true) }
29
29
 
30
30
  resources
31
31
  end
@@ -52,10 +52,13 @@ module Middleman
52
52
  def page(path, opts={})
53
53
  options = opts.dup
54
54
 
55
+ page_data = options.delete(:data) || {}
56
+ page_data[:id] = options.delete(:id) if options.key?(:id)
57
+
55
58
  # Default layout
56
59
  metadata = {
57
60
  locals: options.delete(:locals) || {},
58
- page: options.delete(:data) || {},
61
+ page: page_data,
59
62
  options: options
60
63
  }
61
64
 
@@ -402,11 +402,11 @@ module Middleman
402
402
  ext.after_configuration if ext.respond_to?(:after_configuration)
403
403
 
404
404
  if ext.respond_to?(:manipulate_resource_list)
405
- ext.app.sitemap.register_resource_list_manipulator(ext.class.ext_name, ext, ext.class.resource_list_manipulator_priority)
405
+ ext.app.sitemap.register_resource_list_manipulators(ext.class.ext_name, ext, ext.class.resource_list_manipulator_priority)
406
406
  end
407
407
 
408
408
  if ext.class.resources_generators && !ext.class.resources_generators.empty?
409
- ext.app.sitemap.register_resource_list_manipulator(
409
+ ext.app.sitemap.register_resource_list_manipulators(
410
410
  :"#{ext.class.ext_name}_generator",
411
411
  ext,
412
412
  ext.class.resource_list_manipulator_priority,
@@ -3,7 +3,7 @@ require 'middleman-core/rack'
3
3
 
4
4
  class Middleman::Extensions::AssetHash < ::Middleman::Extension
5
5
  option :sources, %w(.css .htm .html .js .php .xhtml), 'List of extensions that are searched for hashable assets.'
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.'
6
+ option :exts, %w(.jpg .jpeg .png .gif .webp .js .css .otf .woff .woff2 .eot .ttf .svg .svgz .map), 'List of extensions that get asset hashes appended to them.'
7
7
  option :ignore, [], 'Regexes of filenames to skip adding asset hashes to'
8
8
  option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
9
9
 
@@ -30,10 +30,15 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
30
30
  ::IO.popen(options[:command], 'r') do |pipe|
31
31
  while buf = pipe.gets
32
32
  without_newline = buf.sub(/\n$/, '')
33
- logger.info "== External: #{without_newline}" if without_newline.length > 0
33
+ logger.info "== External: #{without_newline}" unless without_newline.empty?
34
34
  end
35
35
  end
36
36
 
37
+ unless $?.success?
38
+ logger.error '== External: Command failed with non-zero exit status'
39
+ exit(1)
40
+ end
41
+
37
42
  @watcher.poll_once!
38
43
  rescue ::Errno::ENOENT => e
39
44
  logger.error "== External: Command failed with message: #{e.message}"
@@ -22,7 +22,9 @@ module Middleman
22
22
 
23
23
  # Set BUNDLE_GEMFILE and run Bundler setup. Raises an exception if there is no Gemfile
24
24
  def setup_bundler
25
- ENV['BUNDLE_GEMFILE'] ||= File.join(findup('Gemfile', ENV['MM_ROOT']), 'Gemfile')
25
+ if found_gemfile_root = findup('Gemfile', ENV['MM_ROOT'])
26
+ ENV['BUNDLE_GEMFILE'] ||= File.join(found_gemfile_root, 'Gemfile')
27
+ end
26
28
 
27
29
  unless File.exist?(ENV['BUNDLE_GEMFILE'])
28
30
  ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__)
@@ -7,7 +7,7 @@ module Middleman
7
7
  # The Middleman Logger
8
8
  class Logger < ActiveSupport::Logger
9
9
  def self.singleton(*args)
10
- if !@_logger || args.length > 0
10
+ if !@_logger || !args.empty?
11
11
  if args.length == 1 && (args.first.is_a?(::String) || args.first.respond_to?(:write))
12
12
  args = [0, false, args.first]
13
13
  end
@@ -10,7 +10,9 @@
10
10
  <div class="container">
11
11
  <article id="main">
12
12
  <h1>Middleman Information</h1>
13
-
13
+ <p>
14
+ Middleman version <%= Middleman::VERSION %>
15
+ </p>
14
16
  <ul class="nav-list">
15
17
  <li>
16
18
  <a href="/__middleman/sitemap/">Sitemap</a>
@@ -2,6 +2,7 @@ require 'rack'
2
2
  require 'rack/file'
3
3
  require 'rack/lint'
4
4
  require 'rack/head'
5
+ require 'rack/utils'
5
6
 
6
7
  require 'middleman-core/util'
7
8
  require 'middleman-core/logger'
@@ -124,6 +125,7 @@ module Middleman
124
125
 
125
126
  # Halt request and return 404
126
127
  def not_found(res, path)
128
+ path = ::Rack::Utils.escape_html(path)
127
129
  res.status = 404
128
130
  res.write "<html><head></head><body><h1>File Not Found</h1><p>#{path}</p></body></html>"
129
131
  res.finish
@@ -76,7 +76,7 @@ module Middleman
76
76
  scope.image_tag(link, title: title, alt: alt_text)
77
77
  else
78
78
  link_string = link.dup
79
- link_string << %("#{title}") if title && title.length > 0 && title != alt_text
79
+ link_string << %("#{title}") if title && !title.empty? && title != alt_text
80
80
  "![#{alt_text}](#{link_string})"
81
81
  end
82
82
  end
@@ -89,7 +89,7 @@ module Middleman
89
89
  scope.link_to(content, link, attributes)
90
90
  else
91
91
  link_string = link.dup
92
- link_string << %("#{title}") if title && title.length > 0 && title != alt_text
92
+ link_string << %("#{title}") if title && !title.empty? && title != alt_text
93
93
  "[#{content}](#{link_string})"
94
94
  end
95
95
  end
@@ -36,10 +36,13 @@ module Middleman
36
36
  md = metadata.dup
37
37
  should_ignore = md.delete(:ignore)
38
38
 
39
+ page_data = md.delete(:data) || {}
40
+ page_data[:id] = md.delete(:id) if md.key?(:id)
41
+
39
42
  r = ProxyResource.new(app.sitemap, path, target)
40
43
  r.add_metadata(
41
44
  locals: md.delete(:locals) || {},
42
- page: md.delete(:data) || {},
45
+ page: page_data || {},
43
46
  options: md
44
47
  )
45
48
 
@@ -85,16 +85,26 @@ module Middleman
85
85
  file_descriptor && file_descriptor[:full_path].to_s
86
86
  end
87
87
 
88
+ Contract Or[Symbol, String]
89
+ def page_id
90
+ metadata[:page][:id] || destination_path
91
+ end
92
+
88
93
  # Merge in new metadata specific to this resource.
89
94
  # @param [Hash] meta A metadata block with keys :options, :locals, :page.
90
95
  # Options are generally rendering/sitemap options
91
96
  # Locals are local variables for rendering this resource's template
92
97
  # Page are data that is exposed through this resource's data member.
93
98
  # Note: It is named 'page' for backwards compatibility with older MM.
94
- Contract METADATA_HASH => METADATA_HASH
95
- def add_metadata(meta={})
99
+ Contract METADATA_HASH, Maybe[Bool] => METADATA_HASH
100
+ def add_metadata(meta={}, reverse=false)
96
101
  @page_data = nil
97
- @metadata.deep_merge!(meta)
102
+
103
+ @metadata = if reverse
104
+ meta.deep_merge(@metadata)
105
+ else
106
+ @metadata.deep_merge(meta)
107
+ end
98
108
  end
99
109
 
100
110
  # Data about this resource, populated from frontmatter or extensions.
@@ -87,6 +87,13 @@ module Middleman
87
87
  @app.config_context.class.send :def_delegator, :app, :sitemap
88
88
  end
89
89
 
90
+ Contract Symbol, RespondTo[:manipulate_resource_list], Maybe[Or[Num, ArrayOf[Num]]], Maybe[Symbol] => Any
91
+ def register_resource_list_manipulators(name, manipulator, priority=50, custom_name=nil)
92
+ Array(priority || 50).each do |p|
93
+ register_resource_list_manipulator(name, manipulator, p, custom_name)
94
+ end
95
+ end
96
+
90
97
  # Register an object which can transform the sitemap resource list. Best to register
91
98
  # these in a `before_configuration` or `after_configuration` hook.
92
99
  #
@@ -149,6 +156,17 @@ module Middleman
149
156
  end
150
157
  end
151
158
 
159
+ # Find a resource given its page id
160
+ # @param [String] page_id The page id.
161
+ # @return [Middleman::Sitemap::Resource]
162
+ Contract Or[String, Symbol] => Maybe[IsA['Middleman::Sitemap::Resource']]
163
+ def find_resource_by_page_id(page_id)
164
+ @lock.synchronize do
165
+ ensure_resource_list_updated!
166
+ @_lookup_by_page_id[page_id.to_sym]
167
+ end
168
+ end
169
+
152
170
  # Get the array of all resources
153
171
  # @param [Boolean] include_ignored Whether to include ignored resources
154
172
  # @return [Array<Middleman::Sitemap::Resource>]
@@ -210,7 +228,7 @@ module Middleman
210
228
 
211
229
  @resource_list_manipulators.each do |m|
212
230
  ::Middleman::Util.instrument 'sitemap.manipulator', name: m[:name] do
213
- @app.logger.debug "== Running manipulator: #{m[:name]}"
231
+ @app.logger.debug "== Running manipulator: #{m[:name]} (#{m[:priority]})"
214
232
  @resources = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, @resources)
215
233
 
216
234
  # Reset lookup cache
@@ -220,6 +238,7 @@ module Middleman
220
238
  @resources.each do |resource|
221
239
  @_lookup_by_path[resource.path] = resource
222
240
  @_lookup_by_destination_path[resource.destination_path] = resource
241
+ @_lookup_by_page_id[resource.page_id.to_sym] = resource
223
242
  end
224
243
 
225
244
  invalidate_resources_not_ignored_cache!
@@ -239,6 +258,7 @@ module Middleman
239
258
  @lock.synchronize do
240
259
  @_lookup_by_path = {}
241
260
  @_lookup_by_destination_path = {}
261
+ @_lookup_by_page_id = {}
242
262
  end
243
263
  end
244
264
 
@@ -96,8 +96,9 @@ module Middleman
96
96
  #
97
97
  # @param [String, Symbol] name The partial to render.
98
98
  # @param [Hash] options
99
+ # @param [Proc] block A block will be evaluated to return internal contents.
99
100
  # @return [String]
100
- Contract Any, Or[Symbol, String], Hash => String
101
+ Contract Any, Or[Symbol, String], Hash => String, Maybe[Proc] => String
101
102
  def render(_, name, options={}, &block)
102
103
  name = name.to_s
103
104
 
@@ -29,7 +29,7 @@ module Middleman
29
29
  if obj.is_a? ::Array
30
30
  obj.map { |e| recursively_enhance(e) }
31
31
  elsif obj.is_a? ::Hash
32
- ::Hashie::Mash.new(obj)
32
+ EnhancedHash.new(obj)
33
33
  else
34
34
  obj
35
35
  end
@@ -104,30 +104,19 @@ module Middleman
104
104
  sass_type_aliasing = ['.scss', '.sass']
105
105
  erb_type_aliasing = ['.erb', '.haml', '.slim']
106
106
 
107
- if (all_extensions & sass_type_aliasing).length > 0
108
- all_extensions |= sass_type_aliasing
109
- end
110
-
111
- if (all_extensions & erb_type_aliasing).length > 0
112
- all_extensions |= erb_type_aliasing
113
- end
107
+ all_extensions |= sass_type_aliasing unless (all_extensions & sass_type_aliasing).empty?
108
+ all_extensions |= erb_type_aliasing unless (all_extensions & erb_type_aliasing).empty?
114
109
 
115
110
  all_extensions.uniq!
116
111
 
117
112
  app.sitemap.resources.select(&:file_descriptor).select { |r|
118
113
  local_extensions = collect_extensions(r.file_descriptor[:full_path].to_s)
119
-
120
- if (local_extensions & sass_type_aliasing).length > 0
121
- local_extensions |= sass_type_aliasing
122
- end
123
-
124
- if (local_extensions & erb_type_aliasing).length > 0
125
- local_extensions |= erb_type_aliasing
126
- end
114
+ local_extensions |= sass_type_aliasing unless (local_extensions & sass_type_aliasing).empty?
115
+ local_extensions |= erb_type_aliasing unless (local_extensions & erb_type_aliasing).empty?
127
116
 
128
117
  local_extensions.uniq!
129
118
 
130
- ((all_extensions & local_extensions).length > 0) && files.none? { |f| f == r.file_descriptor[:full_path] }
119
+ !(all_extensions & local_extensions).empty? && files.none? { |f| f == r.file_descriptor[:full_path] }
131
120
  }.map(&:file_descriptor)
132
121
  end
133
122
  end
@@ -99,8 +99,13 @@ module Middleman
99
99
  # Given a source path (referenced either absolutely or relatively)
100
100
  # or a Resource, this will produce the nice URL configured for that
101
101
  # path, respecting :relative_links, directory indexes, etc.
102
- Contract ::Middleman::Application, Or[String, ::Middleman::Sitemap::Resource], Hash => String
102
+ Contract ::Middleman::Application, Or[String, Symbol, ::Middleman::Sitemap::Resource], Hash => String
103
103
  def url_for(app, path_or_resource, options={})
104
+ if path_or_resource.is_a?(String) || path_or_resource.is_a?(Symbol)
105
+ r = app.sitemap.find_resource_by_page_id(path_or_resource)
106
+ path_or_resource = r if r
107
+ end
108
+
104
109
  # Handle Resources and other things which define their own url method
105
110
  url = if path_or_resource.respond_to?(:url)
106
111
  path_or_resource.url
@@ -22,7 +22,7 @@ module Middleman
22
22
 
23
23
  Contract String, String, ArrayOf[String], Proc => String
24
24
  def rewrite_paths(body, _path, exts, &_block)
25
- matcher = /([\'\"\(,]\s*)([^\s\'\"\)>]+(#{::Regexp.union(exts)}))/
25
+ matcher = /([\'\"\(,]\s*|# sourceMappingURL=)([^\s\'\"\)>]+(#{::Regexp.union(exts)}))/
26
26
 
27
27
  url_fn_prefix = 'url('
28
28
 
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  # Current Version
3
3
  # @return [String]
4
- VERSION = '4.1.1'.freeze unless const_defined?(:VERSION)
4
+ VERSION = '4.1.2'.freeze unless const_defined?(:VERSION)
5
5
  end
@@ -51,10 +51,10 @@ Gem::Specification.new do |s|
51
51
  s.add_dependency('execjs', ['~> 2.0'])
52
52
 
53
53
  # Testing
54
- s.add_dependency('contracts', ['~> 0.12.0'])
54
+ s.add_dependency('contracts', ['~> 0.13.0'])
55
55
 
56
56
  # Hash stuff
57
57
  s.add_dependency('hashie', ['~> 3.4'])
58
- s.add_dependency('hamster', ['~> 2.0'])
58
+ s.add_dependency('hamster', ['~> 3.0'])
59
59
  s.add_dependency('backports', ['~> 3.6'])
60
60
  end
@@ -7,6 +7,112 @@ end
7
7
 
8
8
  describe Middleman::CoreExtensions::Data::DataStore do
9
9
 
10
+ describe "#store" do
11
+ before :each do
12
+ @subject = described_class.new instance_double("Middleman::Application"),
13
+ Middleman::CoreExtensions::Data::DATA_FILE_MATCHER
14
+ end
15
+
16
+ context "when given a name and data" do
17
+ it "adds data at the given name" do
18
+ @subject.store :foo, { 'bar' => 'baz' }
19
+ @subject.store :baz, [:wu, :tang]
20
+
21
+ expect( @subject.store['foo'] ).to eq({ 'bar' => 'baz' })
22
+ expect( @subject.store['baz'] ).to match_array [:wu, :tang]
23
+ end
24
+
25
+ it "overwrites previous keys if given the same key" do
26
+ @subject.store :foo, { 'bar' => 'baz' }
27
+ @subject.store :foo, [:wu, :tang]
28
+
29
+ expect( @subject.store['foo'] ).to match_array [:wu, :tang]
30
+ end
31
+ end
32
+
33
+ context "when given no args" do
34
+ it "returns @local_sources instance var" do
35
+ @subject.instance_variable_set :"@local_sources", { foo: 'bar' }
36
+ expect( @subject.store ).to eq({ foo: 'bar' })
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#callbacks" do
42
+ before :each do
43
+ @subject = described_class.new instance_double("Middleman::Application"),
44
+ Middleman::CoreExtensions::Data::DATA_FILE_MATCHER
45
+ end
46
+
47
+ context "when given a name and proc" do
48
+ it "adds a callback at the given name" do
49
+ @subject.callbacks :foo, lambda { "bar" }
50
+ callback = @subject.instance_variable_get(:@callback_sources)['foo']
51
+
52
+ expect( callback.call ).to eq "bar"
53
+ end
54
+
55
+ it "overwrites previous keys if given the same key" do
56
+ @subject.callbacks :foo, lambda { "bar" }
57
+ @subject.callbacks :foo, lambda { "baz" }
58
+ callback = @subject.instance_variable_get(:@callback_sources)['foo']
59
+
60
+ expect( callback.call ).to eq "baz"
61
+ end
62
+ end
63
+
64
+ context "when given no args" do
65
+ it "returns @callback_sources instance var" do
66
+ @subject.instance_variable_set :"@callback_sources", { foo: 'bar' }
67
+ expect( @subject.callbacks ).to eq({ foo: 'bar' })
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "#data_for_path" do
73
+ before :each do
74
+ @subject = described_class.new instance_double("Middleman::Application"),
75
+ Middleman::CoreExtensions::Data::DATA_FILE_MATCHER
76
+ end
77
+
78
+ context "given path matches local data" do
79
+ it "returns hash for key" do
80
+ @subject.store :foo, { 'bar' => 'baz' }
81
+ expect( @subject.data_for_path(:foo) ).to eq({ 'bar' => 'baz' })
82
+ end
83
+
84
+ it "returns array for key" do
85
+ @subject.store :foo, [:bar, :baz]
86
+ expect( @subject.data_for_path(:foo) ).to match_array [:bar, :baz]
87
+ end
88
+ end
89
+
90
+ context "given path matches callback data" do
91
+ it "returns value of calback lambda" do
92
+ @subject.callbacks :foo, lambda { { 'bar' => 'baz' } }
93
+ @subject.callbacks :wu, lambda { [:tang, :clan] }
94
+
95
+ expect( @subject.data_for_path(:foo) ).to eq({ 'bar' => 'baz' })
96
+ expect( @subject.data_for_path(:wu) ).to match_array [:tang, :clan]
97
+ end
98
+ end
99
+
100
+ context "given path matches both sources" do
101
+ it "returns match from local data" do
102
+ @subject.store :foo, { 'local' => 'data' }
103
+ @subject.callbacks :foo, lambda { { 'callback' => 'data' } }
104
+
105
+ expect( @subject.data_for_path(:foo) ).to eq({ 'local' => 'data' })
106
+ end
107
+ end
108
+
109
+ context "given path matches no sources" do
110
+ it "returns nil" do
111
+ expect( @subject.data_for_path(:missing) ).to be_nil
112
+ end
113
+ end
114
+ end
115
+
10
116
  describe "#key?" do
11
117
 
12
118
  it "returns true if key included in local_data, local_sources, or callback_sources" do
@@ -38,4 +144,4 @@ describe Middleman::CoreExtensions::Data::DataStore do
38
144
 
39
145
  end
40
146
 
41
- end
147
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.1
4
+ version: 4.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Reynolds
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-02-03 00:00:00.000000000 Z
13
+ date: 2016-02-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -248,14 +248,14 @@ dependencies:
248
248
  requirements:
249
249
  - - "~>"
250
250
  - !ruby/object:Gem::Version
251
- version: 0.12.0
251
+ version: 0.13.0
252
252
  type: :runtime
253
253
  prerelease: false
254
254
  version_requirements: !ruby/object:Gem::Requirement
255
255
  requirements:
256
256
  - - "~>"
257
257
  - !ruby/object:Gem::Version
258
- version: 0.12.0
258
+ version: 0.13.0
259
259
  - !ruby/object:Gem::Dependency
260
260
  name: hashie
261
261
  requirement: !ruby/object:Gem::Requirement
@@ -276,14 +276,14 @@ dependencies:
276
276
  requirements:
277
277
  - - "~>"
278
278
  - !ruby/object:Gem::Version
279
- version: '2.0'
279
+ version: '3.0'
280
280
  type: :runtime
281
281
  prerelease: false
282
282
  version_requirements: !ruby/object:Gem::Requirement
283
283
  requirements:
284
284
  - - "~>"
285
285
  - !ruby/object:Gem::Version
286
- version: '2.0'
286
+ version: '3.0'
287
287
  - !ruby/object:Gem::Dependency
288
288
  name: backports
289
289
  requirement: !ruby/object:Gem::Requirement
@@ -390,6 +390,7 @@ files:
390
390
  - features/move_files.feature
391
391
  - features/multiple-sources.feature
392
392
  - features/nested_layouts.feature
393
+ - features/page-id.feature
393
394
  - features/paginate.feature
394
395
  - features/partials.feature
395
396
  - features/preview_changes.feature
@@ -446,6 +447,12 @@ files:
446
447
  - fixtures/asset-hash-host-app/source/subdir/index.html.erb
447
448
  - fixtures/asset-hash-minified-app/config.rb
448
449
  - fixtures/asset-hash-minified-app/source/javascripts/jquery.min.js
450
+ - fixtures/asset-hash-source-map/config.rb
451
+ - fixtures/asset-hash-source-map/lib/middleware.rb
452
+ - fixtures/asset-hash-source-map/source/index.html.erb
453
+ - fixtures/asset-hash-source-map/source/javascripts/application.js
454
+ - fixtures/asset-hash-source-map/source/javascripts/application.js.map
455
+ - fixtures/asset-hash-source-map/source/layout.erb
449
456
  - fixtures/asset-host-app/config.rb
450
457
  - fixtures/asset-host-app/source/.htaccess
451
458
  - fixtures/asset-host-app/source/asset_host.html.erb
@@ -644,6 +651,8 @@ files:
644
651
  - fixtures/external-helpers/lib/hello_helper.rb
645
652
  - fixtures/external-helpers/source/automatic.html.erb
646
653
  - fixtures/external-helpers/source/index.html.erb
654
+ - fixtures/external-pipeline-error/config.rb
655
+ - fixtures/external-pipeline-error/source/javascripts/file.js
647
656
  - fixtures/feature-params-app/config.rb
648
657
  - fixtures/feature-params-app/source/index.html.erb
649
658
  - fixtures/fonts-app/config.rb
@@ -1167,6 +1176,11 @@ files:
1167
1176
  - fixtures/page-helper-layout-block-app/source/layouts/layout.erb
1168
1177
  - fixtures/page-helper-layout-block-app/source/path/child.html.erb
1169
1178
  - fixtures/page-helper-layout-block-app/source/path/index.html.erb
1179
+ - fixtures/page-id-app/config.rb
1180
+ - fixtures/page-id-app/source/fm.html.erb
1181
+ - fixtures/page-id-app/source/index.html.erb
1182
+ - fixtures/page-id-app/source/overwrites/from-default.html.erb
1183
+ - fixtures/page-id-app/source/overwrites/from-frontmatter.html.erb
1170
1184
  - fixtures/paginate-app/config.rb
1171
1185
  - fixtures/paginate-app/source/archive/2011/index.html.erb
1172
1186
  - fixtures/paginate-app/source/blog/2011-01-01-test-article.html.markdown
@@ -1180,10 +1194,12 @@ files:
1180
1194
  - fixtures/paginate-app/source/tag.html.erb
1181
1195
  - fixtures/partial-chained_templates-app/config.rb
1182
1196
  - fixtures/partials-app/config.rb
1197
+ - fixtures/partials-app/source/_block.erb
1183
1198
  - fixtures/partials-app/source/_code_snippet.html
1184
1199
  - fixtures/partials-app/source/_locals.erb
1185
1200
  - fixtures/partials-app/source/_main.erb
1186
1201
  - fixtures/partials-app/source/_main.str
1202
+ - fixtures/partials-app/source/block.html.erb
1187
1203
  - fixtures/partials-app/source/images/tiger.svg
1188
1204
  - fixtures/partials-app/source/index.html.erb
1189
1205
  - fixtures/partials-app/source/locals.html.erb
@@ -1528,6 +1544,7 @@ test_files:
1528
1544
  - features/move_files.feature
1529
1545
  - features/multiple-sources.feature
1530
1546
  - features/nested_layouts.feature
1547
+ - features/page-id.feature
1531
1548
  - features/paginate.feature
1532
1549
  - features/partials.feature
1533
1550
  - features/preview_changes.feature
@@ -1584,6 +1601,12 @@ test_files:
1584
1601
  - fixtures/asset-hash-host-app/source/subdir/index.html.erb
1585
1602
  - fixtures/asset-hash-minified-app/config.rb
1586
1603
  - fixtures/asset-hash-minified-app/source/javascripts/jquery.min.js
1604
+ - fixtures/asset-hash-source-map/config.rb
1605
+ - fixtures/asset-hash-source-map/lib/middleware.rb
1606
+ - fixtures/asset-hash-source-map/source/index.html.erb
1607
+ - fixtures/asset-hash-source-map/source/javascripts/application.js
1608
+ - fixtures/asset-hash-source-map/source/javascripts/application.js.map
1609
+ - fixtures/asset-hash-source-map/source/layout.erb
1587
1610
  - fixtures/asset-host-app/config.rb
1588
1611
  - fixtures/asset-host-app/source/.htaccess
1589
1612
  - fixtures/asset-host-app/source/asset_host.html.erb
@@ -1782,6 +1805,8 @@ test_files:
1782
1805
  - fixtures/external-helpers/lib/hello_helper.rb
1783
1806
  - fixtures/external-helpers/source/automatic.html.erb
1784
1807
  - fixtures/external-helpers/source/index.html.erb
1808
+ - fixtures/external-pipeline-error/config.rb
1809
+ - fixtures/external-pipeline-error/source/javascripts/file.js
1785
1810
  - fixtures/feature-params-app/config.rb
1786
1811
  - fixtures/feature-params-app/source/index.html.erb
1787
1812
  - fixtures/fonts-app/config.rb
@@ -2305,6 +2330,11 @@ test_files:
2305
2330
  - fixtures/page-helper-layout-block-app/source/layouts/layout.erb
2306
2331
  - fixtures/page-helper-layout-block-app/source/path/child.html.erb
2307
2332
  - fixtures/page-helper-layout-block-app/source/path/index.html.erb
2333
+ - fixtures/page-id-app/config.rb
2334
+ - fixtures/page-id-app/source/fm.html.erb
2335
+ - fixtures/page-id-app/source/index.html.erb
2336
+ - fixtures/page-id-app/source/overwrites/from-default.html.erb
2337
+ - fixtures/page-id-app/source/overwrites/from-frontmatter.html.erb
2308
2338
  - fixtures/paginate-app/config.rb
2309
2339
  - fixtures/paginate-app/source/archive/2011/index.html.erb
2310
2340
  - fixtures/paginate-app/source/blog/2011-01-01-test-article.html.markdown
@@ -2318,10 +2348,12 @@ test_files:
2318
2348
  - fixtures/paginate-app/source/tag.html.erb
2319
2349
  - fixtures/partial-chained_templates-app/config.rb
2320
2350
  - fixtures/partials-app/config.rb
2351
+ - fixtures/partials-app/source/_block.erb
2321
2352
  - fixtures/partials-app/source/_code_snippet.html
2322
2353
  - fixtures/partials-app/source/_locals.erb
2323
2354
  - fixtures/partials-app/source/_main.erb
2324
2355
  - fixtures/partials-app/source/_main.str
2356
+ - fixtures/partials-app/source/block.html.erb
2325
2357
  - fixtures/partials-app/source/images/tiger.svg
2326
2358
  - fixtures/partials-app/source/index.html.erb
2327
2359
  - fixtures/partials-app/source/locals.html.erb