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 olan postları elde etmek.

Bu doğrultuda yazıları tarihe göre sıralayıp en az bir ortak etikete sahip olanları “ilgili yazılar” başlığı altında sıralamıştık.

Pekâlâ, bu yaklaşımın kusuru nedir?

  • Zamana göre sıraladığımız için, ortak en az bir etiket olması koşuluyla, her zaman son yazılan 4 post listelenecek. Diğer bir deyişle, yeni yazılara öncelik vermiş oluyoruz, önceden yazdığımız yazıları ikinci plana atıyoruz.

Belki de en mantıklı çözüm, aynı koleksiyon içerisindeki yazıları listelemek olacaktır. Böylece hem gereksiz yere diğer koleksiyonları birleştirip iş yükünü arttırmamış oluruz hem de zaten aynı koleksiyondaki yazılar birbirleriyle ilgili oldukları için istediğimize yakın bir sonuç almış oluruz.

Benzer yazıyı Pagination Filtered by Category başlığı altında önceden paylaşmıştım. Aynı koleksiyonda bir önceki ve bir sonraki yazıyı verecek kod ise basitçe aşağıdaki gibi yazılabilir.

{% assign this_collection = site[page.collection] | sort: 'date'%}
  {% for item in this_collection %}
  {% if item.url == page.url %}
    {% if item.previous.url %}
        <a href="{{item.previous.url}}">{{item.previous.title}}</a>
    {% endif %}
    {% if item.next.url %}
        <a href="{{item.next.url}}">{{item.next.title}}</a>
    {% endif %}
  {% endif %}
{% endfor %}

Yine de bununla yetinmeyeceğiz! Gelelim, önceki yazıdaki kodu nasıl iyileştireceğimize. Örnek vererek açıklayalım.

(0) Okuduğumuz sayfa [jekyll, liquid, pagination, tags] etiketlerine sahip.

(1) Bu koleksiyondaki bir önceki yazı, tamamen aynı [jekyll, liquid, pagination, tags] etiketlere sahip.

(2) Bir başka sayfa ise [jekyll, mathjax, LaTeX] etiketlerine sahip.

Mevcut durumda, bizim için (1) ve (2), (0) ile ilişkili sayfa çünkü en azından bir adet etiket ortak. Kaç adet etiketin ortak olmasına dikkat etmiyoruz.

İstediğim yapı ise herbir post için 0 ile 1 arasında bir ilişki değeri üretecek ve o değere göre sıralayacak, tarihe göre değil! Örneğin, (1) numaralı yazı 4 etikete de sahip olduğu için ilişki değeri = 1 olacaktır. (2) ise sadece 1 etikete sahip olduğu için ilişki değeri = 0.25 olacaktır.

Evet, istediğim yapı bu. Peki ama sadece liquid syntaxı kullanılarak bu yapıyı kurmak mümkün mü? Değişkenlerim nesne değiller. Direkt item’ı saklamak istemedim. İstediğim yapı için hem item.title hem item.url hem de ilişki değeri’ni saklamalıyım ve üçü birbirine senkronize bir şekilde ilişki değerine göre sıralanmalı.

Teknik anlamda kolay olması gereken bu olay, burada imkansıza yakındır. Aklıma ilk gelen yapı, dictionary olmuştu. Tabii ki aradığımı bulamadım. Daha sonra kendi 2 boyutlu arrayimi oluşturayım dedim. Yine mümkün olmadığını gördüm. Üç ayrı array’i aynı döngü içinde döndürmekten başka çare ne yazık ki bulamadım.

Önceki yazı için büyük olasılıkla build time’ı kötü etkileyeceğini uzun ve karışık bir kod olduğunu söylemiştim; ancak asıl bu yazıda paylaşacağım kod bu niteliklere sahip. Kendileri uzun, karışık ve kesinlikle gereksiz ama yine de yazdım. Saçma bir inattı aslında, ilk günden beri çok basit, eksik ve ilkel bulduğum bu syntax ile bir nevi mücadeleye girdim bugün. Sonunda istediğim sonucu elde ettim.

