diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a3371f..b7bec4c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ master === +* Add `page_id` concept. Using the `id` key in frontmatter, proxy or page will set an ID on a resource which can be referenced by `url_for` and `link_to`. * Allow looking for `Gemfile` when setting up a project to fail gracefully. # 4.1.1 diff --git a/middleman-core/features/page-id.feature b/middleman-core/features/page-id.feature new file mode 100644 index 00000000..63dd6fad --- /dev/null +++ b/middleman-core/features/page-id.feature @@ -0,0 +1,26 @@ +Feature: Page IDs + + Scenario: link_to works with blocks (erb) + Given the Server is running at "page-id-app" + When I go to "/index.html" + Then I should see "I am: index.html" + And I should see "URL1: /fm.html" + And I should see "URL2: /2.html" + And I should see 'URL3: Hi' + And I should see 'URL4: Sym' + + When I go to "/fm.html" + Then I should see "I am: frontmatter" + + When I go to "/1.html" + Then I should see "I am: page1" + When I go to "/2.html" + Then I should see "I am: page2" + When I go to "/3.html" + Then I should see "I am: page3" + + When I go to "/overwrites/from-default.html" + Then I should see "I am: something-else" + + When I go to "/overwrites/from-frontmatter.html" + Then I should see "I am: from_frontmatter" diff --git a/middleman-core/fixtures/page-id-app/config.rb b/middleman-core/fixtures/page-id-app/config.rb new file mode 100644 index 00000000..d0475e7a --- /dev/null +++ b/middleman-core/fixtures/page-id-app/config.rb @@ -0,0 +1,5 @@ +%w(1 2 3).each do |n| + proxy "/#{n}.html", "/index.html", id: "page#{n}" +end + +page "/overwrites/*", id: :"something-else" diff --git a/middleman-core/fixtures/page-id-app/source/fm.html.erb b/middleman-core/fixtures/page-id-app/source/fm.html.erb new file mode 100644 index 00000000..4d6d0772 --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/fm.html.erb @@ -0,0 +1,5 @@ +--- +id: frontmatter +--- + +I am: <%= current_resource.page_id %> diff --git a/middleman-core/fixtures/page-id-app/source/index.html.erb b/middleman-core/fixtures/page-id-app/source/index.html.erb new file mode 100644 index 00000000..8f2997b6 --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/index.html.erb @@ -0,0 +1,6 @@ +I am: <%= current_resource.page_id %> + +URL1: <%= url_for "frontmatter" %> +URL2: <%= url_for "page2" %> +URL3: <%= link_to "Hi", "page3" %> +URL4: <%= link_to "Sym", :"something-else" %> diff --git a/middleman-core/fixtures/page-id-app/source/overwrites/from-default.html.erb b/middleman-core/fixtures/page-id-app/source/overwrites/from-default.html.erb new file mode 100644 index 00000000..a27800bd --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/overwrites/from-default.html.erb @@ -0,0 +1 @@ +I am: <%= current_resource.page_id %> diff --git a/middleman-core/fixtures/page-id-app/source/overwrites/from-frontmatter.html.erb b/middleman-core/fixtures/page-id-app/source/overwrites/from-frontmatter.html.erb new file mode 100644 index 00000000..194cf4c1 --- /dev/null +++ b/middleman-core/fixtures/page-id-app/source/overwrites/from-frontmatter.html.erb @@ -0,0 +1,5 @@ +--- +id: from_frontmatter +--- + +I am: <%= current_resource.page_id %> diff --git a/middleman-core/lib/middleman-core/core_extensions/routing.rb b/middleman-core/lib/middleman-core/core_extensions/routing.rb index 089b0486..b10fba53 100644 --- a/middleman-core/lib/middleman-core/core_extensions/routing.rb +++ b/middleman-core/lib/middleman-core/core_extensions/routing.rb @@ -52,10 +52,13 @@ module Middleman def page(path, opts={}) options = opts.dup + page_data = options.delete(:data) || {} + page_data[:id] = options.delete(:id) if options.key?(:id) + # Default layout metadata = { locals: options.delete(:locals) || {}, - page: options.delete(:data) || {}, + page: page_data, options: options } diff --git a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb index 33c0f9a5..b11e02eb 100644 --- a/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb +++ b/middleman-core/lib/middleman-core/sitemap/extensions/proxies.rb @@ -36,10 +36,13 @@ module Middleman md = metadata.dup should_ignore = md.delete(:ignore) + page_data = md.delete(:data) || {} + page_data[:id] = md.delete(:id) if md.key?(:id) + r = ProxyResource.new(app.sitemap, path, target) r.add_metadata( locals: md.delete(:locals) || {}, - page: md.delete(:data) || {}, + page: page_data || {}, options: md ) diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb index b7b0e063..22213c21 100644 --- a/middleman-core/lib/middleman-core/sitemap/resource.rb +++ b/middleman-core/lib/middleman-core/sitemap/resource.rb @@ -85,6 +85,11 @@ module Middleman file_descriptor && file_descriptor[:full_path].to_s end + Contract Or[Symbol, String] + def page_id + metadata[:page][:id] || destination_path + end + # Merge in new metadata specific to this resource. # @param [Hash] meta A metadata block with keys :options, :locals, :page. # Options are generally rendering/sitemap options diff --git a/middleman-core/lib/middleman-core/sitemap/store.rb b/middleman-core/lib/middleman-core/sitemap/store.rb index 41037309..a7ade5fc 100644 --- a/middleman-core/lib/middleman-core/sitemap/store.rb +++ b/middleman-core/lib/middleman-core/sitemap/store.rb @@ -149,6 +149,17 @@ module Middleman end end + # Find a resource given its page id + # @param [String] page_id The page id. + # @return [Middleman::Sitemap::Resource] + Contract Or[String, Symbol] => Maybe[IsA['Middleman::Sitemap::Resource']] + def find_resource_by_page_id(page_id) + @lock.synchronize do + ensure_resource_list_updated! + @_lookup_by_page_id[page_id.to_sym] + end + end + # Get the array of all resources # @param [Boolean] include_ignored Whether to include ignored resources # @return [Array] @@ -220,6 +231,7 @@ module Middleman @resources.each do |resource| @_lookup_by_path[resource.path] = resource @_lookup_by_destination_path[resource.destination_path] = resource + @_lookup_by_page_id[resource.page_id.to_sym] = resource end invalidate_resources_not_ignored_cache! @@ -239,6 +251,7 @@ module Middleman @lock.synchronize do @_lookup_by_path = {} @_lookup_by_destination_path = {} + @_lookup_by_page_id = {} end end diff --git a/middleman-core/lib/middleman-core/util/paths.rb b/middleman-core/lib/middleman-core/util/paths.rb index 61abec59..7c6ffc37 100644 --- a/middleman-core/lib/middleman-core/util/paths.rb +++ b/middleman-core/lib/middleman-core/util/paths.rb @@ -99,8 +99,13 @@ module Middleman # Given a source path (referenced either absolutely or relatively) # or a Resource, this will produce the nice URL configured for that # path, respecting :relative_links, directory indexes, etc. - Contract ::Middleman::Application, Or[String, ::Middleman::Sitemap::Resource], Hash => String + Contract ::Middleman::Application, Or[String, Symbol, ::Middleman::Sitemap::Resource], Hash => String def url_for(app, path_or_resource, options={}) + if path_or_resource.is_a?(String) || path_or_resource.is_a?(Symbol) + r = app.sitemap.find_resource_by_page_id(path_or_resource) + path_or_resource = r if r + end + # Handle Resources and other things which define their own url method url = if path_or_resource.respond_to?(:url) path_or_resource.url