feat: Allowing post_url tag to receive liquid variables (#9776)

Merge pull request 9776
This commit is contained in:
Jefferson Quesado 2025-06-05 11:51:04 -03:00 committed by GitHub
parent e2e1ee8eaa
commit 79a8e16f22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 73 additions and 12 deletions

View File

@ -188,3 +188,25 @@ You can also use this tag to create a link to a post in Markdown as follows:
[Name of Link]({% post_url 2010-07-21-name-of-post %}) [Name of Link]({% post_url 2010-07-21-name-of-post %})
``` ```
{% endraw %} {% endraw %}
Now lets say you have a [datafile]({{ '/docs/datafiles/' | relative_url }}) `_data/cool_posts.yaml` used to keep track
of certain posts that you intend to be listed as say *Cool Posts*:
```yaml
- title: "An Awesome Post"
slug: "2010-07-21-name-of-post"
- title: "Another Awesome Post"
slug: "2016-07-26-name-of-post"
```
You may list such posts using the `post_url` tag as well (from {%- include docs_version_badge.html version="4.5.0" -%}):
{% raw %}
```liquid
Cool posts:
{%- for cool_post in site.data.cool_posts %}
- [{{ cool_post.title }}]({% post_url {{ cool_post.slug }} %})
{%- endfor %}
```
{% endraw %}

View File

@ -157,3 +157,37 @@ Feature: PostUrl Tag
But the _site directory should exist But the _site directory should exist
And I should see "<p><a href=\"/cats%20and%20dogs/2019/02/04/hello-world.html\">Post 1</a></p>" in "_site/index.html" And I should see "<p><a href=\"/cats%20and%20dogs/2019/02/04/hello-world.html\">Post 1</a></p>" in "_site/index.html"
And I should see "<p><a href=\"/2019/02/05/hello-again.html\">Post 2</a></p>" in "_site/index.html" And I should see "<p><a href=\"/2019/02/05/hello-again.html\">Post 2</a></p>" in "_site/index.html"
Scenario: Calling for a post via a liquid variable
Given I have a _posts directory
And I have the following post:
| title | date | content |
| Hello World | 2019-02-04 | Lorem ipsum dolor |
And I have an "index.md" page with content:
"""
{% assign value='2019-02-04-hello-world' %}
[Welcome]({% post_url {{ value }} %})
"""
When I run jekyll build
Then I should get a zero exit status
And the _site directory should exist
And I should see "<p><a href=\"/2019/02/04/hello-world.html\">Welcome</a></p>" in "_site/index.html"
Scenario: Calling for posts via a liquid variable in a for tag
Given I have a _posts directory
And I have the following post:
| title | date | content |
| Hello World | 2019-02-04 | Lorem ipsum dolor |
| We Meet Again | 2019-02-05 | Alpha beta gamma |
And I have an "index.md" page with content:
"""
{% assign posts = '2019-02-04-hello-world;2019-02-05-we-meet-again' | split: ';' %}
{%- for slug in posts -%}
[{{ slug }}]({% post_url {{ slug }} %})
{%- endfor %}
"""
When I run jekyll build
Then I should get a zero exit status
And the _site directory should exist
And I should see "<a href=\"/2019/02/04/hello-world.html\">2019-02-04-hello-world</a>" in "_site/index.html"
And I should see "<a href=\"/2019/02/05/we-meet-again.html\">2019-02-05-we-meet-again</a>" in "_site/index.html"

View File

@ -66,23 +66,28 @@ module Jekyll
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, tokens)
super super
@markup = markup.strip @markup = markup.strip
@template = Liquid::Template.parse(@markup) if @markup.include?("{{")
begin
@post_comparer = PostComparer.new(@markup)
rescue StandardError
raise_markup_parse_error
end
# Deprecated instance_variables. # Deprecated instance_variables.
# To be removed in Jekyll v5.0. # To be removed in Jekyll v5.0.
@orig_post = @markup @orig_post = @markup
@post = @post_comparer @post = nil
end end
def render(context) def render(context)
@context = context @context = context
@resolved_markup = @template&.render(@context) || @markup
site = context.registers[:site] site = context.registers[:site]
begin
@post_comparer = PostComparer.new(@resolved_markup)
rescue StandardError
raise_markup_parse_error
end
# For backwards compatibility only; deprecated instance_variable.
# To be removed in Jekyll v5.0.
@post = @post_comparer
# First pass-through. # First pass-through.
site.posts.docs.each do |post| site.posts.docs.each do |post|
return relative_url(post) if @post_comparer == post return relative_url(post) if @post_comparer == post
@ -104,23 +109,23 @@ module Jekyll
def raise_markup_parse_error def raise_markup_parse_error
raise Jekyll::Errors::PostURLError, <<~MSG raise Jekyll::Errors::PostURLError, <<~MSG
Could not parse name of post #{@markup.inspect} in tag 'post_url'. Could not parse name of post #{@resolved_markup.inspect} in tag 'post_url'.
Make sure the correct name is given to the tag. Make sure the correct name is given to the tag.
MSG MSG
end end
def raise_post_not_found_error def raise_post_not_found_error
raise Jekyll::Errors::PostURLError, <<~MSG raise Jekyll::Errors::PostURLError, <<~MSG
Could not find post #{@markup.inspect} in tag 'post_url'. Could not find post #{@resolved_markup.inspect} in tag 'post_url'.
Make sure the post exists and the correct name is given to the tag. Make sure the post exists and the correct name is given to the tag.
MSG MSG
end end
def log_legacy_usage_deprecation def log_legacy_usage_deprecation
Jekyll::Deprecator.deprecation_message( Jekyll::Deprecator.deprecation_message(
"A call to '{% post_url #{@markup} %}' did not match a post using the new matching " \ "A call to '{% post_url #{@resolved_markup} %}' did not match a post using the new " \
"method of checking name (path-date-slug) equality. Please make sure that you change " \ "matching method of checking name (path-date-slug) equality. Please make sure that " \
"this tag to match the post's name exactly." "you change this tag to match the post's name exactly."
) )
end end
end end