Merge pull request #944 from x3ro/permalink-special-characters
WIP - Improve permalink generation for URLs with special characters
This commit is contained in:
commit
0d890e4b70
|
@ -33,6 +33,7 @@ require 'jekyll/deprecator'
|
||||||
require 'jekyll/configuration'
|
require 'jekyll/configuration'
|
||||||
require 'jekyll/site'
|
require 'jekyll/site'
|
||||||
require 'jekyll/convertible'
|
require 'jekyll/convertible'
|
||||||
|
require 'jekyll/url'
|
||||||
require 'jekyll/layout'
|
require 'jekyll/layout'
|
||||||
require 'jekyll/page'
|
require 'jekyll/page'
|
||||||
require 'jekyll/post'
|
require 'jekyll/post'
|
||||||
|
|
|
@ -37,7 +37,12 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the String permalink or nil if none has been set.
|
# Returns the String permalink or nil if none has been set.
|
||||||
def permalink
|
def permalink
|
||||||
self.data && self.data['permalink']
|
return nil if self.data.nil? || self.data['permalink'].nil?
|
||||||
|
if site.config['relative_permalinks']
|
||||||
|
File.join(@dir, self.data['permalink'])
|
||||||
|
else
|
||||||
|
self.data['permalink']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# The template of the permalink.
|
# The template of the permalink.
|
||||||
|
@ -61,29 +66,21 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the String url.
|
# Returns the String url.
|
||||||
def url
|
def url
|
||||||
return @url if @url
|
@url ||= URL.new({
|
||||||
|
:template => template,
|
||||||
url = if permalink
|
:placeholders => url_placeholders,
|
||||||
if site.config['relative_permalinks']
|
:permalink => permalink
|
||||||
File.join(@dir, permalink)
|
}).to_s
|
||||||
else
|
|
||||||
permalink
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
|
# Returns a hash of URL placeholder names (as symbols) mapping to the
|
||||||
|
# desired placeholder replacements. For details see "url.rb"
|
||||||
|
def url_placeholders
|
||||||
{
|
{
|
||||||
"path" => @dir,
|
:path => @dir,
|
||||||
"basename" => self.basename,
|
:basename => self.basename,
|
||||||
"output_ext" => self.output_ext,
|
:output_ext => self.output_ext
|
||||||
}.inject(template) { |result, token|
|
}
|
||||||
result.gsub(/:#{token.first}/, token.last)
|
|
||||||
}.gsub(/\/\//, "/")
|
|
||||||
end
|
|
||||||
|
|
||||||
# sanitize url
|
|
||||||
@url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
|
|
||||||
@url += "/" if url =~ /\/$/
|
|
||||||
@url.gsub!(/\A([^\/])/, '/\1')
|
|
||||||
@url
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Extract information from the page filename.
|
# Extract information from the page filename.
|
||||||
|
|
|
@ -195,36 +195,31 @@ module Jekyll
|
||||||
end
|
end
|
||||||
|
|
||||||
# The generated relative url of this post.
|
# The generated relative url of this post.
|
||||||
# e.g. /2008/11/05/my-awesome-post.html
|
|
||||||
#
|
#
|
||||||
# Returns the String URL.
|
# Returns the String url.
|
||||||
def url
|
def url
|
||||||
return @url if @url
|
@url ||= URL.new({
|
||||||
|
:template => template,
|
||||||
url = if permalink
|
:placeholders => url_placeholders,
|
||||||
permalink
|
:permalink => permalink
|
||||||
else
|
}).to_s
|
||||||
{
|
|
||||||
"year" => date.strftime("%Y"),
|
|
||||||
"month" => date.strftime("%m"),
|
|
||||||
"day" => date.strftime("%d"),
|
|
||||||
"title" => CGI.escape(slug),
|
|
||||||
"i_day" => date.strftime("%d").to_i.to_s,
|
|
||||||
"i_month" => date.strftime("%m").to_i.to_s,
|
|
||||||
"categories" => categories.map { |c| URI.escape(c.to_s) }.join('/'),
|
|
||||||
"short_month" => date.strftime("%b"),
|
|
||||||
"y_day" => date.strftime("%j"),
|
|
||||||
"output_ext" => self.output_ext
|
|
||||||
}.inject(template) { |result, token|
|
|
||||||
result.gsub(/:#{Regexp.escape token.first}/, token.last)
|
|
||||||
}.gsub(/\/\//, "/")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# sanitize url
|
# Returns a hash of URL placeholder names (as symbols) mapping to the
|
||||||
@url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
|
# desired placeholder replacements. For details see "url.rb"
|
||||||
@url += "/" if url =~ /\/$/
|
def url_placeholders
|
||||||
@url.gsub!(/\A([^\/])/, '/\1')
|
{
|
||||||
@url
|
:year => date.strftime("%Y"),
|
||||||
|
:month => date.strftime("%m"),
|
||||||
|
:day => date.strftime("%d"),
|
||||||
|
:title => CGI.escape(slug),
|
||||||
|
:i_day => date.strftime("%d").to_i.to_s,
|
||||||
|
:i_month => date.strftime("%m").to_i.to_s,
|
||||||
|
:categories => (categories || []).map { |c| URI.escape(c.to_s) }.join('/'),
|
||||||
|
:short_month => date.strftime("%b"),
|
||||||
|
:y_day => date.strftime("%j"),
|
||||||
|
:output_ext => self.output_ext
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# The UID for this post (useful in feeds).
|
# The UID for this post (useful in feeds).
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Public: Methods that generate a URL for a resource such as a Post or a Page.
|
||||||
|
#
|
||||||
|
# Examples
|
||||||
|
#
|
||||||
|
# URL.new({
|
||||||
|
# :template => /:categories/:title.html",
|
||||||
|
# :placeholders => {:categories => "ruby", :title => "something"}
|
||||||
|
# }).to_s
|
||||||
|
#
|
||||||
|
module Jekyll
|
||||||
|
class URL
|
||||||
|
|
||||||
|
# options - One of :permalink or :template must be supplied.
|
||||||
|
# :template - The String used as template for URL generation,
|
||||||
|
# for example "/:path/:basename:output_ext", where
|
||||||
|
# a placeholder is prefixed with a colon.
|
||||||
|
# :placeholders - A hash containing the placeholders which will be
|
||||||
|
# replaced when used inside the template. E.g.
|
||||||
|
# { "year" => Time.now.strftime("%Y") } would replace
|
||||||
|
# the placeholder ":year" with the current year.
|
||||||
|
# :permalink - If supplied, no URL will be generated from the
|
||||||
|
# template. Instead, the given permalink will be
|
||||||
|
# used as URL.
|
||||||
|
def initialize(options)
|
||||||
|
@template = options[:template]
|
||||||
|
@placeholders = options[:placeholders] || {}
|
||||||
|
@permalink = options[:permalink]
|
||||||
|
|
||||||
|
if (@template || @permalink).nil?
|
||||||
|
raise ArgumentError, "One of :template or :permalink must be supplied."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# The generated relative URL of the resource
|
||||||
|
#
|
||||||
|
# Returns the String URL
|
||||||
|
def to_s
|
||||||
|
sanitize_url(@permalink || generate_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Internal: Generate the URL by replacing all placeholders with their
|
||||||
|
# respective values
|
||||||
|
#
|
||||||
|
# Returns the _unsanitizied_ String URL
|
||||||
|
def generate_url
|
||||||
|
@placeholders.inject(@template) do |result, token|
|
||||||
|
result.gsub(/:#{token.first}/, token.last)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns a sanitized String URL
|
||||||
|
def sanitize_url(in_url)
|
||||||
|
# Remove all double slashes
|
||||||
|
url = in_url.gsub(/\/\//, "/")
|
||||||
|
|
||||||
|
# Remove every URL segment that consists solely of dots
|
||||||
|
url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
|
||||||
|
|
||||||
|
# Append a trailing slash to the URL if the unsanitized URL had one
|
||||||
|
url += "/" if in_url =~ /\/$/
|
||||||
|
|
||||||
|
# Always add a leading slash
|
||||||
|
url.gsub!(/\A([^\/])/, '/\1')
|
||||||
|
url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
require 'helper'
|
||||||
|
|
||||||
|
class TestURL < Test::Unit::TestCase
|
||||||
|
context "The URL class" do
|
||||||
|
|
||||||
|
should "throw an exception if neither permalink or template is specified" do
|
||||||
|
assert_raises ArgumentError do
|
||||||
|
URL.new(:placeholders => {})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should "replace placeholders in templates" do
|
||||||
|
assert_equal "/foo/bar", URL.new(
|
||||||
|
:template => "/:x/:y",
|
||||||
|
:placeholders => {:x => "foo", :y => "bar"}
|
||||||
|
).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
should "return permalink if given" do
|
||||||
|
assert_equal "/le/perma/link", URL.new(
|
||||||
|
:template => "/:x/:y",
|
||||||
|
:placeholders => {:x => "foo", :y => "bar"},
|
||||||
|
:permalink => "/le/perma/link"
|
||||||
|
).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue