published on 01.07.2018

Motivasyon

Oldukça uzun, bir o kadar da gerekliliği tartışılır kod parçasını paylaşmak üzereyim. Baştan söyleyelim, biraz döngüler dönecek if statementlar kontrol edilecek. Bunlara bağlı olarak, eğer blogunuzda çok post varsa build time kötü derecede etkilenecek. Ne kadar etkisi olur, 11 postluk blogta şu an için yorum yapamıyorum. Gerçi, duruma göre sadeleştirmeniz bazı loopları kaldırmanız mümkün. Uzatmayalım, işe koyulalım.

Kodu adım adım açıklamadan önce, algoritmayı özetleyelim.

Durum:

  • Birçok koleksiyonumuz var.

Eğer koleksiyon yapısını bilmiyorsanız ve umrunuzda değilse devam edebilirsiniz, konumuzla doğrudan ilgisi yok. Koleyksiyonlar hakkında henüz yazmadım ama okumak isteyenler için:

  • Her post’a ait bir ya da daha fazla etiket var. (post.tags dizisi)
    • Örneğin, bu post için, post.tags = [jekyll, liquid, pagination, tag-filter]
  • Birden fazla post aynı etiketle etikenlemiş olabilir.
    • Örneğin bunun gibi 7 post daha var “jekyll” etiketine sahip.
  • Herhangi iki postun birden fazla etiketi ortak olabilir.
    • Örneğin, hem jekyll, hem liquid etiketlerine sahip 4 ayrı post mevcut.

Jekyll’da “posts” koleksiyonlardan biridir ve “post” o koleksiyondan bir üyeye karşılık gelir. Ancak bu yazıda “post” derken yazılan bir metinden (bir url) bahsediyorum, teknik anlamda herhangir koleksiyonun herhangi bir üyesinden bahsediyorum.

Amaç:

  • Tüm postlar arasından (all_posts) mevcut sayfanın etiketlerinden (page.tags) en az birine sahip olan postları elde etmek.

Çözüm

    {% assign constant_limit = 4 %}
    {% assign count = 0 %}

    {% for collection in site.collections %}
        {% assign name = collection.label %}
        {% assign all_posts = all_posts | concat: site[name] %}
    {% endfor %}
    
    {% assign all_posts = all_posts | sort: date | reverse %}

    {% for item in all_posts %}
        {% if item.url == page.url %}
            {% continue %}
        {% endif %}

        {% if count == constant_limit %}
           {% break %}
        {% endif %}

        {% for tag in page.tags %}
            {% if item.tags contains tag %}
                <li style="list-style: square"><a href="{{item.url}}">{{item.title}}</a></li>
                {% assign count = count | plus: 1%}
                {% break %}
            {% endif %}
        {% endfor %}
    {% endfor %}
    
    {% if count < constant_limit %}
        {% for item in all_posts %}
        
            {% if item.url == page.url %}
                {% continue %}
            {% endif %}

            <li style="list-style: square"><a href="{{item.url}}">{{item.title}}</a></li>
            {% assign count = count | plus: 1%}
            
            {% if count == constant_limit %}
                {% break %}
            {% endif %}

        {% endfor %}
    {% endif %}

Tüm kod yukarıdaki gibi, şimdi adım adım açıklayalım buradaki mantığı.

Tüm Koleksiyonları Birleştir

Öncelikle, tüm koleksiyonları bir tek dizide birleştirmeliyiz. Eğer koleksiyon yapısını kullanmıyorsanız, bu adımı geçip all_posts yazan yerlere site.posts yazabilir ve kendinize göre aşağıdaki kodu uyarlayabilirsiniz.

{% for collection in site.collections %}
    {% assign name = collection.label %}
    {% assign all_posts = all_posts | concat: site[name] %}
{% endfor %}

Döngü Mantığı

İç içe iki döngü olacak, all_posts’da herbir post için page.tags’de herbir etiket için. Eğer post etiketi içeriyorsa yazdıracağız.

{% for item in all_posts %}
    {% for tag in page.tags %}
        {% if item.tags contains tag %}
             <li><a href="{{item.url}}">{{item.title}}</a></li>
             {% break %}
        {% endif %}
    {% endfor %}
{% endfor %}

Burada break olmadığı durumda, herbir ortak etiket için aynı yazıyı tekrar listeleyecektir döngü içinde. break ile bir kere yazdırdıktan sonra döngüden çıkmak istiyoruz. Böylece tekrara düşmeyeceğiz.

Mevcut Sayfayı Dikkate Al

Mevcut sayfa da kendisiyle ortak etiketlere (tamamen aynı) sahip olduğu için eklenecektir. {% if item.url != page.url %} koşulunu ekleyerek ya da all_posts döngüsünde aşağıdaki koşuk eklenerek

{% if item.url == page.url %}
    {% continue %}
{% endif %}

bu problemi kolayca çözebiliriz.

Bir Limit Olmalı

Yüzlerce postunuz olduğunu düşünün, okuyucuyu bütün arşivinizi tavsiye ederek korkutmak istemezsiniz. Ayrıca break statementlar ile döngüyü kısaltatabiliriz.

{% if count == constant_limit %}
    {% break %}
{% endif %}

Ya Limitin Altında Kalırsak ?

Sonuçta bu da mümkün. Hatta hiç yazmadığınız bir konu hakkında yazıyorsanız o kadar işten sonra çıktı alamamınız da mümkün. Bunun için ben son yazılan postlardan sırasıyla eklemeyi düşündüm. Farklı çözümler de üretilebilir.

Kod kendini açıklar nitelikte. Yukarıdaki gibi, aynı sayfayı eklememek, mevcut sayfayı eklememek ve limiti geçmemek için kontroller yapıyoruz. Çıkabildiğimiz zaman döngüden çıkıyoruz, sonuna kadar gitmiyoruz.

{% if count < constant_limit %}
    {% for item in all_posts %}
        {% if item.url == page.url %}
            {% continue %}
        {% endif %}
        <li style="list-style: square"><a href="{{item.url}}">{{item.title}}</a></li>
        {% assign count = count | plus: 1%}
        {% if count == constant_limit %}
            {% break %}
        {% endif %}
    {% endfor %}
{% endif %}

Kesinlikle overkill ama liquid syntaxına biraz daha alışmamı sağladı.

You are reading the 11st of 19 episodes in Jekyll.
Published on 01.07.2018 by Mert Bakır with commit de81d3f.
jekyll
#jekyll #liquid #pagination #static-site
Next episode:
Etiketlere Göre İlgili Yazılar - 2
published on 03.07.2018

Bu yazıda daha önce yazdığım Etiketlere Göre İlgili Yazılar konusundaki yapıyı eleştirip iyileştireceğiz. En azından başlangınçta öyle düşünüyordum. Kısaca hatırlayalım, ne yaptığımızı: […] Amaç: Tüm postlar arasından (all_posts) mevcut sayfanın etiketlerinden (page.tags) en az birine sahip …

published on 20.01.2019

Tag Cloud. Bloglarda karşımıza çıkan klişe yapı. Wordpress kullananlar automatic generate ediyorlardır, Jekyll için ise belki vardır plugin ama biz kendimiz oluşturacağız. Öncelikle tag-cloud.html adı altında bir include dosyası oluşturalım. Böylece daha sonra arşiv sayfasında, tag ya da post …

published on 20.01.2019

Bir postun altına, sıradaki N adet postun linkini nasıl ekleriz? Pagination, ama previous ile next yerine next N post. N, sizin seçeceğiniz bir sayı. Pagination adlı yazıda, önceki ve sonraki yazıları nasıl elde edeceğimizi anlatmıştım. Bir de uzunca ve build time kötü etkileyecek ama teoride …

published on 10.07.2022

Previously, I’ve published a blog post about deploying static content on heroku with basic authentication. The main purpose was to get basic auth for a freely hosted static website. In that post, we hosted the source code on GitLab and configured a CI/CD pipeline to render the static content …

published on 28.05.2022

Each git commit has a field called Author which consists ‘user.name’ and ‘user.email’. We usually set these variables once, after installing git, with git config --global so that each repo gets the variables from the global definition. We can also set them locally for a …

published on 25.05.2022

In this post, I’ll first walk through hosting static content with basic authentication. Then, we’ll look into deploying to Heroku using GitLab Pipelines, more specifically deploying a certain sub-directory within the project instead of pushing the whole project. Also, I’ll share …

published on 17.04.2022
edited on 15.07.2022

Önceki bölümde, markdown formatını LaTeX formatına dönüştürmek için kullanılan Pandoc yazılımından bahsetmiştik. Şimdi konuyu bir adım daha ileri taşıyıp ve bookdown’a geçiyoruz. Bookdown; Rmarkdown kullanarak teknik dökümanlar, kitaplar yazabilmemizi sağlayan, Yihui Xie tarafından yazılmış …

published on 10.04.2022

I’ve been using WSL-2 on Windows for over a year. It’s very useful because some Python packages are just a headache to install on Windows. Also, docker. It’s just better on Linux. Yet, WSL-2 can also be problematic. I remember trying a dual-boot setup when things just went way too …

published on 03.03.2022

In this post, I’ll share how to install geopandas and some other gis related packages on Windows. If you are on Mac or Linux you can probably just pip install those without any issue. I usually had to do a google search every time I wanted to install these packages on Windows environment. Of …