Eğer okumadıysanız, Liquid: Dizi Operasyonları ve Hileler adlı yazıma kesinlikle bakmalısınız. Çünkü aşağıda acayip olaylar olacak.

 {% assign constant_limit = 4 %}

    {% assign num_tags = page.tags | size | times: 1.0 %}
    {% assign tag_value = 1 | divided_by: num_tags %}

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

    {% assign url_array = '' | split: '' %}
    {% assign val_array = '' | split: '' %}
    {% assign title_array = '' | split: '' %}

    {% for item in all_posts %}

    {% assign rel_value = 0 %}
    {% assign arraysize = val_array | size %}

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

    {% for tag in page.tags %}
        {% if item.tags contains tag %}
            {% assign rel_value = rel_value | plus: tag_value %}
        {% endif %}
    {% endfor %}

    {% if rel_value != 0 %}
        {% assign free_slot = constant_limit | minus: arraysize %}

        {% if free_slot > 0 %}
            {% assign tempval = rel_value %}
            {% assign tempval = tempval | split: 'ğ' %}
            {% assign val_array = val_array | concat: tempval %}

            {% assign tempurl = item.url %}
            {% assign tempurl = tempurl | split: 'ğ' %}
            {% assign url_array = url_array | concat: tempurl %}

            {% assign temptitle = item.title %}
            {% assign temptitle = temptitle | split: 'ğçş' %}
            {% assign title_array = title_array | concat: temptitle %}

        {% else %}

        {% assign index = -1 %}

        {% for rv in val_array %}
        {% assign rv_int = rv | times: 1 %}
            {% if rel_value > rv_int %}
                {% assign index = forloop.index0 %}
            {% endif %}
        {% endfor %}

        {% if index != -1 %}

        {% assign tempval_array = '' | split: '' %}
        {% assign tempurl_array = '' | split: '' %}
        {% assign temptitle_array = '' | split: '' %}

        {% assign limit = index | minus: 1%}

        {% for i in (0..limit) %}
            {% assign tempval = val_array[i] %}
            {% assign tempval = tempval | split: 'ğ' %}
            {% assign tempval_array = tempval_array | concat: tempval %}

            {% assign tempurl = url_array[i] %}
            {% assign tempurl = tempurl | split: 'ğ' %}
            {% assign tempurl_array = tempurl_array | concat: tempurl %}

            {% assign temptitle = title_array[i] %}
            {% assign temptitle = temptitle | split: 'ğçş' %}
            {% assign temptitle_array = temptitle_array | concat: temptitle %}
        {% endfor %}

        {% assign tempval = rel_value %}
        {% assign tempval = tempval | split: 'ğ' %}
        {% assign tempval_array = tempval_array | concat: tempval %}

        {% assign tempurl = item.url %}
        {% assign tempurl = tempurl | split: 'ğ' %}
        {% assign tempurl_array = tempurl_array | concat: tempurl %}

        {% assign temptitle = item.title %}
        {% assign temptitle = temptitle | split: 'ğçş' %}
        {% assign temptitle_array = temptitle_array | concat: temptitle %}

        {% assign limit = arraysize | minus: 1 %}
        {% assign start = index | plus: 1 %}

        {% for i in (start..limit) %}
            {% assign tempval = val_array[i] %}
            {% assign tempval = tempval | split: 'ğ' %}
            {% assign tempval_array = tempval_array | concat: tempval %}

            {% assign tempurl = url_array[i] %}
            {% assign tempurl = tempurl | split: 'ğ' %}
            {% assign tempurl_array = tempurl_array | concat: tempurl %}

            {% assign temptitle = title_array[i] %}
            {% assign temptitle = temptitle | split: 'ğçş' %}
            {% assign temptitle_array = temptitle_array | concat: temptitle %}
        {% endfor %}

        {% assign val_array = tempval_array %}
        {% assign url_array = tempurl_array %}
        {% assign title_array = temptitle_array %}
        {% endif %}
        {% endif %}
    {% endif %}
{% endfor %}


{% assign title_array = title_array |reverse %}
{% assign url_array = url_array |reverse %}

<ul>
{% for i in url_array %}
    <li><a href="{{url_array[forloop.index0]}}">{{title_array[forloop.index0]}}</a></li>
{% endfor %}
</ul>

Her ne kadar çirkin de dursa kısaca anlatacağım.

  • Mevcut sayfanın tag sayısını kullanarak bir tagin değerini tag_value belirliyoruz.
  • Tüm koleksiyonları birleştiriyoruz.
  • 3 ayrı array oluşturuyoruz. url, val ve title
    • val_array‘inde yukarıda anlattığım ilişki değeri tutulacak. Bu değer 0 ile 1 arasında olabilir, ortak tag sayısı * tag_value
    • Diğer iki array adı ile ifade ediyor kendisini. Bu 3 array hep aynı işlemleri görecek ve böylece url[0] title[0] val[0] aynı sayfaya ait değerleri içerecek.
  • all_posts un içindeki herbir item için for döngüsüne gireceğiz.
    • Eğer page.url == item.url for döngüsünde bu iterasyonu pas geçeceğiz. (continue)
    • Bir sonraki döngü, ortak tag sayısı * tag_value ile rel_value ‘yü hesaplıyor.
    • Eğer ki rel_value 0’dan farklı ise (büyük ise)
      • free_slot hesaplıyoruz. Listeleyeceğimiz max. post sayısı (constant_limit) - mevcut sayı (arraysize)
      • Eğer yer var ise free_slot > 0; 3 array için de ilgili değerleri, kendi dizilerine ekliyoruz.
      • Eğer yer yok ise free_slot == 0; val_array deki değerler ile kıyaslayıp hangi indexe gelmesi gerektiğini hesaplıyoruz ve ilgili indexe atıyoruz.
  • En sonunda arrayleri kullanarak linkleri oluşturup listeliyoruz.

Her ne kadar teoride etiketleri daha iyi kullanarak daha anlamlı sonuçlar üretecek olsa da pratikte lüzumsuz bu yapıyı kurarken syntax ile epey haşır neşir olup bilgi edinmiş oldum. Kesinlikle iyileştirmeye müsait bir halde hâlâ. En azından istediğim çözüme ulaştım.

You are reading the 12nd of 19 episodes in Jekyll.
Published on 03.07.2018 by Mert Bakır with commit de81d3f.
jekyll
#jekyll #liquid #pagination #static-site
Next episode:
Tag Cloud in Jekyll
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 21.01.2019

Jekyll’da varsayılan olarak gelen yapıda tüm postları _posts/ klasörü altında tutarız. Post sayısı arttıkça postları gruplama, alt klasörlere bölme ihtiyacı duyabilirz. Jekyll hâlâ postları görecek ve site.posts değişkeni, _posts/ ve altındaki tüm alt dizinlerdeki tüm postları getirecektir. …

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 …