Jade 语法

FarBox 的模板引擎采用的改良过的 Jade 语法, 并最终编译为 HTML 形态的 Jinja 模板结构
为了保证语法的一致性以及更加的简洁,我们呈现的的模板文件仅仅支持 .jade 后缀的 Jade 语法,并且所有的表述中涉及到的代码也都是 Jade 语法。
当然,在某些场合,如果你比较了解 Jinja 的模板语法,HTML 和 Jade 两者是可以同时混用的。

Jade语法

FarBox将我们常见的文件目录结构转化为了可快速查询的数据库调用,而 API 的主要功能在于渲染页面(HTML)。

如果用传统的角度看待,那么,一个是后端,一个是前端。所以,我们一直在寻找可以融合前后端的API语法,经过改造的Jade语法,基本上满足了我们的设计需求。

Jade是Node.js世界中的一种Python式缩进的模板语法,经过改造后,FarBox 可以将.jade文件转化为Jinja2的语法。

为了更好地进行编写,你可能需要为自己的代码编辑器/IDE增加Jade语法的支持插件。

HTML标签、id、class

.class_name this is content
// 默认会创建div标签,最终结果为<div class="class_name">this is content</div>

tag_name.class_name
// 最终结果为<tag_name class="class_name"></tag_name>

p.class1.class2.class3
// 多个class,最终结果为<p class="class1 class2 class3"></p>

a.a_class(href="#", title="this is a link")
// 多个属性,用`,`隔开,最终结果为<a class="a_class" href="#" title="this is a link"></a>

span#dom_id.class_name_1.class_name_2 this is content
// 最终结果为<span id="dom_id", class="class_name_1 class_name_2">this is content</span>

.class_name this is line 1
| this is line 2
//
     | 可以在跨行中使用 (一般也不会用,代码看起来不好看),最终结果为
     <div class="class_name">
        this is line 1
        this is line 2
    </div>

变量与HTML标签

如果直接将具体的变量与HTML标签关联起来,可参照如下语法。

node post.content  
//等同于<node>post.content</node>

var = post.content
// 等同于 {%set var = post.content %}, 是一个变量的赋值

node= post.content 
// =号左前无空格,则是将变量转为HTML标签,等同于<node>{{ post.content }}</node>

node= 'post.content'
// 等同于<node>post.content</node>

如果HTML标签中有其它属性定义的。

a(href=post.url)= post.title
// 等同于 <a href={{post.url}}>{{post.title}}</a>

a(href='/post/{{post.url_path}}')= post.title
// 这混合了Jinja2语法,等同于 <a href='/post/{{post.url_path}}'>{{post.title}}</a>

for/if

head
    if site.title == 'test'
        title= site.title
    elif site.title == 'a test too'
        title= site.title + '!!!'
    else
        title= 'blank'
    
body
    for post in posts
        h1= post.title

注意!!
不要将 if/else/for 跟其它逻辑混合, 以下语法都是错误的,会导致模板编译无法成功。

if post
    +post.content
else no content 
// 这样写的else是无效的,既不是HTML标签,也不是逻辑判断; 要空一行先。

运行函数

+resposne.raise_404()

注意: 有些时候,如果没有增加+,不会视为 API 的调用,而是转为 HTML 的标签,请务必注意。

跨行

当代码比较长的时候,可以在行尾输入\,然后重起一行,在最终编译的过程中,会自动重新合并为一行。

冒号分割

有些时候,过度的缩进语法,会让模板看起来有些错乱,特别是if / else / for 等逻辑下。那么在简单逻辑下,可以使用 : 进行分割,并不会影响最终的效果。

.posts: .posts_container
    for post in posts: .post
        .title= post.title

实际等价于:

.posts
    .posts_container
        for post in posts
            .post
                .title= post.title

Jade的继承与引用

extends与include

这分别对应Jinja2语法中的extendsinclude,但跟Jinja2不一样的是,不要增加单引号/或双引号。

extends base.jade
// 等价于 Jinja 中的  {% extends 'base.jade' %}

include include/comments.jade
// 等价于 Jinja 中的{% include 'include/comments.jade' %}

macro/mixin

macro 是Jinja2的概念,mixin则是Jade的概念; 在 FarBox 中两者基本等价。

macro相当于自定义一个函数,然后在模板中进行调用,另外,我们也支持对这个函数产生的数据进行缓存,前提是使用cache_为开头的函数名。

Jinja2是Python语言创建的模板框架,所以macro的定义方式,基本接近Python语言中函数的定义。

mixin sidebar(name)
    h1= name
    p this is sidebar

// 等价于 Jinja 中
{% macro sidebar(name) %}
    <h1>{{ name }}</h1>
    <p> this is sidebar </p>
{% endmacro %}

如果macro的定义与调用,都在同一个模板页,则后面可以直接使用这个定义出来的函数。

from "mixins.jade" import get_url
// 等价于 Jinja 中的 {% from "mixins.jade" import get_url %}

macro相对于include而言,它的性能其实更高,include不可避免地会带入一个变量空间,从而造成混乱的概率增加;而macro的内容如果不调用外部变量,则可以有效地防止变量空间混乱的情况。
但一般情况下,视自己如何方便,如何来即可。

Jade与Jinja2语法融合

常见例子

在.jade的模板文件中,可以在单独一行中使用Jinja2的语法。

extends base.jade
from "mixins" import make_posts_list
{{ site.title }}

Jade的自动补全

FarBox 对.jade后缀的模板文件进行编译过程中,会进行以下的自动补全:

  • 如果没有声明doctype,则默认补全为doctype html
  • 如果是html类型的doctype,但没有声明charset的,默认补全为utf8