express框架的渲染模板有多種選擇,官方的例子是Pug,網上找了一下,Pug沒有能夠參考的中文文檔,因而本身動手豐衣足食。翻譯水平通常,各位湊合着看吧。javascript
安裝css
經過npm安裝pug:html
$ npm install pug
簡介java
Pug的渲染語句很簡單,pug.compile()方法將pug源文件(.pug)源文件編譯成一個帶參數(‘locals’,pug文件的路徑)方法,而後調用這個結果方法就能購生成一段由pug文件轉化成的html字符串。node
這個pug.compile()方法能夠重複使用,生成各類各樣的html字符串來渲染html。jquery
//- template.pug,pug文件 p #{name}'s Pug source code!
調用方法:web
const pug = require('pug'); // 編譯pug源文件 const compiledFunction = pug.compileFile('template.pug'); // 渲染數據 console.log(compiledFunction({ name: 'Timothy' })); // "<p>Timothy's Pug source code!</p>" // 渲染另外一個數據 console.log(compiledFunction({ name: 'Forbes' })); // "<p>Forbes's Pug source code!</p>"
Pug還提供另一種渲染方式:pug.render系列的方法,它把編譯和渲染合併成一個步驟,不須要生成編譯函數,直接渲染pug源文件。固然,默認狀況下調用它每次都要編譯一次,這可能會影響性能。能夠選擇配置項cache爲true,將編譯函數緩存起來,不用每次都從新生成,編譯。以下面的pug.renderFile方式:express
const pug = require('pug'); // Compile template.pug, and render a set of data console.log(pug.renderFile('template.pug', { name: 'Timothy' })); // "<p>Timothy's Pug source code!</p>"
Pug和Express結合,參考這個指南。npm
生產環境配置json
Express中環境變量NODE_ENV用來標識當前應用是在開發環境仍是生產環境。Express和Pug會根據這個環境變量自動修改一些配置選項,爲用戶提供友好的「開箱即用」的使用體驗。
例如,在Express中使用Pug時,當process.env.NODE_ENV是「production」,compileDebug選項是false,默認狀況下它是true。
能夠經過設置app.locals或者res.locals爲true或者false來覆蓋compileDebug和cache的默認選項值。還能夠經過Express的app.disable/enable('view cache')放來開修改cache選項。
更多細節,參考Express的api文檔。
本節詳細介紹Pug的api。
提示:能夠直接在瀏覽器的console中訪問這些api,例如:pub.render('p Hello world!')。
Pug中的方法參數以下:
filename:string
要編譯的文件的路徑和名字,使用相對路徑,保留後綴,默認是'.pug'。
basedir:string
全部文件的入口目錄。
doctype:string
若是沒有在Pug模板中指定doctype,能夠在這裏指定。
pretty:boolean | string
[不建議]在渲染HTML結果中添加一些空白字符串做爲空格,以便閱讀。若是使用字符串,則將改字符串做爲特定的空格使用(例如'\t'製表符)。不建議使用這個選項。因爲這個選項修改空白的解析和渲染方式,一般會帶來意想不到的後果,所以後續版本中這個選項將被取消。默認值爲false。
filters:object
自定義hash table過濾器,默認未定義。
self:boolean
使用默認自定義空間的locals,加快編譯速度,無需編寫變量,只須指定self.variable獲取locals。默認false。
debug:boolean
若是設置爲true,tokens和函數體將輸出到日誌中。
compileDebug:boolean
若是設置爲true,錯誤信息中將包含方法源碼便於排查(測試環境會頗有用)。該選項默認開啓,在正式環境關閉。
globals:Array<string>
在html模板中添加全局變量
cache:boolean
若是設置爲true,將緩存編譯函數。使用pug源文件的名字做爲cache的鍵值。render類的函數有這個選項,默認是false。
inlineRuntimeFunctions:boolean
內聯函數,代替require,在compileClient函數內,默認是true(沒必要包含運行時)。在其餘編譯和渲染類型的函數中,這個選項默認是flase。
name:string
模板函數名。只在compileClient函數內。默認值是‘template’。
將一個Pug模板編譯成一個函數,根據不一樣參數能夠被屢次渲染。
source:string
要編譯的pug源文件。
options:?options
選項對象。
returns:function
返回值是一個根據本地配置生成html的函數。
var pug = require('pug'); // 生成編譯函數 var fn = pug.compile('string of pug', options); // 調用編譯函數渲染html var html = fn(locals); // => '<string>of pug</string>'
將一個pug源文件編譯成一個方法,根據不一樣參數能夠屢次調用。
path:string
pug文件的路徑
options:?options
選項對象
returns:function
返回值是一個根據本地配置生成html的函數。
var pug = require('pug'); // 生成編譯函數 var fn = pug.compileFile('path to pug file', options); // 調用編譯函數渲染html var html = fn(locals); // => '<string>of pug</string>'
將一個pug源文件編譯成一段JavaScript函數字符串,能夠用在客戶端,調用這個函數返回html代碼。
path:string
pug文件的路徑
options:?options
選項對象
returns:function
返回值是一個JavaScript函數字符串
var pug = require('pug'); // 生成編譯函數 var fn = pug.compileClient('string of pug', options); // 調用編譯函數生成一個函數字符串,這個函數函數返回html代碼 var html = fn(locals); // => 'function template(locals) { return "<string>of pug</string>"; }'
和compileClient方法相似,不一樣之處在與這個函數返回一個dom結構對象。以下:
{ 'body': 'function (locals) {...}', 'dependencies': ['filename.pug'] }
僅當須要依賴來實現諸如監視Pug文件的更改之類的操做時,才應使用此方法。
編譯一個Pug源文件便覺得可在客戶端與pug運行時一塊兒使用的JavaScript字符串。
path:string
pug文件的路徑
options:?options
選項對象
options.name:string
若是在options選項中指定了name屬性,它將做爲客戶端模板函數的名稱
returns:function
返回值是一個JavaScript函數主體
假設下面是pug文件內容:
h1 This is a Pug template
h2 By #{author}
而後將pug文件編譯爲函數字符串。
var fs = require('fs'); var pug = require('pug'); // 將模板編譯爲函數字符串 var jsFunctionString = pug.compileFileClient('/path/to/pugFile.pug', {name: "fancyTemplateFun"}); // 能夠將全部模板便覺得template.js文件提供給客戶端 fs.writeFileSync("templates.js", jsFunctionString);
這是輸出函數字符串的樣子(寫到templates.js)
function fancyTemplateFun(locals) { var buf = []; var pug_mixins = {}; var pug_interp; var locals_for_with = (locals || {}); (function (author) { buf.push("<h1>This is a Pug template</h1><h2>By " + (pug.escape((pug_interp = author) == null ? '' : pug_interp)) + "</h2>"); }.call(this, "author" in locals_for_with ? locals_for_with.author : typeof author !== "undefined" ? author : undefined) ); return buf.join(""); }
除了編譯的模板以外,還要確保將Pug運行時(node_modules / pug / runtime.js)發送給客戶端。以下:
<!DOCTYPE html> <html> <head> <script src="/runtime.js"></script> <script src="/templates.js"></script> </head> <body> <h1>This is one fancy template.</h1> <script type="text/javascript"> var html = window.fancyTemplateFun({author: "enlore"}); var div = document.createElement("div"); div.innerHTML = html; document.body.appendChild(div); </script> </body> </html>
source:string
要渲染的pug模板
options:?options
選項對象
callback: ?function
一個接受渲染結果回調函數,能夠同步調用。
returns:function
返回值是一個JavaScript函數字符串
var pug = require('pug'); var html = pug.render('string of pug', options); // => '<string>of pug</string>'
path:string
pug文件的路徑
options:?options
選項對象
callback: ?function
一個接受渲染結果回調函數,能夠同步調用。
returns:function
返回值是HTML字符串
var pug = require('pug');
var html = pug.renderFile('path/to/file.pug', options);
// ...
自定義的過濾器
該對象的語義與選項中的過濾器語義相同,可是全局應用於全部Pug編譯。 當pug.filters和options.filters中都存在過濾器時,filters選項優先
提示:不推薦使用此屬性,而推薦使用濾鏡選項。
pug代碼中的標記屬性看起來和HTML(帶逗號),可是它的值只是普通的JavaScript。(注意:此頁面上的示例使用豎線字符(|)進行空白控制。)
a(href='google.com') Google | | a(class='button' href='google.com') Google | | a(class='button', href='google.com') Google
生成結果:
<a href="google.com">Google</a> <a class="button" href="google.com">Google</a> <a class="button" href="google.com">Google</a>
普通的JavaScript也能夠正常工做
- var authenticated = true body(class=authenticated ? 'authed' : 'anon')
<body class="authed"></body>
若是有多個屬性,還能夠把他們放在多行
input( type='checkbox' name='agreement' checked )
<input type="checkbox" name="agreement" checked="checked" />
若是你的JavaScript環境支持ES2015中的模板字符串(包含Node.js/io.js 1.0.0或後續版本),可使用模板字符串,若是屬性值很長,這將會頗有用。
input(data-json=` { "very-long": "piece of ", "data": true } `)
<input data-json=" { "very-long": "piece of ", "data": true } " />
若是屬性名中包可能會干擾JavaScript語法的含奇怪字符,請使用雙引號或者單引號區分不一樣的屬性。包含[]和()(Angular2中常用)
//- In this case, `(click)` is treated as a //- function call instead of a attribute name, //- resulting in the unusual error. div(class='div-class' (click)='play()')
報錯:
index.pug:4:11 2| //- function call instead of a attribute name, 3| //- resulting in the unusual error. > 4| div(class='div-class' (click)='play()') -----------------^ Syntax Error: Assigning to rvalue
正確的寫法是:
div(class='div-class', (click)='play()') div(class='div-class' '(click)'='play()')
<div class="div-class" (click)="play()"></div> <div class="div-class" (click)="play()"></div>
注意:Pug/Jade的早期版本支持插值語法,例如:
a(href="/#{url}") Link
再也不支持此語法。 替代方法以下。 (有關Pug v2與先前版本之間其餘不兼容性的更多信息,請參閱咱們的遷移指南。)
在屬性中包含變量,可使用如下替代方法:
1.在JavaScript中使用屬性
- var url = 'pug-test.html'; a(href='/' + url) Link | | - url = 'https://example.com/' a(href=url) Another link
結果以下:
<a href="/pug-test.html">Link</a> <a href="https://example.com/">Another link</a>
2.若是你的JavaScript環境支持ES2015(包含Node.js/io.js及更高版本),還可使用其語法來簡化屬性
- var btnType = 'info' - var btnSize = 'lg' button(type='button' class='btn btn-' + btnType + ' btn-' + btnSize) | | button(type='button' class=`btn btn-${btnType} btn-${btnSize}`)
結果以下
<button class="btn btn-info btn-lg" type="button"></button> <button class="btn btn-info btn-lg" type="button"></button>
默認狀況下,全部屬性均被轉義(即特殊字符被替換成轉義序列)以防止攻擊(例如:跨站攻擊)。若是須要使用特殊符號,請使用 != 代替 =
div(escaped="<code>") div(unescaped!="<code>")
結果以下:
<div escaped="<code>"></div> <div unescaped="<code>"></div>
注意:未轉義的代碼是很危險的。必須確保清除用戶輸入中沒有這種代碼,以免跨站腳本攻擊
pug中布爾類型的屬性被自動轉換爲true,false。若是未指定任何值,則假定爲true
input(type='checkbox' checked) | | input(type='checkbox' checked=true) | | input(type='checkbox' checked=false) | | input(type='checkbox' checked=true.toString())
結果以下:
<input type="checkbox" checked="checked" /> <input type="checkbox" checked="checked" /> <input type="checkbox" /> <input type="checkbox" checked="true" />
ps:用兩個豎線分隔換行,pug代碼比html代碼還長!這是搞什麼雞毛啊。
像普通屬性同樣,style屬性能夠是一個字符串;同時它也能夠是一個對象,這樣生成樣式會很方便。
a(style={color: 'red', background: 'green'})
<a style="color:red;background:green;"></a>
像普通屬性同樣,class屬性能夠是一個字符串;同時它也能夠是一個對象,這樣生成樣式會很方便。
- var classes = ['foo', 'bar', 'baz'] a(class=classes) | | //- class屬性能夠merge多個 a.bang(class=classes class=['bing'])
<a class="foo bar baz"></a> <a class="bang foo bar baz bing"></a>
它也能夠是將類名映射爲true或false的對象。 這對於應用條件類頗有用
- var currentUrl = '/about' a(class={active: currentUrl === '/'} href='/') Home | | a(class={active: currentUrl === '/about'} href='/about') About
<a href="/">Home</a> <a class="active" href="/about">About</a>
可使用.classname語法建立class屬性
a.button
<a class="button"></a>
因爲div是一個經常使用的dom,若是聲樂標籤名,默認生成一個dom,以下:
.content
<div class="content"></div>
ps:這個比較人性化
使用id語法#idname能夠建立元素
a#main-link
<a id="main-link"></a>
因爲div是一個經常使用的dom,若是聲樂標籤名,默認生成一個dom,以下:
#content
<div id="content"></div>
使用&attributes語法能夠建立多個自定義屬性
div#foo(data-bar="foo")&attributes({'data-foo': 'bar'})
<div id="foo" data-bar="foo" data-foo="bar"></div>
上面例子中啓示可使用object語法建立多個屬性,也可使用變量靈活處理。(參考:Mixin屬性)
- var attributes = {}; - attributes.class = 'baz'; div#foo(data-bar="foo")&attributes(attributes)
<div class="baz" id="foo" data-bar="foo"></div>
注意:使用&attributes屬性不會自動轉義,使用的時候必須注意驗證用戶輸入,避免跨站攻擊。使用mixin調用能夠自動完成轉義。
在JavaScript中case語法是和switch配合使用,pug中也可使用switch...case,以下:
- var friends = 10 case friends when 0 p you have no friends when 1 p you have a friend default p you have #{friends} friends
<p>you have 10 friends</p>
pug中的case語法和JavaScript中的switch相似,以下:
- var friends = 0 case friends when 0 when 1 p you have very few friends default p you have #{friends} friends
<p>you have very few friends</p>
可是和JavaScript中的case仍是有區別,pud中沒有不是switch-case,而是case-when,若是不想在switch語句中輸出任何內容,能夠添加一個顯式的break,以下:
- var friends = 0 case friends when 0 - break when 1 p you have very few friends default p you have #{friends} friends
這個case語句不會輸出任何內容
case塊語法也能夠像下面這樣:
- var friends = 1 case friends when 0: p you have no friends when 1: p you have a friend default: p you have #{friends} friends
<p>you have a friend</p>
Pug容許在模版中編寫內聯JavaScript代碼。有三種類型的代碼:Unbuffered(未緩存?),Buffered(緩衝?)和Unescaped Buffered(未轉義的緩衝)
Unbuffered代碼以-開頭,注意這一句不會輸出任何內容
- for (var x = 0; x < 3; x++) li item
<li>item</li> <li>item</li> <li>item</li>
固然,也支持塊輸出:
- var list = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis"] each item in list li= item
<li>Uno</li> <li>Dos</li> <li>Tres</li> <li>Cuatro</li> <li>Cinco</li> <li>Seis</li>
Buffered代碼以=開頭。它先計算JavaScript表達式並輸出結果,爲安全起見,Buffered代碼首先轉義爲HTML
p = 'This code is <escaped>!'
<p>This code is <escaped>!</p>
它也能夠之內聯屬性編寫,並支持全部JavaScript表達式
p= 'This code is' + ' <escaped>!'
<p>This code is <escaped>!</p>
未轉義的Buffered代碼以!=開頭。它計算JavaScript表達式並輸出結果,可是輸出的Html代碼是未轉義的,所以對用戶而言是不安全的
p != 'This code is <strong>not</strong> escaped!'
<p>This code is <strong>not</strong> escaped!</p>
和轉義的Buffered代碼同樣,它能夠之內聯形式編寫屬性,支持全部的JavaScript表達式
p!= 'This code is' + ' <strong>not</strong> escaped!'
<p>This code is <strong>not</strong> escaped!</p>
注意:未轉義的Buffered代碼多是很是危險的。必須處理用戶輸入,避免跨站攻擊
緩衝註釋和JavaScript中的單行註釋同樣,它的行爲相似於標記標籤,渲染的時候生成html註釋。
// just some paragraphs p foo p bar
<!-- just some paragraphs--> <p>foo</p> <p>bar</p>
Pug還支持無緩衝註釋,只需在註釋開頭加上字符-。這種註釋只是對Pug代碼自己進行註釋,不會呈如今HTML中。
//- will not output within markup p foo p bar
<p>foo</p> <p>bar</p>
塊註釋方式以下:
body //- Comments for your template writers. Use as much text as you want. // Comments for your HTML readers. Use as much text as you want.
<body> <!--Comments for your HTML readers. Use as much text as you want.--> </body>
Pug中的條件註釋和html同樣,沒有特殊的語法。(條件註釋是爲舊版本的Internet Explorer添加回退標記的一種特殊方法。)
Pug中以<開頭被視爲純文本,普通的JavaScript條件註釋在Pug中能夠正常工做。
doctype html <!--[if IE 8]> <html lang="en" class="lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html lang="en"> <!--<![endif]--> body p Supporting old web browsers is a pain. </html>
<!DOCTYPE html> <!--[if IE 8]> <html lang="en" class="lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html lang="en"> <!--<![endif]--> <body> <p>Supporting old web browsers is a pain.</p> </body> </html>
Pug中條件語句能夠不使用括號包裹
- var user = { description: 'foo bar baz' } - var authorised = false #user if user.description h2.green Description p.description= user.description else if authorised h2.blue Description p.description. User has no description, why not add one... else h2.red Description p.description User has no description
<div id="user"> <h2 class="green">Description</h2> <p class="description">foo bar baz</p> </div>
Pug還提供條件判斷語句unless,它和if是相反的,以下兩種判斷是等價的。
unless user.isAnonymous p You're logged in as #{user.name}
if !user.isAnonymous p You're logged in as #{user.name}
doctype html
<!DOCTYPE html>
經常使用文檔內省有一些快捷方式:
doctype html
<!DOCTYPE html>
doctype xml
<?xml version="1.0" encoding="utf-8" ?>
doctype transitional
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
doctype strict
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
doctype frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
doctype 1.1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
doctype basic
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
doctype mobile
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
doctype plist
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
還能夠自定義本身的文檔類型,以下:
doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">
除了在輸出中緩衝外,Pug中的doctype還可能影響編譯。 例如,自動關閉的標籤是否以/>或>結尾取決因而否指定了HTML或XML。 布爾屬性的輸出也可能會受到影響。
若是因爲其餘緣由沒法使用doctype關鍵字(例如,僅渲染HTML片斷),可是仍然但願指定模板的doctype,則能夠經過doctype選項進行操做。
var pug = require('pug'); var source = 'img(src="foo.png")'; pug.render(source); // => '<img src="foo.png"/>' pug.render(source, {doctype: 'xml'}); // => '<img src="foo.png"></img>' pug.render(source, {doctype: 'html'}); // => '<img src="foo.png">'
過濾器容許在Pug模板中使用其餘的語言,他們做爲一塊文本輸入。要將選項傳遞給過濾器,須要在過濾器後的括號內添加(就像標記屬性同樣)例如:
:less(ieCompat=false)
全部JSTransformer模塊均可以用做Pug過濾器。 流行的過濾器包括:babel,:uglify-js,:scss和:markdown-it。 請查看JSTransformer的文檔,以瞭解特定過濾器支持的選項。
若是找不到適合您的用例的過濾器,則能夠編寫本身的自定義過濾器。
例如,若是您但願可以在Pug模板中使用CoffeeScript和Markdown(使用Markdown-it渲染器),則首先要確保已安裝如下插件:
$ npm install --save jstransformer-coffee-script $ npm install --save jstransformer-markdown-it
如今,您應該可以使用如下模板渲染:
:markdown-it(linkify langPrefix='highlight-') # Markdown Markdown document with http://links.com and ```js var codeBlocks; ``` script :coffee-script console.log 'This is coffee script'
<h1>Markdown</h1> <p>Markdown document with <a href="http://links.com">http://links.com</a> and</p> <pre><code class="highlight-js">var codeBlocks; </code></pre> <script> (function() { console.log('This is coffee script'); }).call(this); </script>
警告:過濾器在編譯時渲染。 這使它們快速運行,但也意味着它們不能支持動態內容或選項。默認狀況下,瀏覽器中的編譯沒法訪問基於JSTransformer的篩選器,除非JSTransformer模塊已明確經過CommonJS平臺打包(例如Browserify或Webpack)。 實際上,您正當前這個頁面正式使用使用Browserify打包使得過濾器在瀏覽器中可用。在服務器上預編譯的模板沒有此限制。
若是過濾器的內容比較短,甚至能夠像使用標籤那樣使用過濾器。
p :markdown-it(inline) **BOLD TEXT** p. In the midst of a large amount of plain text, suddenly a wild #[:markdown-it(inline) *Markdown*] appeared.
<p><strong>BOLD TEXT</strong></p> <p>In the midst of a large amount of plain text, suddenly a wild <em>Markdown</em> appeared. </p>
在使用過濾器的時候,能夠經過包含語法將外部文件包含進來。
能夠在同一文本快上應用多個過濾器,爲此只需在同一行使用過濾器語法。
過濾器以相反的順序應用。 文本首先傳遞到最後一個過濾器; 而後,結果將傳遞到倒數第二個過濾器,依此類推。在如下示例中,腳本首先由babel轉換,而後由cdata-js轉換。
script :cdata-js:babel(presets=['es2015']) const myFunc = () => `This is ES2015 in a CD${'ATA'}`;
f.default.existsSync is not a function
經過filters選項,能夠定義自定義過濾器
options.filters = { 'my-own-filter': function (text, options) { if (options.addStart) text = 'Start\n' + text; if (options.addEnd) text = text + '\nEnd'; return text; } };
p :my-own-filter(addStart addEnd) Filter Body
<p> Start Filter Body End </p>
包含語法容許在一個Pug文件中包含另外一個Pug文件。
//- index.pug doctype html html include includes/head.pug body h1 My Site p Welcome to my super lame site. include includes/foot.pug
//- includes/head.pug head title My Site script(src='/javascripts/jquery.js') script(src='/javascripts/app.js')
//- includes/foot.pug footer#footer p Copyright (c) foobar
結果以下:
<!DOCTYPE html> <html> <head> <title>My Site</title> <script src="/javascripts/jquery.js"></script> <script src="/javascripts/app.js"></script> </head> <body> <h1>My Site</h1> <p>Welcome to my super lame site.</p> <footer id="footer"> <p>Copyright (c) foobar</p> </footer> </body> </html>
若是使用絕對路徑,可使用options.basedir變量拼接,不然按照相對當前文件的路徑解析。
若是沒有後綴,.pug將做爲默認後綴。
包含的文件不是pug,則當作純文原本處理。
//- index.pug doctype html html head style include style.css body h1 My Site p Welcome to my super lame site. script include script.js
/* style.css */ h1 { color: red; }
// script.js console.log('You are awesome');
<!DOCTYPE html> <html> <head> <style> /* style.css */ h1 { color: red; } </style> </head> <body> <h1>My Site</h1> <p>Welcome to my super lame site.</p> <script> // script.js console.log('You are awesome'); </script> </body> </html>
能夠將過濾器與當前Pug文件結合使用。
//- index.pug doctype html html head title An Article body include:markdown-it article.md
# article.md This is an article written in markdown.
<!DOCTYPE html> <html> <head> <title>An Article</title> </head> <body> <h1>article.md</h1> <p>This is an article written in markdown.</p> </body> </html>
Pug支持模板繼承,模板繼承經過關鍵字「block」和「extends」實現。在模板中,block關鍵字表示這個塊在子模塊中能夠被替換。此過程是遞歸的。下面示例定義了頭部,塊內容和腳。
//- layout.pug html head title My Site - #{title} block scripts script(src='/jquery.js') body block content block foot #footer p some footer content
建立新Pug文件來繼承上面的Pug模板,在新的文件中使用extends關鍵字來繼承,而後Pug模板中的block塊會被繼承下來。
注意foot塊沒有定義,因此使用父模板中的fug塊,輸出「some footer content」。而其餘塊將在自身基礎上繼承父模板的內容。
//- page-a.pug extends layout.pug block scripts script(src='/jquery.js') script(src='/pets.js') block content h1= title - var pets = ['cat', 'dog'] each petName in pets include pet.pug
//- pet.pug p= petName
還能夠覆蓋某個塊以提供其餘的塊,在下面例子中,content塊中暴露了sidebar和primary塊(可是子模塊能夠徹底覆蓋掉content)
//- sub-layout.pug extends layout.pug block content .sidebar block sidebar p nothing .primary block primary p nothing
//- page-b.pug extends sub-layout.pug block content .sidebar block sidebar p nothing .primary block primary p nothing
Pug容許替換(默認),前置,後置一個塊。
假設您但願在每一個頁面的標題塊中都包含默認腳本。 您能夠這樣作:
//- layout.pug html head block head script(src='/vendor/jquery.js') script(src='/vendor/caustic.js') body block content
例如,如今考慮您的JavaScript遊戲頁面。 您須要一些與遊戲相關的腳本以及這些默認腳本。 您能夠簡單地添加塊:
//- page.pug extends layout.pug block append head script(src='/vendor/three.js') script(src='/game.js')
在使用append,prepend的時候能夠省去block關鍵字,以下:
//- page.pug extends layout append head script(src='/vendor/three.js') script(src='/game.js')
Pug的模板繼承是一項強大的功能,可以讓您將複雜的頁面模板結構拆分爲更小,更簡單的文件。 可是,若是將許多模板連接在一塊兒,則可能會使頁面複雜得不可維護。
請注意,只有命名塊和混合定義能夠出如今子模板的頂層(未縮進)。 這個很重要! 父模板定義頁面的總體結構,子模板只能附加,添加或替換特定的標記和邏輯塊。 若是子模板試圖在塊外添加內容,Pug將沒法知道將其放置在最終頁面的何處。
使用未緩衝的代碼,若是須要在子模塊中使用變量,則可使用下面幾種不一樣的方法:
出於一樣的緣由,Pug的緩衝註釋不能出如今擴展模板的頂層:它們產生的HTML註釋在生成的HTML中無處渲染。 (可是,無緩衝的Pug註釋仍然能夠)
Pug提供多種方式在html中插入一個值。
下面例子中title,author,theGreat變量做爲本地變量被插入到代碼中。
- var title = "On Dogs: Man's Best Friend"; - var author = "enlore"; - var theGreat = "<span>escape!</span>"; h1= title p Written with love by #{author} p This will be safe: #{theGreat}
<h1>On Dogs: Man's Best Friend</h1> <p>Written with love by enlore</p> <p>This will be safe: <span>escape!</span></p>
title演示的是最基本的使用方法,再是在#{}中使用變量將會被轉義,並將結果緩衝到要渲染的模板中。
還可使用表達式,只要是合法的,任何地方均可以使用。
- var msg = "not my inside voice"; p This is #{msg.toUpperCase()}
<p>This is NOT MY INSIDE VOICE</p>
Pug能夠自動找出判斷表達式是否結束,甚至能夠包含未轉義的符號,例如}
p No escaping for #{'}'}!
<p>No escaping for }!</p>
若是想在html中輸出#{,能夠將其轉義,或者使用插值。
p Escaping works with \#{interpolation} p Interpolation works with #{'#{interpolation}'} too!
<p>Escaping works with #{interpolation}</p> <p>Interpolation works with #{interpolation} too!</p>
能夠將未轉義的字符串緩衝在模板中。
- var riskyBusiness = "<em>Some of the girls are wearing my mother's clothing.</em>"; .quote p Joel: !{riskyBusiness}
<div class="quote"> <p>Joel: <em>Some of the girls are wearing my mother's clothing.</em></p> </div>
注意:若是原內容來自用戶輸入,則將未轉義的內容緩衝到模板中可能帶來很大的風險。永遠不要相信用戶的輸入。
不只可使用JavaScript插入變量,還能夠在Pug內容中插入標籤,以下:
p. This is a very long and boring paragraph that spans multiple lines. Suddenly there is a #[strong strongly worded phrase] that cannot be #[em ignored]. p. And here's an example of an interpolated tag with an attribute: #[q(lang="es") ¡Hola Mundo!]
<p>This is a very long and boring paragraph that spans multiple lines. Suddenly there is a <strong>strongly worded phrase</strong> that cannot be <em>ignored</em>.</p> <p>And here's an example of an interpolated tag with an attribute: <q lang="es">¡Hola Mundo!</q></p>
您能夠經過編寫與Pug內聯的HTML標籤來完成相同的事,可是,編寫Pug的目的是什麼? 將內嵌的Pug標籤聲明包裝在#[]中,它將被評估並緩衝到其包含標籤的內容中。
默認狀況下,Pug會刪除標記以前和以後全部的空格,以下:
p | If I don't write the paragraph with tag interpolation, tags like strong strong | and em em | might produce unexpected results. p. If I do, whitespace is #[strong respected] and #[em everybody] is happy.
<p>If I don't write the paragraph with tag interpolation, tags like<strong>strong</strong>and<em>em</em>might produce unexpected results.</p> <p>If I do, whitespace is <strong>respected</strong> and <em>everybody</em> is happy.</p>
有關此主題的更多討論,請參見Plain Text。
Pug中支持兩種方式的循環輸出:each和while
Pug中第一種循環輸出語法each能夠迭代模板中的數組和對象。
ul each val in [1, 2, 3, 4, 5] li= val
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul>
循環中能夠從第二個參數中獲取當前index
ul each val, index in ['zero', 'one', 'two'] li= index + ': ' + val
<ul> <li>0: zero</li> <li>1: one</li> <li>2: two</li> </ul>
Pug中甚至能夠迭代中獲取對象的key
ul each val, index in {1:'one',2:'two',3:'three'} li= index + ': ' + val
<ul> <li>1: one</li> <li>2: two</li> <li>3: three</li> </ul>
要迭代的對象或數組只是純JavaScript。 所以,它能夠是變量,也能夠是函數調用的結果,或者幾乎是其餘任何東西。
- var values = []; ul each val in values.length ? values : ['There are no values'] li= val
<ul> <li>There are no values</li> </ul>
若是數組或對象不包含要迭代的值,則還能夠添加一個else塊,該塊將被執行。 如下等效於上面的示例:
- var values = []; ul each val in values li= val else li There are no values
<ul> <li>There are no values</li> </ul>
還可使用for關鍵字代替each,效果是同樣的。
還可使用while來迭代,以下:
- var n = 0; ul while n < 4 li= n++
<ul> <li>0</li> <li>1</li> <li>2</li> <li>3</li> </ul>
Mixins容許建立可重用的塊。
//- Declaration mixin list ul li foo li bar li baz //- Use +list +list
<ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul> <ul> <li>foo</li> <li>bar</li> <li>baz</li> </ul>
Mixins容許傳入參數
mixin pet(name) li.pet= name ul +pet('cat') +pet('dog') +pet('pig')
<ul> <li class="pet">cat</li> <li class="pet">dog</li> <li class="pet">pig</li> </ul>
Mixins還可使用Pug塊做爲內容:
mixin article(title) .article .article-wrapper h1= title if block block else p No content provided +article('Hello world') +article('Hello world') p This is my p Amazing article
<div class="article"> <div class="article-wrapper"> <h1>Hello world</h1> <p>No content provided</p> </div> </div> <div class="article"> <div class="article-wrapper"> <h1>Hello world</h1> <p>This is my</p> <p>Amazing article</p> </div> </div>
混合還能夠傳入一個隱式參數,能夠用來給屬性賦值
mixin link(href, name)
//- attributes == {class: "btn"}
a(class!=attributes.class href=href)= name
+link('/foo', 'foo')(class="btn")
<a class="btn" href="/foo">foo</a>
注意:默認狀況下,屬性中的值已被轉義! 您應該使用!=以免再次轉義它們。 (另請參見未轉義的屬性。)
能夠在混合中使用&attributes:
mixin link(href, name) a(href=href)&attributes(attributes)= name +link('/foo', 'foo')(class="btn")
<a class="btn" href="/foo">foo</a>
注意:語法+ link(class =「 btn」)也是有效的,而且等價於+ link()(class =「 btn」),由於Pug會嘗試檢測括號的內容是屬性仍是參數。 可是,建議您使用第二種語法,由於您沒有明確傳遞任何參數,而且確保第一個括號是參數列表。
還能夠設置參數的默認值,和ES6中設置函數的默認參數值是相似的:
//- Declaration mixin article(title='Default Title') .article .article-wrapper h1= title //- Use +article() +article('Hello world')
<div class="article"> <div class="article-wrapper"> <h1>Default Title</h1> </div> </div> <div class="article"> <div class="article-wrapper"> <h1>Hello world</h1> </div> </div>
在Mixins中可使用解析參數來傳遞多個參數
mixin list(id, ...items) ul(id=id) each item in items li= item +list('my-list', 1, 2, 3, 4)
<ul id="my-list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>
Pug提供了四種獲取純文本的方法-即將未經處理的代碼,文本渲染在HTML中,有時候會頗有用。
純文本仍然使用標記和字符串插值,但該行的第一個單詞不是Pug標記。 而且因爲不會轉義純文本,所以您還能夠包括文字HTML。
一個常見的缺陷是在渲染的HTML中使用空白,將在後面討論。
插入純文本最先的方式是使用內斂標籤。第一個詞是標籤名,後面全部內容都是標籤的內容。若是內容很短或者不介意這一行內容太長,這樣是沒有任何問題的。
p This is plain old <em>text</em> content.
<p>This is plain old <em>text</em> content.</p>
當整行以左尖括號(<)開頭時,它們也被視爲純文本,有時不方便的地方編寫文字HTML標籤頗有用。 例如,一種用例是條件註釋。 因爲文字HTML標記不會獲得處理,所以與Pug標記不一樣,它們不會自動關閉。
<html> body p Indenting the body tag here would make no difference. p HTML itself isn't whitespace-sensitive. </html>
<html> <body> <p>Indenting the body tag here would make no difference.</p> <p>HTML itself isn't whitespace-sensitive.</p> </body> </html>
將純文本添加到模板的另外一種方法是在行的前面加上豎線字符(|)。 如咱們稍後在「空白內容」部分中所述,此方法對於將純文本與內聯標籤混合頗有用。
p | The pipe always goes at the beginning of its own line, | not counting indentation.
<p>The pipe always goes at the beginning of its own line, not counting indentation.</p>
一般,您可能但願標籤中包含大塊文本。 一個很好的例子是在script和style標籤中編寫JavaScript和CSS代碼。 爲此,只需添加一個逗號, 若是標籤具備屬性,則在標籤名稱以後,或者在右括號以後。
注意在tag和逗號之間不能有空格,標籤的純文本內容必須縮進一級。
script. if (usingPug) console.log('you are awesome') else console.log('use pug')
<script> if (usingPug) console.log('you are awesome') else console.log('use pug') </script>
還能夠在tag標籤內部再使用逗號建立一個塊:
div
p This text belongs to the paragraph tag.
br
.
This text belongs to the div tag.
<div> <p>This text belongs to the paragraph tag.</p><br/>This text belongs to the div tag.</div>
空格控制
處理HTML中的空白多是學習Pug最麻煩的地方,不過掌握竅門以後就很容易了。只須要記住兩點:
因此,Pug刪除了標籤之間的空格,保留標籤內部的空格。這樣能夠控制是否能夠在tag或者純文本中出的空格。甚至單詞之間的空格。
| You put the em em pha | sis on the wrong syl em la | ble.
You put the em<em>pha</em>sis on the wrong syl<em>la</em>ble.
去掉空格須要考慮控制標籤和文本是否鏈接在一塊兒。
a ...sentence ending with a link
| .
<a>...sentence ending with a link</a>.
若是須要添加空格,參考下面方法
添加一個或者多個豎線,表示空白的管道符,在HTMl渲染的時候就會有空格出現。
| Don't | button#self-destruct touch | | me!
Don't <button id="self-destruct">touch</button> me!
若是你的內嵌標籤不須要太多屬性,能夠在純文本中使用標籤值或者HTML
p. Using regular tags can help keep your lines short, but interpolated tags may be easier to #[em visualize] whether the tags and text are whitespace-separated.
<p>Using regular tags can help keep your lines short, but interpolated tags may be easier to <em>visualize</em> whether the tags and text are whitespace-separated.</p>
根據須要的空格,能夠在文本的開頭(在塊縮進,豎線字符和/或標記以後)添加一個額外的空格。 或者,您能夠在文本末尾添加尾隨空格。
| Hey, check out a(href="http://example.biz/kitteh.png") this picture | of my cat!
| Hey, check out
a(href="http://example.biz/kitteh.png") this picture
| of my cat!
上面的解決方案能夠很好地工做,可是確定會有些危險:默認狀況下,許多代碼編輯器都會在保存時刪除尾隨空格。 你的同時可能必須配置編輯器,以防止自動刪除部空格。