• pug参考文档


    1. API

    express框架的渲染模板有多种选择,官方的例子是Pug,网上找了一下,Pug没有可以参考的中文文档,于是自己动手丰衣足食。翻译水平一般,各位凑合着看吧。

    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文件,例如在routessite.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结果中添加一些空白字符串作为空格,以便阅读。如果使用字符串,则将改字符串作为特定的空格使用(例如' '制表符)。不建议使用这个选项。由于这个选项修改空白的解析和渲染方式,通常会带来意想不到的后果,因此后续版本中这个选项将被取消。默认值为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文件的路径

    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.compileClient(source, ?options)

    将一个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>"; }' 

    pug.compileClientWithDependenciesTracked(source, ?options)

    和compileClient方法类似,不同之处在与这个函数返回一个dom结构对象。如下:

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

    仅当需要依赖来实现诸如监视Pug文件的更改之类的操作时,才应使用此方法。

    pug.compileFileClient(path, ?options)

    编译一个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> 

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

    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>

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

    path:string

    pug文件的路径

    options:?options

    选项对象

    callback: ?function

    一个接受渲染结果回调函数,可以同步调用。

    returns:function

    返回值是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>

    由于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调用可以自动完成转义。

    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
    ' + text;
        if (options.addEnd)   text = text + '
    End';
        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

  • 相关阅读:
    leetcode 128. Longest Consecutive Sequence 最长连续序列(中等)
    《Effective Java》第54条:返回零长度的数组或者集合,而不是null
    EasyPlayer如何获取点播视频流的时间戳?
    TSINGSEE智能分析网关简介及说明
    TSINGSEE青犀视频AI智能分析网关重磅发布!
    TSINGSEE青犀视频智能分析网关平台首页为何取消四分屏展示?
    基于AI深度学习的安全帽检测算法,如何应用在实际场景中?
    AI智能分析网关包含哪些深度学习算法?如何赋能场景应用?
    AI智能分析网关包含哪些深度学习算法?如何赋能场景应用?
    TSINGSEE智能分析网关如何添加通道?
  • 原文地址:https://www.cnblogs.com/tylerdonet/p/11883833.html
Copyright © 2020-2023  润新知