Wrangler 是一個靜態網站產生器,適合不建立部落格的人。
特徵:
在 Springload,我們經常需要創建靜態站點,但我們一直在努力尋找一個工具,嗯……讓我們繼續使用它。輸入牧馬人。它不會期望您的內容被格式化為一系列部落格文章。它不會複製靜態資產或處理 SaSS 或製作咖啡。
它只做一件事,而且把那件事做得很好。
我們希望您喜歡它。
透過 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
- 自訂擴充功能、類別、掛鉤等都放在這裡。寫一些python模組並將結果傳遞回wranglervar
- 保存範本快取和檔案物件快取(wrangler 使用開箱即用的 Pickle 和 Shelve 組合)所有這些路徑都可以在wrangler.yaml
中更改
Wrangler 假設您正在處理某種結構化數據,並且您希望將這些資料檔案轉換為 HTML(甚至是經典的 ASP,如果您喜歡的話)。
套件中包含三個解析器: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
這是一個很好的 Markdown 備忘單
將元資料用於與頁面相關的任何內容。你可以在這裡添加任何你喜歡的內容,但有一些保留字:
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
導覽中的頁面名稱(也可能是您的標題標籤)
模板路徑,相對於 wrangler.yaml 的templates_dir
標題的簡寫,可以在導航中使用
嘗試替換頁面物件的 Python 類別。必須是wrangler.Core.Page
的子類
從導航樹中隱藏此頁面。
罐頭上寫著什麼
關鍵字列表
覆蓋 wrangler.yaml 中的預設output_file_extension
。該頁面將使用此擴展名呈現。
方便對頁面進行排序,從低到高。預設情況下,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 附帶了 jinja2 markdown 過濾器。如果您使用的是 Markdown 文件,則可在data.content
處找到 Markdown。將內容透過管道傳輸到 Markdown 過濾器,就完成了。
< 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
將所有頁面的輸出檔案副檔名變更為經典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 在啟動時會載入專案lib
目錄中找到的所有 python 模組。
這使您能夠擴展核心功能並操作頁面資料 - 例如,您可以從資料庫加載一些值並使它們在模板中可用。
當您呼叫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 :
為了保持整潔,Node 物件不會直接在其上保存頁面資料的表示 - 節點只是容器。
依照本次討論中的想法,節點有一個Cargo屬性來保存真實的頁麵類別:
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 要載入哪個類別:
內容/自訂.md:
---
class : RightToLeft
---
# My custom page
With its custom content.
然後在lib/
目錄中的某個位置建立一個新類,該類是Page
子類。它在lib/
目錄中的哪個位置結束並不重要,唯一的規則是它必須子類化Page
物件:
庫/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 使用blinker 的訊號來處理hook 和擴展。
鉤子是在渲染過程中的關鍵點觸發的訊號。它們按照它們在模組中出現的順序進行處理,並且可以直接修改傳入的物件。他們還可以存取 wrangler 的config
、 renderer
和reporter
。
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 ()
如果您需要存取 jinja 的contextfilter
或envcontextfilter
您可以匯入它們並將它們套用到您的函數中:
閱讀有關 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