diff --git a/Gemfile b/Gemfile
index 54dc7b36..db4043a0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,6 +11,11 @@ gem 'rspec', '~> 3.0', require: false
gem 'cucumber', '~> 2.0', require: false
gem 'addressable', '~> 2.4.0', require: false
+# Pry tools
+gem 'pry'
+gem 'pry-stack_explorer'
+gem 'pry-rescue'
+
# Optional middleman dependencies, included for tests
gem 'haml', '>= 4.0.5', require: false
gem 'sassc', '~> 1.8', require: false
diff --git a/middleman-core/features/page-id.feature b/middleman-core/features/page-id.feature
index 63dd6fad..74d08cb5 100644
--- a/middleman-core/features/page-id.feature
+++ b/middleman-core/features/page-id.feature
@@ -3,14 +3,60 @@ 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"
+ Then I should see "I am: index"
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'
+ And I should see 'URL5: Imp'
+ And I should see 'URL6: Foldern'
+ And I should see 'URL7: Feed'
When I go to "/fm.html"
Then I should see "I am: frontmatter"
+ When I go to "/implicit.html"
+ Then I should see "I am: implicit"
+ When I go to "/feed.xml"
+ Then I should see "I am: feed.xml"
+ When I go to "/folder/foldern.html"
+ Then I should see "I am: folder/foldern"
+
+ 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"
+
+ Scenario: Override page ID derivation with a proc
+ Given a fixture app "page-id-app"
+ And app "page-id-app" is using config "proc"
+ And the Server is running at "page-id-app"
+
+ When I go to "/index.html"
+ Then I should see "I am: index.html-foo"
+ 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'
+ And I should see 'URL8: Imp'
+ And I should see 'URL9: Foldern'
+ And I should see 'URL10: Feed'
+
+ When I go to "/fm.html"
+ Then I should see "I am: frontmatter"
+ When I go to "/implicit.html"
+ Then I should see "I am: implicit.html-foo"
+ When I go to "/feed.xml"
+ Then I should see "I am: feed.xml-foo"
+ When I go to "/folder/foldern.html"
+ Then I should see "I am: folder/foldern.html-foo"
When I go to "/1.html"
Then I should see "I am: page1"
diff --git a/middleman-core/fixtures/page-id-app/config-proc.rb b/middleman-core/fixtures/page-id-app/config-proc.rb
new file mode 100644
index 00000000..03070f0e
--- /dev/null
+++ b/middleman-core/fixtures/page-id-app/config-proc.rb
@@ -0,0 +1,7 @@
+%w(1 2 3).each do |n|
+ proxy "/#{n}.html", "/index.html", id: "page#{n}"
+end
+
+page "/overwrites/*", id: :"something-else"
+
+config[:page_id_generator] = ->(path){ path + "-foo" }
diff --git a/middleman-core/fixtures/page-id-app/source/feed.xml.erb b/middleman-core/fixtures/page-id-app/source/feed.xml.erb
new file mode 100644
index 00000000..a27800bd
--- /dev/null
+++ b/middleman-core/fixtures/page-id-app/source/feed.xml.erb
@@ -0,0 +1 @@
+I am: <%= current_resource.page_id %>
diff --git a/middleman-core/fixtures/page-id-app/source/folder/foldern.html.erb b/middleman-core/fixtures/page-id-app/source/folder/foldern.html.erb
new file mode 100644
index 00000000..a27800bd
--- /dev/null
+++ b/middleman-core/fixtures/page-id-app/source/folder/foldern.html.erb
@@ -0,0 +1 @@
+I am: <%= current_resource.page_id %>
diff --git a/middleman-core/fixtures/page-id-app/source/implicit.html.erb b/middleman-core/fixtures/page-id-app/source/implicit.html.erb
new file mode 100644
index 00000000..a27800bd
--- /dev/null
+++ b/middleman-core/fixtures/page-id-app/source/implicit.html.erb
@@ -0,0 +1 @@
+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
index 8f2997b6..6060bc3f 100644
--- a/middleman-core/fixtures/page-id-app/source/index.html.erb
+++ b/middleman-core/fixtures/page-id-app/source/index.html.erb
@@ -4,3 +4,11 @@ URL1: <%= url_for "frontmatter" %>
URL2: <%= url_for "page2" %>
URL3: <%= link_to "Hi", "page3" %>
URL4: <%= link_to "Sym", :"something-else" %>
+URL5: <%= link_to "Imp", :implicit %>
+URL6: <%= link_to "Foldern", "folder/foldern" %>
+URL7: <%= link_to "Feed", "feed.xml" %>
+
+<%# If custom proc %>
+URL8: <%= link_to "Imp", "implicit.html-foo" %>
+URL9: <%= link_to "Foldern", "folder/foldern.html-foo" %>
+URL10: <%= link_to "Feed", "feed.xml-foo" %>
diff --git a/middleman-core/lib/middleman-core/sitemap/resource.rb b/middleman-core/lib/middleman-core/sitemap/resource.rb
index 9ff97478..f3619873 100644
--- a/middleman-core/lib/middleman-core/sitemap/resource.rb
+++ b/middleman-core/lib/middleman-core/sitemap/resource.rb
@@ -87,7 +87,7 @@ module Middleman
Contract Or[Symbol, String, Fixnum]
def page_id
- metadata[:page][:id] || destination_path
+ metadata[:page][:id] || make_implicit_page_id(destination_path)
end
# Merge in new metadata specific to this resource.
@@ -208,6 +208,30 @@ module Middleman
"#<#{self.class} path=#{@path}>"
end
alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s
+
+ protected
+
+ # Makes a page id based on path (when not otherwise given)
+ #
+ # Removes .html extension and potential leading slashes or dots
+ # eg. "foo/bar/baz.foo.html" => "foo/bar/baz.foo"
+ Contract String => String
+ def make_implicit_page_id(path)
+ @id ||= begin
+ if prok = @app.config[:page_id_generator]
+ return prok.call(path)
+ end
+
+ basename = if ext == ".html"
+ File.basename(path, ext)
+ else
+ File.basename(path)
+ end
+
+ # Remove leading dot or slash if present
+ File.join(File.dirname(path), basename).gsub(/^\.?\//, '')
+ end
+ end
end
class StringResource < Resource
diff --git a/middleman-core/lib/middleman-core/util/paths.rb b/middleman-core/lib/middleman-core/util/paths.rb
index dfa60f15..2e229392 100644
--- a/middleman-core/lib/middleman-core/util/paths.rb
+++ b/middleman-core/lib/middleman-core/util/paths.rb
@@ -152,7 +152,8 @@ module Middleman
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
+
+ path_or_resource = r ? r : path_or_resource.to_s
end
# Handle Resources and other things which define their own url method