How do I detect the current page in a Jekyll tag plugin?
Asked Answered
B

4

7

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 context.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!

Bastogne answered 20/9, 2011 at 0:6 Comment(0)
B
17

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.

Bastogne answered 5/10, 2011 at 19:36 Comment(3)
That's brilliant. And completely non-intuitive. Thanks for figuring this out.Hosey
But what if you needed to grab the context object at initialize?Cirrostratus
context.environments.first["page"]["path"] can be expressed more succinctly as context['page']['path']Bate
W
3

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'] }
Wergild answered 24/12, 2014 at 11:40 Comment(0)
G
1

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!

Grandiose answered 20/9, 2011 at 6:27 Comment(0)
B
1

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)
Bate answered 24/12, 2020 at 20:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.