How do I detect the current page in a Jekyll tag plugin?
I have a Jekyll (Liquid) block plugin and I'd like to detect what the current page is. I see that a context is passed into render, and that I can retrieve the current site object as context.registers[:site]. However, attempts to get the current page as con开发者_高级运维text.registers[:page] fail.
The problem I'm trying to solve is to create a simple block plugin to detect if the current page is the page mentioned in the tag, and highlight it.
Any tips would be greatly appreciated.
Thanks!
Turns out we can also do this like:
def render(context)
page_url = context.environments.first["page"]["url"]
Which is not obvious but it doesn't require patching the code.
context['page']
seems to return a hash with most of the properties of the current page, including url
and path
so the actual page object can be retrieved with
context.registers[:site].pages.detect { |p| p.path==context['page']['path'] }
I don't think there's a good way of doing it with Jekyll as-is. convertible.rb
only passes the site
object to Liquid, which doesn't contain any page-specific data.
I'd suggest just editing convertible.rb
to pass in the data you need, submitting a pull request to the main project to pull in your changes, and using your fork locally to generate your site. Hooray for open source!
The following trivial patch works for me locally against Jekyll 0.11.0, making a page hash available in Liquid as context.registers[:page]
(note: it's a pre-converted hash at this point, so you'd access context.registers[:page]['url']
, not context.registers[:page].url
):
diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb
index d33abc5..a674ef5 100644
--- a/lib/jekyll/convertible.rb
+++ b/lib/jekyll/convertible.rb
@@ -69,7 +69,7 @@ module Jekyll
#
# Returns nothing.
def do_layout(payload, layouts)
- info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } }
+ info = { :filters => [Jekyll::Filters], :registers => { :site => self.site, :page => payload['page'] } }
# render and transform content (this becomes the final content of the object)
payload["pygments_prefix"] = converter.pygments_prefix
Hope that helps!
This issue always arises when making menu that needs to display the current page a little differently. Here is a Jekyll plugin I wrote that does that for Bootstrap 5:
# Copyright 2020 Michael Slinn
#
# Apache 2 License
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and limitations under the License.
module Jekyll
# Generates a Bootstrap 5 nav item.
#
# Usage: {% nav_item icon link text %}
# Quotes are not used
# icon is assumed to be within the /assets/icons directory
# link must reference a local web page, do not preface with http: or https:
# text can be one or more words
#
# Example:
# {% nav_item house-door.svg /index.html Welcome! %}
class Bootstrap5NavItem < Liquid::Tag
def initialize(href, command_line, tokens)
super
@active = '"'
tokens = command_line.strip.split(" ")
@icon = tokens.shift
@link = tokens.shift
@text = tokens.join(" ").strip
end
def render(context)
relative_link = @link.delete_prefix('/')
page = context['page']['path'] # relative to site root
#puts "******* page=#{page}; @link=#{@link}"
if page == relative_link then
%Q(<li>
<a class="nav-link active" aria-current="page" href="#">
<img class="feather" src="/assets/icons/#{@icon}">
#{@text}
</a>
</li>)
else
%Q(<li>
<a class="nav-link" href="#{@link}">
<img class="feather" src="/assets/icons/#{@icon}">
#{@text}
</a>
</li>)
end
end
end
end
Liquid::Template.register_tag('nav_item', Jekyll::Bootstrap5NavItem)
精彩评论