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 261e231.
jekyll
#jekyll #liquid #pagination #static-site #tags
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 17.04.2022
edited on 02.05.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 …

published on 19.02.2022

Önceki yazıda LaTeX kullanmanın avantajlarından ve zorluklarından bahsetmiştim, MS Word gibi WYSIWYG programlar ile karşılaştırıp tavsiyelerimi yazmıştım. Bu yazıda Pandoc yazılımı üzerine konuşacağız. Pandoc’un da yardımıyla LaTeX’in avantajlarını alıp zorluklarını biraz geri de …

published on 12.02.2022

LaTeX bir çeşit döküman hazırlama sistemidir, ancak çoğumuzun alıştığı arayüzlerin aksine bu döküman içerisinde kod yazar gibi bazı komutlar kullanırız. Daha sonra derleyici (compiler) bu dökümanı bizim tanımladığınız kurallara göre PDF’e dönüştürür. […] 1978 yılında, Donald Knuth TeX …

published on 02.01.2022

This post is for fellow students who is studying Operations Research with CPLEX. If you don’t know already, IBM offers free academic license for IBM ILOG CPLEX Optimization Studio. […] First, you have to register IBM Academic Initiative with your academic instituion issued email. (e.g. …