parent
84437a5052
commit
2a37caac83
|
@ -3,34 +3,39 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module Tags
|
module Tags
|
||||||
class PostComparer
|
class PostComparer
|
||||||
|
# Deprecated (soft; No interpreter warnings).
|
||||||
|
# To be removed in v5.0.
|
||||||
|
# Use private constant `POST_PATH_MATCHER` instead.
|
||||||
MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!.freeze
|
MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!.freeze
|
||||||
|
|
||||||
|
POST_PATH_MATCHER = %r!\A(.+/)*?(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)\z!.freeze
|
||||||
|
private_constant :POST_PATH_MATCHER
|
||||||
|
|
||||||
attr_reader :path, :date, :slug, :name
|
attr_reader :path, :date, :slug, :name
|
||||||
|
|
||||||
def initialize(name)
|
def initialize(name)
|
||||||
@name = name
|
@name = name
|
||||||
|
|
||||||
all, @path, @date, @slug = *name.sub(%r!^/!, "").match(MATCHER)
|
all, @path, @date, @slug = *name.delete_prefix("/").match(POST_PATH_MATCHER)
|
||||||
unless all
|
unless all
|
||||||
raise Jekyll::Errors::InvalidPostNameError,
|
raise Jekyll::Errors::InvalidPostNameError,
|
||||||
"'#{name}' does not contain valid date and/or title."
|
"'#{name}' does not contain valid date and/or title."
|
||||||
end
|
end
|
||||||
|
|
||||||
basename_pattern = "#{date}-#{Regexp.escape(slug)}\\.[^.]+"
|
basename_pattern = "#{date}-#{Regexp.escape(slug)}\\.[^.]+"
|
||||||
@name_regex = %r!^_posts/#{path}#{basename_pattern}|^#{path}_posts/?#{basename_pattern}!
|
@name_regex = %r!\A_posts/#{path}#{basename_pattern}|\A#{path}_posts/?#{basename_pattern}!
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_date
|
def post_date
|
||||||
@post_date ||= Utils.parse_date(
|
@post_date ||= Utils.parse_date(date, "Path '#{name}' does not contain valid date.")
|
||||||
date,
|
|
||||||
"'#{date}' does not contain valid date and/or title."
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns `MatchData` or `nil`.
|
||||||
def ==(other)
|
def ==(other)
|
||||||
other.relative_path.match(@name_regex)
|
other.relative_path.match(@name_regex)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Deprecated. To be removed in v5.0.
|
||||||
def deprecated_equality(other)
|
def deprecated_equality(other)
|
||||||
slug == post_slug(other) &&
|
slug == post_slug(other) &&
|
||||||
post_date.year == other.date.year &&
|
post_date.year == other.date.year &&
|
||||||
|
@ -40,9 +45,9 @@ module Jekyll
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Construct the directory-aware post slug for a Jekyll::Post
|
# Construct the directory-aware post slug for a Jekyll::Document object.
|
||||||
#
|
#
|
||||||
# other - the Jekyll::Post
|
# other - the Jekyll::Document object.
|
||||||
#
|
#
|
||||||
# Returns the post slug with the subdirectory (relative to _posts)
|
# Returns the post slug with the subdirectory (relative to _posts)
|
||||||
def post_slug(other)
|
def post_slug(other)
|
||||||
|
@ -58,47 +63,66 @@ module Jekyll
|
||||||
class PostUrl < Liquid::Tag
|
class PostUrl < Liquid::Tag
|
||||||
include Jekyll::Filters::URLFilters
|
include Jekyll::Filters::URLFilters
|
||||||
|
|
||||||
def initialize(tag_name, post, tokens)
|
def initialize(tag_name, markup, tokens)
|
||||||
super
|
super
|
||||||
@orig_post = post.strip
|
@markup = markup.strip
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@post = PostComparer.new(@orig_post)
|
@post_comparer = PostComparer.new(@markup)
|
||||||
rescue StandardError => e
|
rescue StandardError
|
||||||
raise Jekyll::Errors::PostURLError, <<~MSG
|
raise_markup_parse_error
|
||||||
Could not parse name of post "#{@orig_post}" in tag 'post_url'.
|
|
||||||
Make sure the post exists and the name is correct.
|
|
||||||
#{e.class}: #{e.message}
|
|
||||||
MSG
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Deprecated instance_variables.
|
||||||
|
# To be removed in Jekyll v5.0.
|
||||||
|
@orig_post = @markup
|
||||||
|
@post = @post_comparer
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(context)
|
def render(context)
|
||||||
@context = context
|
@context = context
|
||||||
site = context.registers[:site]
|
site = context.registers[:site]
|
||||||
|
|
||||||
site.posts.docs.each do |document|
|
# First pass-through.
|
||||||
return relative_url(document) if @post == document
|
site.posts.docs.each do |post|
|
||||||
|
return relative_url(post) if @post_comparer == post
|
||||||
end
|
end
|
||||||
|
|
||||||
# New matching method did not match, fall back to old method
|
# First pass-through did not yield the requested post. Search again using legacy matching
|
||||||
# with deprecation warning if this matches
|
# method. Log deprecation warning if a post is detected via this round.
|
||||||
|
site.posts.docs.each do |post|
|
||||||
|
next unless @post_comparer.deprecated_equality(post)
|
||||||
|
|
||||||
site.posts.docs.each do |document|
|
log_legacy_usage_deprecation
|
||||||
next unless @post.deprecated_equality document
|
return relative_url(post)
|
||||||
|
|
||||||
Jekyll::Deprecator.deprecation_message(
|
|
||||||
"A call to '{% post_url #{@post.name} %}' did not match a post using the new " \
|
|
||||||
"matching method of checking name (path-date-slug) equality. Please make sure " \
|
|
||||||
"that you change this tag to match the post's name exactly."
|
|
||||||
)
|
|
||||||
return relative_url(document)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
raise_post_not_found_error
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def raise_markup_parse_error
|
||||||
raise Jekyll::Errors::PostURLError, <<~MSG
|
raise Jekyll::Errors::PostURLError, <<~MSG
|
||||||
Could not find post "#{@orig_post}" in tag 'post_url'.
|
Could not parse name of post #{@markup.inspect} in tag 'post_url'.
|
||||||
Make sure the post exists and the name is correct.
|
Make sure the correct name is given to the tag.
|
||||||
MSG
|
MSG
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def raise_post_not_found_error
|
||||||
|
raise Jekyll::Errors::PostURLError, <<~MSG
|
||||||
|
Could not find post #{@markup.inspect} in tag 'post_url'.
|
||||||
|
Make sure the post exists and the correct name is given to the tag.
|
||||||
|
MSG
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_legacy_usage_deprecation
|
||||||
|
Jekyll::Deprecator.deprecation_message(
|
||||||
|
"A call to '{% post_url #{@markup} %}' did not match a post using the new matching " \
|
||||||
|
"method of checking name (path-date-slug) equality. Please make sure that you change " \
|
||||||
|
"this tag to match the post's name exactly."
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue