Reputation: 2533
I'm trying to write a custom tag plugin for Jekyll that will output a hierarchical navigation tree of all the pages (not posts) on the site. I'm basically wanting a bunch nested <ul>
's with links (with the page title as the link text) to the pages with the current page noted by a certain CSS class.
I'm very inexperienced with ruby. I'm a PHP guy.
I figured I'd start just by trying to iterate through all the pages and output a one-dimensional list just to make sure I could at least do that. Here's what I have so far:
module Jekyll
class NavTree < Liquid::Tag
def initialize(tag_name, text, tokens)
super
end
def render(context)
site = context.registers[:site]
output = '<ul>'
site.pages.each do |page|
output += '<li><a href="'+page.url+'">'+page.title+'</a></li>'
end
output += '<ul>'
output
end
end
end
Liquid::Template.register_tag('nav_tree', Jekyll::NavTree)
And I'm inserting it into my liquid template via {% nav_tree %}
.
The problem is that the page
variable in the code above doesn't have all the data that you'd expect. page.title
is undefined and page.url
is just the basename with a forward slash in front of it (e.g. for /a/b/c.html
, it's just giving me /c.html
).
What am I doing wrong?
Side note: I already tried doing this with pure Liquid markup, and I eventually gave up. I can easily iterate through site.pages
just fine with Liquid, but I couldn't figure out a way to appropriately nest the lists.
Upvotes: 6
Views: 2508
Reputation: 683
Recently I faced a similar problem where the error "cannot convert nill into string" is just blowing my head. My config.yml file holds a line something like this " baseurl: /paradocs/jekyll/out/ " now thats for my local for a server i need to make that beseurl empty and the error starts to appear in build time so finally i have to made " baseurl: / " .. And that's did my job.
Upvotes: 0
Reputation: 56
Try:
module Jekyll
# Add accessor for directory
class Page
attr_reader :dir
end
class NavTree < Liquid::Tag
def initialize(tag_name, text, tokens)
super
end
def render(context)
site = context.registers[:site]
output = '<ul>'
site.pages.each do |page|
output += '<li><a href="'+page.dir+page.url+'">'+(page.data['title'] || page.url) +'</a></li>'
end
output += '<ul>'
output
end
end
end
Liquid::Template.register_tag('nav_tree', Jekyll::NavTree)
Upvotes: 4
Reputation: 191
page.title
is not always defined (example: atom.xml
). You have to check if it is defined. Then you can take page.name
or not process the entry...
def render(context)
site = context.registers[:site]
output = '<ul>'
site.pages.each do |page|
unless page.data['title'].nil?
t = page.data['title']
else
t = page.name
end
output += "<li><a href="'+page.dir+page.url+'">'+t+'</a></li>"
end
output += '<ul>'
output
end
Upvotes: 4