Sorted navigation menu with Jekyll and Liquid

后端 未结 10 1964
清酒与你
清酒与你 2020-12-07 11:57

I\'m constructing a static site (no blog) with Jekyll/Liquid. I want it to have an auto-generated navigation menu that lists all existing pages and highlight the current pag

相关标签:
10条回答
  • 2020-12-07 12:48

    I've solved this using a generator. The generator iterates over pages, getting the navigation data, sorting it and pushing it back to the site config. From there Liquid can retrieve the data and display it. It also takes care of hiding and showing items.

    Consider this page fragment:

    ---
    navigation:
      title: Page name
      weight: 100
      show: true
    ---
    content.
    

    The navigation is rendered with this Liquid fragment:

    {% for p in site.navigation %}
    <li> 
        <a  {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">{{ p.navigation.title }}</a>
    </li>
    {% endfor %}
    

    Put the following code in a file in your _plugins folder:

    module Jekyll
    
      class SiteNavigation < Jekyll::Generator
        safe true
        priority :lowest
    
        def generate(site)
    
            # First remove all invisible items (default: nil = show in nav)
            sorted = []
            site.pages.each do |page|
              sorted << page if page.data["navigation"]["show"] != false
            end
    
            # Then sort em according to weight
            sorted = sorted.sort{ |a,b| a.data["navigation"]["weight"] <=> b.data["navigation"]["weight"] } 
    
            # Debug info.
            puts "Sorted resulting navigation:  (use site.config['sorted_navigation']) "
            sorted.each do |p|
              puts p.inspect 
            end
    
            # Access this in Liquid using: site.navigation
            site.config["navigation"] = sorted
        end
      end
    end
    

    I've spent quite a while figuring this out since I'm quite new to Jekyll and Ruby, so it would be great if anyone can improve on this.

    0 讨论(0)
  • 2020-12-07 12:50

    The solution above by @kikito also worked for me. I just added a few lines to remove pages without weight from the navigation and to get rid of white space:

    <nav>
      <ul>
        {% for weight in (1..5) %}
          {% unless p.weight %}
            {% for p in site.pages %}
              {% if p.weight == weight %}
                {% if p.url == page.url %}
                  <li>{{ p.title }}</li>
                {% else %}
                  <li><a href="{{ p.url }}" title="{{ p.title }}">{{ p.title }}</a></li>
                {% endif %}
              {% endif %}
            {% endfor %}
          {% endunless %}
        {% endfor %}
      </ul>
    </nav>
    
    0 讨论(0)
  • 2020-12-07 12:57

    Easy solution:

    Assign a sorted array of site.pages first then run a for loop on the array.

    Your code will look like:

    {% assign links = site.pages | sort: 'weight' %}
    {% for p in links %}
      <li>
        <a {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">
          {{ p.title }}
        </a>
      </li>
    {% endfor %}
    

    This works in my navbar _include which is simply:

    <section id="navbar">
        <nav>
            {% assign tabs = site.pages | sort: 'weight' %}
            {% for p in tabs %}
                <span class="navitem"><a href="{{ p.url }}">{{ p.title }}</a></span>
            {% endfor %}
        </nav>
    </section>
    
    0 讨论(0)
  • 2020-12-07 12:58

    The simplest solution would be to prefix the filename of your pages with an index like this:

    00-home.html 01-services.html 02-page3.html

    Pages are be ordered by filename. However, now you'll have ugly urls.

    In your yaml front matter sections you can override the generated url by setting the permalink variable.

    For instance:

    ---
    layout: default
    permalink: index.html
    ---
    
    0 讨论(0)
提交回复
热议问题