ฉันกำลังสร้างไซต์เอกสารของเราขึ้นใหม่โดยใช้ Jekyll เนื่องจากหน้าเอกสารของเราค่อนข้างใหญ่ เราจึงต้องมีการนำทางย่อยบางประเภทนอกเหนือจากการนำทางระดับบนสุด
ในโพสต์นี้ เราจะพูดถึงวิธีสร้างปลั๊กอิน Jekyll แบบง่ายๆ ที่สามารถสร้างลิงก์การนำทางย่อยจากส่วนหัวในโพสต์หรือหน้าของคุณ
ภาพรวม
ฉันได้แบ่งโปรเจ็กต์นี้เป็นงานต่อไปนี้:
- สร้างตัวสร้าง Jekyll ซึ่งทำงานกับทุกหน้าในไซต์
- สอนตัวสร้างวิธีการแสดงหน้าล่วงหน้าเพื่อให้สามารถดึงข้อมูลส่วนหัวได้
- ใช้ nokogiri เพื่อแยกวิเคราะห์หน้า HTML แยกส่วนหัวและเนื้อหาที่เกี่ยวข้อง
- แสดงการนำทางย่อย
ในตัวอย่างด้านล่าง ลิงก์การนำทางย่อยทั้งหมดเป็นลิงก์สมอ เพื่อให้วิธีนี้ใช้งานได้ คุณจะต้องแน่ใจว่าตัวประมวลผล markdown ของคุณสร้าง ID สำหรับส่วนหัว RedCarpet กับ with_toc_data
ตัวเลือกใช้งานได้ดี
ตัวสร้าง Jekyll พื้นฐาน
มีปลั๊กอินสองสามประเภทที่คุณสามารถสร้างสำหรับ Jekyll ได้ เรากำลังจะสร้างเครื่องกำเนิดไฟฟ้า
ตัวสร้างเป็นเพียงคลาสที่สืบทอดมาจาก Jekyll::Generator
และมีวิธีที่เรียกว่า generate
.
ตัวสร้างจะทำงานหลังจาก Jekyll โหลดไฟล์ markdown ทั้งหมด แต่ก่อนที่ไฟล์เหล่านั้นจะถูกแปลงเป็น HTML site
ออบเจ็กต์ถูกส่งผ่านไปยังวิธีสร้าง และคุณสามารถใช้ออบเจ็กต์ไซต์เพื่อเข้าถึงหน้าไซต์ โพสต์ และแหล่งข้อมูลอื่นๆ ทั้งหมดของคุณ
ในตัวอย่างด้านล่าง เราสร้างตัวสร้างที่วนซ้ำทุกหน้าและพิมพ์ชื่อออกมา
class MySubnavGenerator < Jekyll::Generator
def generate(site)
site.pages.each do |page|
puts page.data["title"]
end
end
end
นอกจากนี้เรายังสามารถแก้ไขข้อมูลหน้าและไซต์ภายในเครื่องกำเนิดไฟฟ้า -- ข้อมูลที่โหลดจากส่วนหน้าและจากไฟล์การกำหนดค่าเว็บไซต์
page.data["title"] += " - modified!"
site.data["tagline"]
การมาร์กดาวน์ล่วงหน้าเป็น HTML
เราต้องการแยกหัวเรื่องออกจากเอกสารการลดราคาของเรา วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการแปลง markdown เป็น HTML จากนั้นแยกวิเคราะห์ HTML โดยใช้เครื่องมือเช่น nokogiri
สิ่งนี้ทำให้ฉันรู้สึกสกปรกเล็กน้อยหรือไม่? ใช่. มันจะช้าไปหน่อยมั้ย? อย่างแน่นอน. แต่เนื่องจาก Jekyll เป็นเครื่องมือสร้างไซต์แบบสแตติก ฉันจึงไม่ต้องกังวลเกี่ยวกับประสิทธิภาพแบบเรียลไทม์ ฉันก็เลยเอาจมูกมาปิดไว้
ที่นี่ เราใช้ตัวตัดมาร์กดาวน์ในตัวของ Jekyll เพื่อแปลงทุกหน้ามาร์กดาวน์เป็น HTML
class MySubnavGenerator < Jekyll::Generator
def generate(site)
parser = Jekyll::Converters::Markdown.new(site.config)
site.pages.each do |page|
if page.ext == ".md"
html = parser.convert(page['content'])
# Do something with the html here
end
end
end
end
การแยกส่วนหัว
สำหรับไซต์เอกสารใหม่ของเรา ฉันตัดสินใจว่าทุกแท็ก H2 ควรมีลิงก์การนำทางย่อยที่สอดคล้องกัน ดังนั้นฉันจะใช้ nokogiri เพื่อแยกวิเคราะห์ HTML ของแต่ละหน้า จากนั้นฉันจะดึงแท็ก H2 ออกจากหน้า
สำหรับตอนนี้ เราจะพิมพ์เนื้อหาและรหัสของ H2 ไปที่หน้าจอ:
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']))
doc.css('h2').each do |heading|
puts "#{ heading.text }: #{ heading['id'] }"
end
end
end
end
end
การสร้างเมนูการนำทางย่อย
ตอนนี้เรามีข้อความส่วนหัวและรหัสแล้ว เราจึงสามารถสร้างรายการลิงก์การนำทางย่อยได้
เราจะจัดเก็บรายการลิงก์นี้เป็นแอตทริบิวต์ข้อมูลของหน้านั้นเอง ด้วยวิธีนี้ เราสามารถเข้าถึงลิงก์จากเทมเพลตหน้าเว็บของเราได้
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').each do |heading|
page.data["subnav"] << { "title" => heading.text, "url" => [page.url, heading['id']].join("#") }
end
end
end
end
end
ในเทมเพลตของคุณ คุณสามารถวนซ้ำผ่านการนำทางย่อยและแสดงแต่ละลิงก์:
{% for item in page.subnav %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% endfor %}
การแก้ไขปัญหา
อย่างที่ฉันได้กล่าวไว้ก่อนหน้านี้ ทั้งหมดนี้ขึ้นอยู่กับตัวประมวลผล markdown ของคุณที่สร้าง ID เฉพาะสำหรับแต่ละหัวข้อ นี่คือการตั้งค่า markdown ของฉันจาก _config.yml
:
# Use the redcarpet Markdown renderer
markdown: redcarpet
redcarpet:
extensions: [
'no_intra_emphasis',
'fenced_code_blocks',
'autolink',
'strikethrough',
'superscript',
'with_toc_data',
'tables',
'hardwrap'
]
ถัดไป...
วิธีการข้างต้นใช้ได้ดีหากคุณต้องการการนำทางย่อยเพียงระดับเดียวเท่านั้น แต่ถ้าคุณต้องการมากกว่านี้ล่ะ? เช่น หากคุณต้องการให้แท็ก H3 ทั้งหมด "อยู่ภายใน" ของ H2 เพื่อสร้างลิงก์การนำทางย่อยในเมนูของคุณ
เราจะกล่าวถึงสิ่งนั้นและอื่น ๆ ในโพสต์บล็อกในอนาคต คอยติดตาม!