पिछली पोस्ट में मैंने आपको दिखाया था कि जेकिल पेज में प्रत्येक H2 के लिए सबनेविगेशन लिंक कैसे उत्पन्न करें। इस पोस्ट में, हम उस नींव पर निर्माण करेंगे और आपको दिखाएंगे कि H3, H4, आदि के आधार पर सबनेविगेशन के मनमाने स्तर कैसे जोड़ सकते हैं।
अवलोकन
मैंने इस प्रोजेक्ट को कुछ चरणों में विभाजित किया है:
- सबसे पहले, हम नोकोगिरी का उपयोग करके H3 टैग द्वारा परिभाषित अनुभागों को H2 टैग के "अंदर" से निकालेंगे
- अगला, हम मनमाने स्तर के सब नेविगेशन को रेंडर करने के लिए एक अच्छी ट्रिक का उपयोग करेंगे। हम एक रिकर्सिव टेम्पलेट बनाने जा रहे हैं।
शुरू करने से पहले, आइए एक बात स्पष्ट कर लें। जब मैं 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>
दस्तावेज़ को अनुभागों में तोड़ना
ऊपर दिए गए HTML दस्तावेज़ जैसे दस्तावेज़ को अनुभागों में तोड़ने में स्पष्ट समस्या यह है कि कुछ भी नेस्टेड नहीं है। HTML पार्स करने के लिए अधिकांश टूल नेस्टिंग के साथ काम करने के लिए बनाए गए हैं।
यह डील ब्रेकर नहीं है, लेकिन इसका मतलब है कि हमें थोड़ा और काम करना होगा। नीचे दिए गए उदाहरण में हम प्रत्येक 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 %}
बस इतना ही!
यह जेकिल की अद्भुत दुनिया में हमारे संक्षिप्त प्रवास का समापन करता है। अगले कुछ दिनों में रूबी इंटर्नल्स पर लेखों की एक श्रृंखला प्रकाशित कर रहा हूँ, तो बने रहें!