middleman-core 4.1.1 → 4.1.2

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