কম্পিউটার

জেকিলের সাথে সাবনেভিগেশনের একাধিক স্তর

পূর্ববর্তী একটি পোস্টে আমি আপনাকে দেখিয়েছি কিভাবে একটি জেকিল পৃষ্ঠায় প্রতিটি H2 এর জন্য সাবনেভিগেশন লিঙ্ক তৈরি করতে হয়। এই পোস্টে, আমরা সেই ভিত্তির উপর ভিত্তি করে তৈরি করব এবং আপনাকে দেখাব কিভাবে আপনি H3, H4, ইত্যাদির উপর ভিত্তি করে সাবনেভিগেশনের নির্বিচারে মাত্রা যোগ করতে পারেন।

ওভারভিউ

আমি এই প্রকল্পটিকে কয়েকটি ধাপে ভাগ করেছি:

  • প্রথমে, H2 ট্যাগের "ভিতরে" H3 ট্যাগ দ্বারা সংজ্ঞায়িত বিভাগগুলি বের করতে আমরা nokogiri ব্যবহার করব
  • এরপর, আমরা সাব নেভিগেশনের নির্বিচারে মাত্রা রেন্ডার করার জন্য একটি দুর্দান্ত কৌশল ব্যবহার করব। আমরা একটি পুনরাবৃত্ত টেমপ্লেট তৈরি করতে যাচ্ছি।

আমরা শুরু করার আগে, আসুন কিছু পরিষ্কার করা যাক। যখন আমি একটি H3 ট্যাগকে একটি H2 এর ভিতরে বলে উল্লেখ করি, তখন আমার মানে এই নয় যে এটি আক্ষরিকভাবে নেস্টেড। পরিবর্তে, আমি সেই পরিস্থিতির উল্লেখ করছি যা আমরা নীচে দেখতে পাচ্ছি:

<h2>Animals</h2>
<p>Here are some kinds of animals.</p>
<h3>Giraffe</h3>
<p>This section about giraffes logically belongs inside of the section about animals, even though the structure of the Dom doesn't define it as being nested</p>
<h3>Zebra</h3>
<p>Another section that logically belongs under "Animals"</p>

দস্তাবেজটিকে বিভাগে ভাঙা

উপরের মত একটি এইচটিএমএল ডকুমেন্টকে ভাগে ভাগ করার সময় আমরা যে সুস্পষ্ট সমস্যাটির মুখোমুখি হই, তা হল কিছুই নেস্ট করা নেই। এইচটিএমএল পার্স করার জন্য বেশিরভাগ টুল নেস্টিংয়ের সাথে কাজ করার জন্য তৈরি করা হয়।

এটি কোনও চুক্তি ভঙ্গকারী নয়, তবে এর অর্থ এই যে আমাদের আরও কিছুটা কাজ করতে হবে। নীচের উদাহরণে আমরা প্রতিটি H2 ট্যাগ খুঁজে পাই এবং তারপর ম্যানুয়ালি H3 ট্যাগের জন্য ভাইবোন স্ক্যান করি।

আমি অভিনব পেয়েছিলাম এবং একটি কাস্টম গণনাকারী ব্যবহার করেছি। আপনার যদি সেগুলি সম্পর্কে কোনও প্রশ্ন থাকে তবে সেগুলিতে আমার ব্লগ পোস্ট দেখুন৷

require "nokogiri"

class MySubnavGenerator < Jekyll::Generator
  def generate(site)
    parser = Jekyll::Converters::Markdown.new(site.config)

    site.pages.each do |page|
      if page.ext == ".md"
        doc = Nokogiri::HTML(parser.convert(page['content']))

        page.data["subnav"] = doc.css('h2').map do |h2|
          to_nav_item(page, h2).tap do |item|
            item["children"] = subheadings(h2).map { |h3| to_nav_item(page, h3) }
          end
        end
      end
    end
  end

  # Converts a heading into a hash of the info for a link
  def to_nav_item(page, heading)
    {
      "title" => heading.text,
      "url" => [page.url, heading['id']].join("#")
    }
  end

  # Returns an enumerator of all H3s "belonging" to an H2
  def subheadings(el)
    Enumerator.new do |y|
      next_el = el.next_sibling
      while next_el && next_el.name != "h2"
        if next_el.name == "h3"
          y << next_el
        end
        next_el = next_el.next_sibling
      end
    end
  end
