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:
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)
- Use la etiqueta
sorted_for
lugar defor
con el parámetrosort_by:property
para ordenar por la propiedad dada. También puede agregarreversed
al igual que el originalfor
. - 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.