天天看點

pug參考文檔

express架構的渲染模闆有多種選擇,官方的例子是Pug,網上找了一下,Pug沒有可以參考的中文文檔,于是自己動手豐衣足食。翻譯水準一般,各位湊合着看吧。

1. API

ps:最近搜尋了一下,中文文檔還是有的,不知道為啥當時死活百度上找不到。

https://pug.bootcss.com/api/getting-started.html

https://pugjs.org/zh-cn/api/reference.html

1.1 開始

安裝

通過npm安裝pug:

$ npm install pug      

簡介

Pug的渲染語句很簡單,pug.compile()方法将pug源檔案(.pug)源檔案編譯成一個帶參數(‘locals’,pug檔案的路徑)方法,然後調用這個結果方法就能購生成一段由pug檔案轉化成的html字元串。

這個pug.compile()方法可以重複使用,生成各種各樣的html字元串來渲染html。

//- template.pug,pug檔案
p #{name}'s Pug source code!      

調用方法:

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方式:

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>"      

1.2 和Express整合

Pug和Express結合,參考這個指南。

生産環境配置

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文檔。

1.2.1 配置渲染引擎

1. 在app.js檔案中設定渲染引擎:

// 設定渲染引擎
app.set('views', path.join(__dirname, './views'));
app.set('view engine', 'pug');      

2. 在view目錄下建立pug檔案

3. 在routers檔案夾下的檔案中建立路由以渲染pug檔案,例如在routes\site.js檔案中:

const express = require('express');
const router = express.Router();
/* GET users listing. */
router.get('/', function (req, res, next) {
  res.render('index', { title: '首頁', message: '首頁' })
});
module.exports = router;      

1.3 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’。

1.3.2 方法

pug.compile(source, ?options)

将一個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.compileFile(path, ?options)

将一個pug源檔案編譯成一個方法,根據不同參數可以多次調用。

path:string

pug檔案的路徑

選項對象

var pug = require('pug');

// 生成編譯函數
var fn = pug.compileFile('path to pug file', options);

// 調用編譯函數渲染html
var html = fn(locals);
// => '<string>of pug</string>'       

pug.compileClient(source, ?options)

将一個pug源檔案編譯成一段JavaScript函數字元串,可以用在用戶端,調用這個函數傳回html代碼。

傳回值是一個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>"; }'       

pug.compileClientWithDependenciesTracked(source, ?options)

和compileClient方法類似,不同之處在與這個函數傳回一個dom結構對象。如下:

{
  'body': 'function (locals) {...}',
  'dependencies': ['filename.pug']
}      

僅當需要依賴來實作諸如監視Pug檔案的更改之類的操作時,才應使用此方法。

pug.compileFileClient(path, ?options)

編譯一個Pug源檔案便以為可在用戶端與pug運作時一起使用的JavaScript字元串。

options.name:string

如果在options選項中指定了name屬性,它将作為用戶端模闆函數的名稱

傳回值是一個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>       

pug.render(source, ?options, ?callback)

要渲染的pug模闆

callback: ?function

一個接受渲染結果回調函數,可以同步調用。

var pug = require('pug');

var html = pug.render('string of pug', options);
// => '<string>of pug</string>'       

pug.renderFile(path, ?options, ?callback)

傳回值是HTML字元串

var pug = require('pug');

var html = pug.renderFile('path/to/file.pug', options);
// ...       

1.4 filters選項

pug.filters

自定義的過濾器

該對象的語義與選項中的過濾器語義相同,但是全局應用于所有Pug編譯。 當pug.filters和options.filters中都存在過濾器時,filters選項優先

提示:不推薦使用此屬性,而推薦使用濾鏡選項。

2. 文法參考

