带Jekyll和Liquid的已排序导航菜单

带Jekyll和Liquid的已排序导航菜单,jekyll,liquid,Jekyll,Liquid,我正在用Jekyll/Liquid构建一个静态站点(没有博客)。我希望它有一个自动生成的导航菜单,列出所有现有页面,并突出显示当前页面。这些项目应按特定顺序添加到菜单中。因此,我在页面的YAML中定义了一个weight属性: --- layout : default title : Some title weight : 5 --- 导航菜单的构造如下所示: <ul> {% for p in site.pages | sort:weight %} <li>

我正在用Jekyll/Liquid构建一个静态站点(没有博客)。我希望它有一个自动生成的导航菜单,列出所有现有页面,并突出显示当前页面。这些项目应按特定顺序添加到菜单中。因此,我在页面的YAML中定义了一个
weight
属性:

---
layout : default
title  : Some title
weight : 5
---
导航菜单的构造如下所示:

<ul>
  {% for p in site.pages | sort:weight %}
    <li>
      <a {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">
        {{ p.title }}
      </a>
    </li>
  {% endfor %}
</ul>
    {site.pages中p的百分比|排序:权重%}
  • {%endfor%}

这将创建指向所有现有页面的链接,但它们未排序,
排序
过滤器似乎被忽略。显然,我做错了什么,但我不知道是什么。

您唯一的选择似乎是使用双循环

<ul>
{% for weight in (1..10) %}
  {% for p in site.pages %}
    {% if p.weight == weight %}
      <li>
        <a {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">
          {{ p.title }}
        </a>
      </li>
    {% endif %}
  {% endfor %}
{% endfor %}
</ul>
    {(1..10)%中的重量百分比} {site.pages%中p的%s} {%如果p.weight==weight%}
  • {%endif%} {%endfor%} {%endfor%}

虽然它很难看,但它应该有用。如果您还有没有权重的页面,则必须在当前内部循环之前/之后添加一个额外的内部循环,只需执行
{%p.weight%}

我使用生成器解决了这个问题。生成器遍历页面,获取导航数据,对其进行排序,并将其推回到站点配置。液体可以从那里检索数据并显示出来。它还负责隐藏和显示项目

考虑这个页面片段:

---
navigation:
  title: Page name
  weight: 100
  show: true
---
content.
{% for p in site.navigation %}
<li> 
    <a  {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">{{ p.navigation.title }}</a>
</li>
{% endfor %}
导航由以下液体片段呈现:

---
navigation:
  title: Page name
  weight: 100
  show: true
---
content.
{% for p in site.navigation %}
<li> 
    <a  {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">{{ p.navigation.title }}</a>
</li>
{% endfor %}
{%p在site.navigation%}
  • {%endfor%}
    将以下代码放入_plugins文件夹中的文件中:

    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
    
    模块杰基尔
    类SiteNavigation排序最简单的解决方案是在页面的文件名前面加上如下索引:

    <ul>
      {% sorted_for p in site.pages sort_by:weight %}
        <li>
          <a {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">
            {{ p.title }}
          </a>
        </li>
      {% endsorted_for %}
    </ul>
    
    00-home.html 01-services.html 02-page3.html

    页面按文件名排序。但是,现在您将有丑陋的URL

    在yaml front matter部分中,可以通过设置permalink变量覆盖生成的url

    例如:

    ---
    layout: default
    permalink: index.html
    ---
    

    我已经编写了一个简单的Jekyll插件来解决这个问题:

  • 将.rb的
    sorted_复制到您的Jekyll项目的
    \u plugins
    子目录:

    module Jekyll
      class SortedForTag < Liquid::For
        def render(context)
          sorted_collection = context[@collection_name].dup
          sorted_collection.sort_by! { |i| i.to_liquid[@attributes['sort_by']] }
    
          sorted_collection_name = "#{@collection_name}_sorted".sub('.', '_')
          context[sorted_collection_name] = sorted_collection
          @collection_name = sorted_collection_name
    
          super
        end
    
        def end_tag
          'endsorted_for'
        end
      end
    end
    
    Liquid::Template.register_tag('sorted_for', Jekyll::SortedForTag)
    

    以下解决方案适用于Github(不需要插件):

    另外,我想变得聪明,添加自定义属性只是为了排序。不幸的是,自定义属性无法作为Page类上的方法访问,因此无法用于排序:

    {% assign sorted_pages = site.pages | sort:"weight" %} #bummer
    
    简易解决方案:

    分配一个已排序的
    站点数组。页面
    首先在数组上运行for循环

    您的代码如下所示:

    {% 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 %}
    

    上面@kikito的解决方案也对我有效。我只是添加了几行,以从导航中删除无重量的页面,并消除空白:

    <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>
    
    
    
      {(1..5)%中的重量百分比} {%除非p.weight%} {site.pages%中p的%s} {%如果p.weight==weight%} {%如果p.url==page.url%}
    • {{p.title}}
    • {%else%}
    • {%endif%} {%endif%} {%endfor%} {%end除非%} {%endfor%}

    自Jekyll 2.2.0以来,您可以按任何对象属性对对象数组进行排序。您现在可以执行以下操作:

    {% assign pages = site.pages | sort:"weight"  %}
    <ul>
      {% for p in pages %}
        <li>
          <a {% if p.url == page.url %}class="active"{% endif %} href="{{ p.url }}">
            {{ p.title }}
          </a>
        </li>
      {% endfor %}
    </ul>
    
    {%assign pages=site.pages |排序:“权重”%}
    
      {%页中的p为%}
    • {%endfor%}
    与@kikito解决方案相比,可以节省大量的构建时间

    编辑必须将排序属性指定为整数
    权重:10
    ,而不是字符串
    权重:“10”


    将排序属性指定为字符串将以字符串排序结束,如“1、10、11、2、20,…”

    如果您尝试按重量和标签排序,并将数字限制为10,则下面的代码可以执行此操作:

    {% assign counter = '0' %}
    {% assign pages = site.pages | sort: "weight"  %}
    {% for page in pages %}
    {% for tag in page.tags %}
    {% if tag == "Getting Started" and counter < '9' %}
    {% capture counter %}{{ counter | plus:'1' }}{% endcapture %}
    <li><a href="{{ page.permalink | prepend: site.baseurl }}">{{page.title}}</a></li>
    {% endif %}
    {% endfor %}
    {% endfor %} 
    
    {%assign counter='0%}
    {%assign pages=site.pages |排序:“权重”%}
    {第%页中的第%页}
    {page.tags%中的标记的%s}
    {%if标记==“Getting Started”且计数器<'9'%}
    {%capture counter%}{{counter}加上:'1'}{%endcapture%}
    
  • {%endif%} {%endfor%} {%endfor%}
    我可以通过Jekyll/Liquid获得以下代码,以满足您对产品类别的要求:

    • 创建指向所有现有页面的链接
    • 按重量分类(也适用于按类别分类)
    • 突出显示当前页面
    最上面还显示了帖子的数量。所有这些都是在没有任何插件的情况下完成的

    <ul class="topics">
    {% capture tags %}
        {% for tag in site.categories %}
            {{ tag[0] }}
        {% endfor %}
    {% endcapture %}
    {% assign sortedtags = tags | split:' ' | sort %}
        {% for tag in sortedtags %}
        <li class="topic-header"><b>{{ tag }} ({{ site.categories[tag] | size }} topics)</b>
            <ul class='subnavlist'>
            {% assign posts = site.categories[tag] | sort:"weight" %}
            {% for post in posts %}
                <li class='recipe {% if post.url == page.url %}active{% endif %}'>
                <a href="/{{ site.github.project_title }}{{ post.url }}">{{ post.title }}</a>
                </li>
            {% endfor %}
            </ul>
        </li>
        {% endfor %}
    </ul>
    
      {%capture tags%} {site.categories%中标记的%s} {{tag[0]} {%endfor%} {%endcapture%} {%assign sortedtags=tags | split:''排序%} {sortedtags%中的标记的%s}
    • {{tag}}({{site.categories[tag]| size}}主题)