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