2.1 屬性

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="
  {
    &quot;very-long&quot;: &quot;piece of &quot;,
    &quot;data&quot;: 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="&lt;code&gt;"></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屬性

像普通屬性一樣,style屬性可以是一個字元串;同時它也可以是一個對象,這樣生成樣式會很友善。

a(style={color: 'red', background: 'green'})       
<a style="color:red;background:green;"></a>       

class屬性

像普通屬性一樣,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>       

class選擇器文法

可以使用.classname文法建立class屬性

a.button      
<a class="button"></a>       

由于div是一個常用的dom,如果聲樂标簽名,預設生成一個dom,如下:

.content      
<div class="content"></div>       

ps:這個比較人性化

ID文法

使用id文法#idname可以建立元素

a#main-link      
<a id="main-link"></a>      
#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調用可以自動完成轉義。

2.2 Case文法

在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>       

Case

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>       

2.3 内聯代碼

Pug允許在模版中編寫内聯JavaScript代碼。有三種類型的代碼:Unbuffered(未緩存?),Buffered(緩沖?)和Unescaped Buffered(未轉義的緩沖)

Unbuffered Code

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 Code

Buffered代碼以=開頭。它先計算JavaScript表達式并輸出結果,為安全起見,Buffered代碼首先轉義為HTML

p
  = 'This code is <escaped>!'      
<p>This code is &lt;escaped&gt;!</p>       

它也可以以内聯屬性編寫,并支援所有JavaScript表達式

p= 'This code is' + ' <escaped>!'      
<p>This code is &lt;escaped&gt;!</p>       

Unescaped Buffered Code

未轉義的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代碼可能是非常危險的。必須處理使用者輸入,避免跨站攻擊

2.5 注釋

緩沖注釋和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>       

2.6 條件語句

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}       

2.7 文檔類型

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">       

Doctype選項

除了在輸出中緩沖外,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">'      

2.7 過濾器

過濾器允許在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>       

2.8 檔案包含

包含文法允許在一個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>       

2.8 模闆繼承

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允許替換(預設),前置,後置一個塊。

假設您希望在每個頁面的head塊中都包含預設腳本。 您可以這樣做:

//- 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的模闆繼承是一項強大的功能,可讓您将複雜的頁面模闆結構拆分為更小,更簡單的檔案。 但是,如果将許多模闆連結在一起,則可能會使頁面複雜得不可維護。

請注意,隻有命名塊(block)和混合定義可以出現在子模闆的頂層(未縮進),頂層不能出現其他内容,如lin(),script,和普通的标簽如div(class="content")。 這個很重要! 否則會報錯:Only named blocks and mixins can appear at the top level of an extending template。父模闆定義頁面的整體結構,子模闆隻能附加,添加或替換特定的标記和邏輯塊。 如果子模闆試圖在塊外添加内容,Pug将無法知道将其放置在最終頁面的何處。

使用未緩沖的代碼,如果需要在子子產品中使用變量,則可以使用下面幾種不同的方法:

  • 将變量添加到Pug選項對象,或在父模闆的未緩沖代碼中定義它們。 子模闆将繼承這些變量。
  • 在子模闆的塊中定義變量。 擴充模闆必須至少包含一個塊,否則将為空-隻需在此處定義變量即可。

出于同樣的原因,Pug的緩沖注釋不能出現在擴充模闆的頂層:它們産生的HTML注釋在生成的HTML中無處渲染。 (但是,無緩沖的Pug注釋仍然可以)

2.10 插值

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: &lt;span&gt;escape!&lt;/span&gt;</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。

2.11 循環輸出

Pug中支援兩種方式的循環輸出:each和while

each

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

還可以使用while來疊代,如下:

- var n = 0;
ul
  while n < 4
    li= n++       
<ul>
  <li>0</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>       

2.12 Mixins

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>       

2.13 純文字

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标簽很有用。 例如,一種用例是條件注釋。 由于文字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最麻煩的地方,不過掌握竅門之後就很容易了。隻需要記住兩點:

  1. Pug預設删除縮進,和元素間的所有空白。是以html結束符将和下一個html開始符相鄰。這對一些塊級元素(例如段落)是沒有問題的,因為他們在浏覽器中是單獨的段落(處理使用css的display屬性修)。但是如果确實需要在元素之間插入空格,參考下面第二條:
  2. 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!       

上面的解決方案可以很好地工作,但是肯定會有些危險:預設情況下,許多代碼編輯器都會在儲存時删除尾随空格。 你的同時可能必須配置編輯器,以防止自動删除部空格。

參考連接配接:https://pugjs.org/api/getting-started.html

作者:

Tyler Ning

出處:http://www.cnblogs.com/tylerdonet/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,如有問題,請微信聯系冬天裡的一把火

pug參考文檔

繼續閱讀