Add page_id concept

This commit is contained in:
Thomas Reynolds 2016-02-22 11:17:21 -08:00
parent b695f6da1e
commit edb1a53060
12 changed files with 81 additions and 3 deletions

View file

@ -1,6 +1,7 @@
master 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. * Allow looking for `Gemfile` when setting up a project to fail gracefully.
# 4.1.1 # 4.1.1

View file

@ -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: <a href="/3.html">Hi</a>'
And I should see 'URL4: <a href="/overwrites/from-default.html">Sym</a>'
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"

View file

@ -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"

View file

@ -0,0 +1,5 @@
---
id: frontmatter
---
I am: <%= current_resource.page_id %>

View file

@ -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" %>

View file

@ -0,0 +1 @@
I am: <%= current_resource.page_id %>

View file

@ -0,0 +1,5 @@
---
id: from_frontmatter
---
I am: <%= current_resource.page_id %>

View file

@ -52,10 +52,13 @@ module Middleman
def page(path, opts={}) def page(path, opts={})
options = opts.dup options = opts.dup
page_data = options.delete(:data) || {}
page_data[:id] = options.delete(:id) if options.key?(:id)
# Default layout # Default layout
metadata = { metadata = {
locals: options.delete(:locals) || {}, locals: options.delete(:locals) || {},
page: options.delete(:data) || {}, page: page_data,
options: options options: options
} }

View file

@ -36,10 +36,13 @@ module Middleman
md = metadata.dup md = metadata.dup
should_ignore = md.delete(:ignore) 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 = ProxyResource.new(app.sitemap, path, target)
r.add_metadata( r.add_metadata(
locals: md.delete(:locals) || {}, locals: md.delete(:locals) || {},
page: md.delete(:data) || {}, page: page_data || {},
options: md options: md
) )

View file

@ -85,6 +85,11 @@ module Middleman
file_descriptor && file_descriptor[:full_path].to_s file_descriptor && file_descriptor[:full_path].to_s
end end
Contract Or[Symbol, String]
def page_id
metadata[:page][:id] || destination_path
end
# Merge in new metadata specific to this resource. # Merge in new metadata specific to this resource.
# @param [Hash] meta A metadata block with keys :options, :locals, :page. # @param [Hash] meta A metadata block with keys :options, :locals, :page.
# Options are generally rendering/sitemap options # Options are generally rendering/sitemap options

View file

@ -149,6 +149,17 @@ module Middleman
end end
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 # Get the array of all resources
# @param [Boolean] include_ignored Whether to include ignored resources # @param [Boolean] include_ignored Whether to include ignored resources
# @return [Array<Middleman::Sitemap::Resource>] # @return [Array<Middleman::Sitemap::Resource>]
@ -220,6 +231,7 @@ module Middleman
@resources.each do |resource| @resources.each do |resource|
@_lookup_by_path[resource.path] = resource @_lookup_by_path[resource.path] = resource
@_lookup_by_destination_path[resource.destination_path] = resource @_lookup_by_destination_path[resource.destination_path] = resource
@_lookup_by_page_id[resource.page_id.to_sym] = resource
end end
invalidate_resources_not_ignored_cache! invalidate_resources_not_ignored_cache!
@ -239,6 +251,7 @@ module Middleman
@lock.synchronize do @lock.synchronize do
@_lookup_by_path = {} @_lookup_by_path = {}
@_lookup_by_destination_path = {} @_lookup_by_destination_path = {}
@_lookup_by_page_id = {}
end end
end end

View file

@ -99,8 +99,13 @@ module Middleman
# Given a source path (referenced either absolutely or relatively) # Given a source path (referenced either absolutely or relatively)
# or a Resource, this will produce the nice URL configured for that # or a Resource, this will produce the nice URL configured for that
# path, respecting :relative_links, directory indexes, etc. # 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={}) 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 # Handle Resources and other things which define their own url method
url = if path_or_resource.respond_to?(:url) url = if path_or_resource.respond_to?(:url)
path_or_resource.url path_or_resource.url