Wrangler เป็นเครื่องมือสร้างเว็บไซต์แบบคงที่สำหรับผู้ที่ไม่ได้สร้างบล็อก
คุณสมบัติ:
ที่ Springload เรามักจะต้องสร้างไซต์แบบคงที่ แต่เราประสบปัญหาในการหาเครื่องมือที่เอาล่ะ.. ช่วยให้เราทำต่อไปได้ เข้าไปในรถแรงเลอร์ จะไม่คาดหวังว่าเนื้อหาของคุณจะถูกจัดรูปแบบเป็นชุดบทความในบล็อก ไม่คัดลอกสินทรัพย์คงที่หรือประมวลผล SaSS หรือชงกาแฟ
มันทำสิ่งหนึ่งและมันก็ทำสิ่งหนึ่งได้ค่อนข้างดี
เราหวังว่าคุณจะชอบมัน
ติดตั้ง wrangler ผ่าน pip:
pip install wrangler
สร้างโครงการใหม่ใน .
ปัจจุบัน
wrangler create .
สิ่งนี้จะสร้างไดเร็กทอรีจำนวนมาก หากต้องการตรวจสอบว่าใช้งานได้ ให้สร้างไซต์เล็กๆ ที่สร้างขึ้นอัตโนมัติ:
wrangler build content www
ให้บริการเว็บไซต์ของคุณผ่านเครื่องมือที่คุณเลือกหรือเซิร์ฟเวอร์ในตัวที่มีประโยชน์ที่ http://127.0.0.1:8000/
:
wrangler serve www
ต้องการดูเนื้อหาและเทมเพลตของคุณเพื่อดูการเปลี่ยนแปลงและสร้างใหม่โดยอัตโนมัติหรือไม่ มีแอพสำหรับสิ่งนั้น งาน watch ใช้ตัวเลือกเดียวกันกับ build
wrangler watch content www
Wrangler ปฏิบัติตามแบบแผนระบบไฟล์ที่ค่อนข้างง่าย:
my-site/
| --content
| ----index.yaml
| --lib
| --templates
| ----template.j2
| --var
| --wrangler.yaml
| --www
content
- ไดเร็กทอรีเนื้อหา โครงสร้างไซต์ของคุณจะสะท้อนไดเร็กทอรีนี้ หากคุณมี content/index.yaml
คุณจะได้รับ www/index.html
templates
- ที่ซึ่งเทมเพลต jinja2 .j2
ของคุณแสดงอยู่www
- โฟลเดอร์รูทของเว็บ จริงๆ แล้ว คุณสามารถส่งออกไปที่ใดก็ได้ เราเพิ่งเลือก www เป็นค่าเริ่มต้นที่สมเหตุสมผลlib
- ส่วนขยายที่กำหนดเอง คลาส hooks ฯลฯ เข้าไปที่นี่ เขียนโมดูลหลามและส่งผลลัพธ์กลับไปยัง wranglervar
- เก็บแคชเทมเพลตและแคชอ็อบเจ็กต์ไฟล์ (wrangler ใช้คำสั่งผสม Pickle และ Shelve นอกกรอบ) เส้นทางทั้งหมดนี้สามารถเปลี่ยนแปลงได้ใน wrangler.yaml
Wrangler ถือว่าคุณกำลังทำงานกับข้อมูลที่มีโครงสร้างบางประเภท และคุณต้องการแปลไฟล์ข้อมูลเหล่านั้นเป็น HTML (หรือแม้แต่ ASP แบบคลาสสิก หากคุณสนใจ)
parsers สามตัวรวมอยู่ในแพ็คเกจ: json, yaml และ markdown (โดยมี yaml front-matter) พวกมันทำงานเป็นรายไฟล์ ดังนั้นสิ่งนี้จึงถูกต้องสมบูรณ์:
my-site/
| --content
| ----index.yaml
| ----page-2.json
| ----page-3.md
meta :
title : My title
template : template.j2
description : " My cool page! "
data :
content : " Here's some page content! "
blocks :
- " Lots of content "
- " even more content "
- " wow, so much content! "
{
"meta" : {
"title" : " My title " ,
"template" : " template.j2 " ,
"description" : " My cool page! "
},
"data" : {
"content" : " Here's some page content! " ,
"blocks" : [
" Lots of content " ,
" even more content " ,
" wow, so much content! "
]
}
}
---
title : My title
template : template.j2
description : " Markdown uses yaml front-matter "
---
# A heading!
Some paragraph text
## Another heading!
Even more text
---
Nice HR you got there.
* A list
* with some
* list items
นี่เป็นสูตรโกงมาร์กดาวน์ที่ดี
ใช้ข้อมูลเมตาสำหรับสิ่งที่เกี่ยวข้องกับเพจ คุณสามารถโยนสิ่งที่คุณชอบได้ที่นี่ แต่มีคำที่สงวนไว้สองสามคำ:
meta :
title : " Musings on the pronounciation of doge "
alias : " Doge "
template : " template.j2 "
class : DogePage
hide_from_nav : true
description : " Is it dog-e, doog, douge, douche? How do I properly refer to this meme? "
keywords : ["much", "analytics", "such", "SEO"]
output_file_extension : asp
weight : 1
thumbnail : /assets/images/thumb/doge-100x100.jpg
related :
- content/other-page.yaml
- content/pages/this-page-here.yaml
ชื่อเพจในการนำทาง (และอาจเป็นแท็กชื่อของคุณด้วย)
เส้นทางเทมเพลต สัมพันธ์กับ templates_dir
ของ wrangler.yaml ของคุณ
ชวเลขของชื่อเรื่องซึ่งสามารถนำไปใช้ในการนำทางแทนได้
ความพยายามที่จะแทนที่คลาส Python สำหรับวัตถุหน้า ต้องเป็นคลาสย่อยของ wrangler.Core.Page
ซ่อนหน้านี้จากแผนผังการนำทาง
สิ่งที่เขียนไว้บนกระป๋อง
รายการคำหลัก
แทนที่ค่าเริ่มต้น output_file_extension
จาก wrangler.yaml เพจจะแสดงผลด้วยส่วนขยายนี้
สะดวกในการเรียงลำดับหน้าจากต่ำไปสูง ตามค่าเริ่มต้น wrangler จะใช้การเรียงลำดับตามตัวอักษรของระบบไฟล์
เส้นทางไปยังรูปภาพขนาดย่อ
รายการหน้าที่เกี่ยวข้อง ในเทมเพลตของคุณ ข้อมูลนี้จะช่วยให้คุณได้รับข้อมูลพื้นฐานเกี่ยวกับหน้าอื่นๆ (เช่น ชื่อและคำอธิบาย)
Wrangler จะเพิ่มบางสิ่งลงในข้อมูลเมตาของคุณโดยอัตโนมัติ ในเทมเพลตของคุณคุณสามารถเข้าถึง:
{{ meta.url }}
{{ meta.segments }}
{{ meta.filepath }}
{{ meta.mtime }}
{{ meta.children }}
{{ meta.parents }}
{{ meta.parents_siblings }}
พาธไปยังไฟล์ที่สร้างขึ้นซึ่งสัมพันธ์กับ output_dir
เช่น /
รายการส่วนของ URL ทั้งหมด: ["sub-directory", "index.html"]
ชื่อของไฟล์อินพุต
เวลาที่แก้ไข คุณสามารถใช้สิ่งนี้เพื่อสร้างการประทับเวลาของบล็อกได้ เป็นต้น
ลูกโดยตรงของไดเร็กทอรีปัจจุบัน
โหนดทั้งหมดระหว่างไฟล์ปัจจุบันและ /
พี่น้องของไดเรกทอรีหลัก
ข้อมูลหน้าเป็นทางเลือกทั้งหมด
ลองดูที่หน้าเล็กๆ นี้ custom-page.yaml
คุณสามารถโยน wrangler เพจที่ไม่มีข้อมูล และฮาร์ดโค้ดทุกอย่างในเทมเพลต custom-page.j2
หากคุณต้องการ
meta :
title : No content!
template : custom-page.j2
output_file_extension : txt
สิ่งนี้จะสร้าง www/custom-page.txt
Wrangler มาพร้อมกับตัวกรอง markdown jinja2 หากคุณใช้ไฟล์มาร์กดาวน์ คุณสามารถดูมาร์กดาวน์ได้ที่ data.content
ไพพ์เนื้อหาไปยังตัวกรองมาร์กดาวน์ เท่านี้ก็เสร็จเรียบร้อย
< div class = " content " >
{{ data.content|markdown }}
</ div >
Markdown เป็นรูปแบบการเขียนที่ยอดเยี่ยม แต่อาจมีข้อจำกัดบางประการเมื่อคุณจัดการกับข้อมูลที่มีโครงสร้างมากขึ้น สำหรับไฟล์ YAML และ JSON ให้เข้าถึงส่วนต่างๆ ของพจนานุกรม data
และโยงเข้าด้วยกันตามที่เห็นสมควร:
< div class = " content " >
{{ data.content }}
{% for block in data . blocks %}
< p >{{ block }}</ p >
{% endfor %}
</ div >
ตัวเลือกที่แก้ไขได้สำหรับ wrangler จะถูกบันทึกไว้ในไฟล์ wrangler.yaml
ในรูทโปรเจ็กต์ของคุณ
เปิดมันขึ้นมาแล้วคุณจะพบกับสามโหนด: wrangler
, site
และ extensions
นี่คือการกำหนดค่าหลัก ซึ่งเป็นสิ่งที่ฮาร์ดคอร์ มีลักษณะเล็กน้อยดังนี้:
wrangler :
# Template directory relative to your project root
templates_dir : templates
# Default template to load if no template is specified for a page
default_template : template.j2
# Default output file extension. Note this can be overwritten in the content
# by specifying 'output_file_extension' in the 'meta' area
output_file_extension : html
# Supported data formats. Ensure a parser is registered for each type.
# More information about parsers can be found in the link at the top of the file.
data_formats : ['yaml', 'yml', 'json', 'js', 'md', 'markdown']
# Ignore hidden files, and files starting with underscores
ignore : ['.','_']
# Prints all the internal plumbing output to stdout
verbose : false
# Always force all pages to be rendered
force : false
# Run without the cache (useful for developing custom page classes, to prevent them
# from being cached each run).
nocache : false
# The location of the template cache zip file.
# Ensure the var path exists and is writeable by the user
build_cache_file : var/build.cache
compiled_templates_file : var/jinja
compiled_templates_log : var/jinja.log
# Custom methods/classes go in the lib directory, for instance
# lib/Page.py or lib/Extensions.py or lib/Filters.py
lib_path : lib
# file continues....
กำหนดค่าส่วนขยายใดๆ ที่คุณได้ตั้งค่าไว้ที่นี่ ส่วนขยายช่วยให้คุณเรียกใช้ฟังก์ชัน Python ใดก็ได้ที่คุณต้องการ และแทรกผลลัพธ์ลงในเทมเพลตของคุณ
# wrangler.yaml continued...
extensions :
# Sitemap generates a tree structure of your entire site, relative to the
# webroot specified here
#
# {{ extensions.sitemap }}
#
# We leave it up to you to iterate over the sitemap and print everything in
# a pretty manner, but this gist might get you started:
# https://gist.github.com/joshbarr/111
sitemap :
webroot : /
{{ extensions.cachebuster }}
มีส่วนขยายเริ่มต้นบางรายการรวมอยู่ด้วย: sitemap
, fileinfo
และ cachebuster
ตัวแปรไซต์เป็นตัวแปรทั่วทั้งไซต์ ซึ่งมีอยู่ในเทมเพลตของคุณในฐานะรายการย่อยของออบเจ็กต์ site
ตัวอย่างเช่น หากต้องการรับเส้นทางรูปภาพ คุณสามารถโทร {{ site.paths.images }}
และช่วยตัวเองในการพิมพ์บ้าง
# wrangler.yaml continued...
site :
paths :
css : assets/css
js : assets/js
assets : assets
{# Hey, it's those handy vars I set in my site_vars #}
{{ site.paths.css }}
เอกสารทั้งหมดนี้อยู่ในไฟล์ wrangler.yaml
เช่นกัน ดังนั้นคุณจะไม่หลงทาง!
รับอาร์กิวเมนต์ตำแหน่งเดียวซึ่งเป็นเส้นทางในการสร้างโปรเจ็กต์ใหม่ของคุณ:
cd my-sweet-site && wrangler create .
# or
wrangler create my-sweet-site
input_dir
ไดเร็กทอรีอินพุต เช่น site/content
output_dir
ไดเร็กทอรีเอาต์พุต เช่น www
wrangler build content www
บังคับให้แสดงผลไม่ว่าเนื้อหาของคุณจะถูกแก้ไขครั้งล่าสุดเมื่อใด:
wrangler build content www --force
แคชออบเจ็กต์หน้าทั้งหมดอีกครั้ง
wrangler build content www --nocache
เปลี่ยนนามสกุลไฟล์เอาต์พุตสำหรับทุกหน้าเป็น classic asp
(ทำไมทุกคนถึงทำอย่างนั้น?)
wrangler build content www -o ".asp"
เปลี่ยนรูปแบบข้อมูลที่จะค้นหาใน input_dir
เป็น json
wrangler build content www -d 'json'
เปลี่ยนตำแหน่งของไดเร็กทอรีเทมเพลต
wrangler build content www -t other-templates-dir
เปลี่ยนตำแหน่งของไฟล์กำหนดค่า
wrangler build content www -c site/config/wrangler.yaml
มีออปชั่นแบบเดียวกับ wrangler build
เลย
พิมพ์ระบบประปาทั้งหมดทุกครั้งที่มีการเปลี่ยนแปลงไฟล์:
wrangler watch content www --verbose
ยอมรับหนึ่งอาร์กิวเมนต์ตำแหน่ง (ไดเรกทอรีที่จะให้บริการ) และตัวเลือก --port
(ค่าเริ่มต้น 8000)
wrangler serve www --port 8001
ลบแคชเทมเพลตและแคชออบเจ็กต์ออกจากไดเร็กทอรี 'var'
wrangler clean
Wrangler จะโหลดโมดูล Python ทั้งหมดที่พบในไดเร็กทอรี lib
ของโปรเจ็กต์ของคุณเมื่อทำการบูท
สิ่งนี้ให้อำนาจคุณในการขยายฟังก์ชันหลักและจัดการข้อมูลเพจ - ตัวอย่างเช่น คุณสามารถโหลดค่าบางค่าจากฐานข้อมูลและทำให้สามารถใช้ได้ในเทมเพลตของคุณ
เมื่อคุณเรียกใช้ build
wrangler จะสร้างการแสดงโครงสร้างแผนผังในไดเร็กทอรี content/
ของคุณ
มันใช้รายการวัตถุ Node
ที่เชื่อมโยงกันเป็นสองเท่าซึ่งถูกบดเป็น NodeGraph
ซึ่งเป็นคอนเทนเนอร์ที่มีประโยชน์สำหรับการจัดการกับโหนด
# Pseudocode
NodeGraph :
# The nodes in their hierarchical structure, eg:
tree :
Node :
children :
- Node :
children :
- Node
- Node :
children :
- Node
- Node
- Node
# The 'all' dictionary is the same nodes represented in a flat structure.
# This can be much quicker to iterate over than the tree, and you can
# access both from within your hooks and extensions.
# The filepath is used as the unique key.
all :
content/index.md :
Node :
# node's data...
content/other-page.md :
Node :
# node's data...
โหนดสามารถเข้าถึงลูก ๆ ของพวกเขาและผู้ปกครองของพวกเขาด้วย:
# More pseudocode
Node :
path : " content/index.md "
children :
- Node :
- Node :
- Node :
parent :
Node :
เพื่อให้สิ่งต่าง ๆ เป็นระเบียบเรียบร้อย โหนดออบเจ็กต์ไม่ได้เก็บการแสดงข้อมูลหน้าไว้โดยตรง โหนดเป็นเพียงคอนเทนเนอร์
ตามแนวคิดในการสนทนานี้ โหนดมีคุณสมบัติ ขนส่งสินค้า ที่เก็บคลาสเพจ จริง :
from wrangler . Core import Node
class GoldBullion ( object ):
price = 1200
the_node = Node ( "index" , "content/index.md" , parent = None , cargo = None )
the_node . add_cargo ( GoldBullion ())
cargo = the_node . get_cargo ()
print cargo . price
เพจมีการแสดง dict
ตามข้อมูลของไฟล์ต้นฉบับของคุณ และจัดเตรียมวิธีที่สอดคล้องกันสำหรับ Renderer
ในการเข้าถึงข้อมูล หากต้องการสร้างเพจแบบกำหนดเอง เพียงคลาสย่อย wrangler.Core.Page
และเพจจะถูกโหลดอัตโนมัติ
เคล็ดลับที่มีประโยชน์: หากคลาสที่คุณกำหนดเองมีชื่อ Page
นั้นจะเขียนทับออบเจ็กต์ Page
เริ่มต้นสำหรับทุกหน้า
# lib/Page.py
import wrangler . Core as wrangler
class Page ( wrangler . Page ):
def get_content ( self ):
return self . data [ "data" ]
def get_metadata ( self ):
return self . data [ "meta" ]
def get_properties ( self ):
print "Hey, I'm a custom page instance!"
return {
"title" : self . get_title (),
"alias" : self . get_short_title (),
"description" : self . get_meta_description (),
"url" : self . get_tidy_url (),
"show_in_navigation" : self . show_in_navigation (),
"weight" : self . get_weight (),
"thumbnail" : self . get_thumbnail ()
}
ในตัวอย่างด้านบน เรากำลังแก้ไขเมธอดหน้าหลักสามวิธี ได้แก่ get_content()
, get_metadata()
และ get_properties()
เรียกว่าเมื่อมีการเรนเดอร์เพจ สิ่งนี้จะมีอยู่ในเทมเพลตของคุณเป็นออบเจ็กต์ data
:
<!doctype html>
< div class = ' dump-of-data-object ' >
{{ data.content }}
</ div >
เรียกว่าเมื่อมีการเรนเดอร์เพจ นี่คือออบเจ็กต์ meta
:
<!doctype html>
< title >{{ meta.title }}
อธิบายยากกว่าเล็กน้อย แต่ก็ยังยอดเยี่ยม เมื่อ Node
ถูกแสดงผล มันจะร้องขอข้อมูลบางอย่างเกี่ยวกับเพจที่เกี่ยวข้องกับเพจปัจจุบัน เช่น เพจย่อย พี่น้อง ผู้ปกครอง และเพจที่เกี่ยวข้องด้วยตนเอง
แทนที่จะแบ่งปัน ทุกสิ่ง กับ สิ่งอื่น แต่ละคลาส Page
จะอธิบายข้อมูลพื้นฐานที่ยินดีแบ่งปันกับเพจอื่นๆ
def get_properties ( self ):
return {
"title" : self . get_title (),
"alias" : self . get_short_title (),
"url" : self . get_tidy_url (),
"show_in_navigation" : self . show_in_navigation (),
"weight" : self . get_weight (),
# Let's add the modified time, so our theoretical parent
# page could know when we last saved the file.
"mtime" : self . getmtime ()
}
มาดูตัวอย่างง่ายๆ กัน คลาสของหน้าที่กำหนดเองซึ่งจะกลับข้อความทั้งหมดบนหน้า ใช้งานได้จริงมาก
ขั้นแรก ให้ตั้งค่าคุณสมบัติ class
ในเมตาเพจของคุณเพื่อบอก wrangler ว่าจะโหลดคลาสใด:
เนื้อหา/custom.md:
---
class : RightToLeft
---
# My custom page
With its custom content.
จากนั้นสร้างคลาสใหม่ที่ไหนสักแห่งในไดเรกทอรี lib/
ของคุณที่คลาสย่อย Page
มันไม่สำคัญว่ามันจะไปอยู่ที่ใดในไดเร็กทอรี lib/
ของคุณ กฎข้อเดียวคือมันจะต้องซับคลาสของออบเจ็กต์ Page
:
lib/pages.py
import wrangler . Core as wrangler
class RightToLeft ( wrangler . Page )
def get_content ( self ):
for key , val in self . data [ "data" ]:
self . data [ "data" ][ key ] = val [:: - 1 ]
return self . data [ "data" ]
ยอดเยี่ยม! หน้าของเราจะพิมพ์ด้วยข้อความจากขวาไปซ้าย
หากคุณดูในไฟล์ wrangler.yaml
คุณจะสังเกตเห็นว่ามันยอมรับไฟล์ได้สามประเภท: ["yaml", "json", "md"]
Wrangler มีตัวแยกวิเคราะห์สามตัวตามค่าเริ่มต้น ได้แก่ Yaml
, Markdown
และ Json
ซึ่งใช้ไฟล์อินพุตและแสดงว่าเป็นข้อมูลที่มีความหมาย
ตัวโหลดอัตโนมัติจะค้นหาสิ่งใดก็ตามที่คลาสย่อย wrangler.Core.Parser
ตัวอย่างเช่น คุณสามารถทำได้ที่ไหนสักแห่งใน lib/Parsers.py
เพื่อรองรับรูปแบบข้อความ
from wrangler . Core import Parser
from lxml import objectify
from collections import defaultdict
class XmlParser ( Parser ):
accepts = [ "xml" , "robotlanguage" ]
def interpret ( self , file_contents ):
return root = objectify . fromstring ( file_contents )
Wrangler ใช้สัญญาณไฟเลี้ยวในการประมวลผลขอเกี่ยวและส่วนต่อขยาย
Hooks คือสัญญาณที่ยิงไปที่จุดวิกฤติในกระบวนการเรนเดอร์ พวกมันได้รับการประมวลผลตามลำดับที่ปรากฏในโมดูลของคุณ และสามารถแก้ไขออบเจ็กต์ที่เข้ามาได้โดยตรง พวกเขายังสามารถเข้าถึง config
, renderer
และ reporter
ของ wrangler ได้อีกด้วย
from wrangler . Core import before_render , after_render , load_item , save_item , render_item
@ before_render
def before ( ** kw ):
nodes = kw [ 'nodes' ]
config = kw [ 'config' ]
renderer = kw [ 'renderer' ]
reporter = kw [ 'reporter' ]
print "Hey, I'm a hook!"
return "foo!"
@ after_render
def after ( ** kw ):
nodes = kw [ 'nodes' ]
config = kw [ 'config' ]
renderer = kw [ 'renderer' ]
reporter = kw [ 'reporter' ]
print "Hey, I'm a hook!"
return ""
ส่วนขยายคือสคริปต์ Python ที่ส่งคืนข้อมูลที่มีประโยชน์ไปยังพจนานุกรม extensions
ของเทมเพลตของคุณ
ลองใช้สคริปต์เล็กๆ นี้:
# lib/my_extensions.py
from wrangler . Core import extension
@ extension
def my_extension ( sender , ** kwargs ):
# Add some config to your YAML file and access it here:
config = kwargs [ 'config' ][ 'extensions' ][ 'my_extension' ]
return config [ "string_to_print" ]
จะสามารถเข้าถึงได้จากเทมเพลตของคุณที่ extensions.YOUR_EXTENSION_NAME
:
< em class = " extension " >
{{ extensions.my_extension }}
</ em >
ซึ่งส่งผลให้ผลลัพธ์นี้:
< i > "This is my basic extension!" </ i >
ใน wrangler.yaml
ของคุณมีส่วนสำหรับจัดการส่วนขยายของคุณ:
# My extension just prints a string... not very exciting!
my_extension :
string_to_print : " This is my basic extension! "
Wrangler ช่วยให้คุณสามารถขยาย Jinja2 ด้วยตัวกรองแบบกำหนดเองได้
ตัวกรองควรอยู่ในไฟล์ใดก็ได้ในไดเรกทอรี lib ของคุณ lib/
พวกมันเชื่อมต่อผ่านมัณฑนากรซึ่งมีชื่อว่า template_filter
#lib/filters.py
from wrangler . Core import template_filter
from jinja2 import contextfilter
@ template_filter
def my_filter ( value ):
return value . lower ()
หากคุณต้องการเข้าถึง contextfilter
หรือ envcontextfilter
ของ Jinja คุณสามารถนำเข้าและนำไปใช้กับฟังก์ชันของคุณได้เช่นกัน:
อ่านเพิ่มเติมเกี่ยวกับตัวกรองบริบทของ jinja2
#lib/filters.py
from wrangler . Core import template_filter
from jinja2 import contextfilter
@ template_filter
@ contextfilter
def my_filter ( context , value ):
print context
return value