type page new matter images front files custom jekyll liquid

page - jekyll where



Menú de navegación ordenado con Jekyll y Liquid (10)

Estoy construyendo un sitio estático (sin blog) con Jekyll / Liquid. Quiero que tenga un menú de navegación generado automáticamente que enumera todas las páginas existentes y resalta la página actual. Los artículos deben agregarse al menú en un orden particular. Por lo tanto, defino una propiedad de weight en las páginas ''YAML:

--- layout : default title : Some title weight : 5 ---

El menú de navegación se construye de la siguiente manera:

<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>

Esto crea enlaces a todas las páginas existentes, pero no están ordenadas, el filtro de sort parece ignorado. Obviamente, estoy haciendo algo mal, pero no puedo entender qué.


A continuación, la solución funciona en Github (no requiere un complemento):

{% assign sorted_pages = site.pages | sort:"name" %} {% for node in sorted_pages %} <li><a href="{{node.url}}">{{node.title}}</a></li> {% endfor %}

El fragmento anterior ordena las páginas por nombre de archivo (el atributo de name en el objeto Página se deriva del nombre del archivo). 00-index.md nombre de los archivos para que coincidieran con mi orden deseada: 00-index.md , 01-about.md - y ¡ 01-about.md ! Las páginas están ordenadas.

Una sorpresa es que esos prefijos numéricos terminan en las URL, lo que parece incómodo para la mayoría de las páginas y es un problema real con 00-index.html. Permalinknks al rescate:

--- layout: default title: News permalink: "index.html" ---

PD: quería ser inteligente y agregar atributos personalizados solo para ordenar. Desafortunadamente, los atributos personalizados no son accesibles como métodos en la clase de página y, por lo tanto, no se pueden usar para ordenar:

{% assign sorted_pages = site.pages | sort:"weight" %} #bummer


Desde Jekyll 2.2.0 puede ordenar una matriz de objetos por cualquier propiedad de objeto. Ahora puede hacer:

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

Y ahorre mucho tiempo de compilación en comparación con la solución de @kikito.

editar : DEBE asignar su propiedad de clasificación como un weight: 10 entero weight: 10 y no como un weight: "10" cadena weight: "10" .

La asignación de propiedades de clasificación como cadena terminará en una secuencia de cadenas como "1, 10, 11, 2, 20, ..."


Escribí un plugin simple de Jekyll para resolver este problema:

  1. Copie sorted_for.rb del subdirectorio https://gist.github.com/3765912 a _plugins de su proyecto Jekyll:

    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)

  2. Use la etiqueta sorted_for lugar de for con el parámetro sort_by:property para ordenar por la propiedad dada. También puede agregar reversed al igual que el original for .
  3. No te olvides de usar la etiqueta de finalización diferente endsorted_for .

En tu caso, el uso se ve así:

<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>


La solución anterior de @kikito también funcionó para mí. Acabo de agregar algunas líneas para eliminar páginas sin peso de la navegación y para eliminar el espacio en blanco:

<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>


La solución más simple sería ponerle un prefijo al nombre de archivo de sus páginas con un índice como este:

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

Las páginas se ordenan por nombre de archivo. Sin embargo, ahora tendrás urls feas.

En las secciones principales de yaml puede anular la url generada estableciendo la variable de enlace permanente.

Por ejemplo:

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


Lo he resuelto usando un generador. El generador itera por las páginas, obtiene los datos de navegación, los ordena y los devuelve a la configuración del sitio. Desde allí Liquid puede recuperar los datos y mostrarlos. También se ocupa de ocultar y mostrar elementos.

Considera este fragmento de página:

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

La navegación se representa con este fragmento de líquido:

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

Coloque el siguiente código en un archivo en su carpeta _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

He pasado bastante tiempo averiguando esto ya que soy bastante nuevo para Jekyll y Ruby, por lo que sería genial si alguien puede mejorar en esto.


Puedo obtener el siguiente código que funciona con Jekyll / Liquid para que coincida con su requisito con la categoría:

  • crea enlaces a todas las páginas existentes,
  • ordenados por peso (funciona también en la clasificación por categoría),
  • resalta la página actual.

Encima de ellos muestra también el número de publicaciones. Todo se hace sin ningún complemento.

<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>

Compruébalo en acción en nuestra página de red . Puede hacer clic en una publicación para resaltar la navegación, así como un enlace determinado para llevarlo a la página de origen donde se asigna su peso.


Si está tratando de clasificar por peso y por etiqueta y limitar el número a 10, aquí hay un código para hacerlo:

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


Solución fácil:

Asigne primero una matriz ordenada de site.pages luego ejecute un ciclo for para la matriz.

Tu código se verá así:

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

Esto funciona en mi barra de _include que es simplemente:

<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>


Su única opción parece estar utilizando un bucle doble.

<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>

Feo como es, debería funcionar. Si también tiene páginas sin un peso, tendrá que incluir un bucle interno adicional simplemente haciendo {% unless p.weight %} antes / después de la interna actual.