end

আমি বুঝতে পারি যে এটি আপনাকে নিক্ষেপ করার জন্য কোডের একটি ব্লব, তবে এটি আগের পোস্টে আমরা যে কাজটি করেছি তার থেকে এটি তৈরি করে। আপনার যদি জেকিল প্লাগ-ইনগুলির গঠন সম্পর্কে কোন প্রশ্ন থাকে, বা আমরা যেভাবে নোকোগিরি ব্যবহার করছি অনুগ্রহ করে সেই নিবন্ধটি দেখুন৷

যখন আমি আমাদের ডকুমেন্টেশন সাইটের বিরুদ্ধে এই কোডটি চালাই, তখন আমি একটি হ্যাশ পাই যা দেখতে এরকম কিছু:

[{"title"=>"Getting Started",
  "url"=>"/lib/java.html#getting-started",
  "sub_subnav"=>
   [{"title"=>"Download / Maven", "url"=>"/lib/java.html#download-maven"},
    {"title"=>"Stand Alone Usage", "url"=>"/lib/java.html#stand-alone-usage"},
    {"title"=>"Servlet Usage", "url"=>"/lib/java.html#servlet-usage"},
    {"title"=>"Play Usage", "url"=>"/lib/java.html#play-usage"},
    {"title"=>"API Usage", "url"=>"/lib/java.html#api-usage"}]},
    ...

এখন আমাদের যা করতে হবে তা হল কিভাবে তরল টেমপ্লেট ব্যবহার করে এই জিনিসটি রেন্ডার করা যায়।

সাবনাভ রেন্ডার করা

তরল টেমপ্লেট ব্যবহার করে নির্বিচারে গভীর সাব নেভিগেশন রেন্ডার করা আসলে এতটা কঠিন নয়। কৌশলটি হল একটি আংশিক ব্যবহার করা যা নিজেকে রেন্ডার করে।

আমার লেআউটে, আমি আংশিক রেন্ডার করি এবং নেভিগেশন আইটেম সংগ্রহে পাস করি।

{% include navigation_item.html collection=page.subnav level=0 %}

আংশিকটি নেভিগেশনের এই স্তরের জন্য লিঙ্ক তৈরি করে এবং তারপরে বাচ্চাদের একটি তালিকায় পাস করে নিজেকে রেন্ডার করে। ঠিক একটি পুনরাবৃত্ত ফাংশনের মতো, এটি তাত্ত্বিকভাবে চিরতরে চলতে পারে। শুধু কিক করার জন্য, আমি সাবনাভের প্রতিটি স্তরকে level-1 এর মত একটি ক্লাস দিতে কিছুটা কোড যোগ করেছি অথবা level-2 . এটি স্টাইলিং এর জন্য সত্যিই দরকারী।

{% if include.collection.size > 0 %}
<ul class="nav nav-list level-{{ include.level }}">
    {% for item in include.collection %}
      {% if item.url == page.url %}
      <li class="active">
      {% else %}
      <li>
      {% endif %}
        {% if item.subnav.size > 0 %}
          <a class="has-subnav" href="{{ item.url }}">
          <span class="glyphicon glyphicon-plus"></span>
          <span class="glyphicon glyphicon-minus"></span>
        {% else %}
          <a href="{{ item.url }}">
        {% endif %}
          {{ item.title }}
        </a>
        {% assign next_level = include.level | plus: 1 %}
        {% include navigation_item.html collection=item.children level=next_level %}
      </li>
    {% endfor %}
  </ul>
{% endif %}

এটাই!

এটি জেকিলের বিস্ময়কর জগতে আমাদের সংক্ষিপ্ত যাত্রা শেষ করে। রুবি অভ্যন্তরীণ নিবন্ধগুলির একটি সিরিজ প্রকাশের পরের কয়েক দিনে, তাই সাথে থাকুন!


  1. জাভাস্ক্রিপ্টে একাধিক ধাপ সহ একটি ফর্ম কীভাবে তৈরি করবেন?

  2. অ্যান্ড্রয়েডে একাধিক স্ক্রিন সহ ওয়েবভিউকে কীভাবে সমর্থন করবেন?

  3. CSS3 এর সাথে একাধিক ব্যাকগ্রাউন্ড যোগ করা

  4. MongoDB-তে একাধিক শর্ত সহ অ্যারে কীভাবে আপডেট করবেন