A Lightweight JavaScript Template Engine.

Overview

Juicer 中文文档

当前最新版本: 0.6.14

Juicer 是一个高效、轻量的前端 (Javascript) 模板引擎,使用 Juicer 可以是你的代码实现数据和视图模型的分离(MVC)。除此之外,它还可以在 Node.js 环境中运行。

你可以在遵守 MIT Licence 的前提下随意使用并分发它。Juicer 代码完全开源并托管在 Github 上,如果你在使用的过程中发现什么 Bug 抑或是一些好的建议都欢迎在 Github Issue 上提交。

名字的由来

倘若我们把数据比作新鲜可口的水果,把模板看做是水,Juicer 就是把水果和水榨出我们需要的HTML代码片段的榨汁机。

Juicer 的引入

<script type="text/javascript" src="juicer-min.js></script>

* 使用方法

> 编译模板并根据所给的数据立即渲染出结果.

juicer(tpl, data);

> 仅编译模版暂不渲染,它会返回一个可重用的编译后的函数.

var compiled_tpl = juicer(tpl);

> 根据给定的数据,对之前编译好的模板进行数据渲染.

var compiled_tpl = juicer(tpl);
var html = compiled_tpl.render(data);

> 注册/注销自定义函数(对象),在下边 ${变量} 中会有实例.

juicer.register('function_name', function);
juicer.unregister('function_name');

> 自定义模板语法边界符,下边是 Juicer 默认的边界符。你可以借此解决 Juicer 模板语法同某些后端语言模板语法冲突的情况.

juicer.set({
	'tag::operationOpen': '{@',
	'tag::operationClose': '}',
	'tag::interpolateOpen': '${',
	'tag::interpolateClose': '}',
	'tag::noneencodeOpen': '$${',
	'tag::noneencodeClose': '}',
	'tag::commentOpen': '{#',
	'tag::commentClose': '}'
});

默认参数配置

{
	cache:          true [false],
	strip:          true [false],
	errorhandling:  true [false],
	detection:      true [false]
}

默认配置是 Juicer 推荐的使用方式,如果你使用过程中的确需要更改这些参数,可以这么做:

逐条参数更改:

juicer.set('strip',false);
juicer.set('cache',false);

批量参数更改:

juicer.set({
	'strip': false,
	'cache': false
};

Juicer 默认会对编译后的模板进行缓存,从而避免同一模板多次数据渲染时候重复编译所耗的时间,如无特殊需要,强烈不建议关闭默认参数中的 cache,这么做将会令 Juicer 缓存失效从而降低性能.

* 语法

a. ${变量}

使用 ${} 输出变量值,其中_为对数据源的引用(如${_},常用于数据源为数组的情况)。支持自定义函数(通过自定义函数你可以实现很多有趣的功能,类似 ${data|links} 就可以通过事先定义的自定义函数 links 直接对 data 拼装出<a href=".." alt=".." /> ).

${name}
${name|function}
${name|function, arg1, arg2}

让我们通过一个例子演示一下自定义函数的奇妙用法吧.

var json = {
	links: [
		{href: 'http://juicer.name', alt: 'Juicer'},
		{href: 'http://benben.cc', alt: 'Benben'},
		{href: 'http://ued.taobao.com', alt: 'Taobao UED'}
	]
};

var tpl = [
	'{@each links as item}',
		'${item|links_build} <br />',
	'{@/each}'
].join('');

var links = function(data) {
	return '<a href="' + data.href + '" alt="' + data.alt + '" />';
};

juicer.register('links_build', links); //注册自定义函数 juicer(tpl, json);

上述代码执行后我们会发现结果是这样的:

&lt;a href=&quot;http://juicer.name&quot; alt=&quot;Juicer&quot; <br />
&lt;a href=&quot;http://benben.cc&quot; alt=&quot;Benben&quot; <br />
&lt;a href=&quot;http://ued.taobao.com&quot; alt=&quot;Taobao UED&quot; <br />

可以看得出,结果被转义了,如果我们上边使用 $${item|links} 就会得到我们预期的结果,这就是下边即将提到的避免转义。

转义/避免转义

出于安全角度的考虑,${变量} 在输出之前会对其内容进行转义,如果你不想输出结果被转义,可以使用 $${变量} 来避免这种情况。例如:

var json = {
	value: '&lt;strong&gt;juicer&lt;/strong&gt;'
};

var escape_tpl='${value}';
var unescape_tpl='$${value}';

juicer(escape_tpl, json); //输出 '&lt;strong&gt;juicer&lt;/strong&gt;'
juicer(unescape_tpl, json); //输出 '<strong>juicer</strong>'

b. 循环遍历 {@each} ... {@/each}

如果你需要对数组进行循环遍历的操作,就可以像这样使用 each .

{@each list as item}
	${item.prop}
{@/each}

如果遍历过程中想取得当前的索引值,也很方便.

{@each list as item, index}
	${item.prop}
	${index} //当前索引
{@/each}

c. 判断 {@if} ... {@else if} ... {@else} ... {@/if}

我们也会经常碰到对数据进行逻辑判断的时候.

{@each list as item,index}
	{@if index===3}
		the index is 3, the value is ${item.prop}
	{@else if index === 4}
		the index is 4, the value is ${item.prop}
	{@else}
		the index is not 3, the value is ${item.prop}
	{@/if}
{@/each}

d. 注释 {# 注释内容}

为了后续代码的可维护性和可读性,我们可以在模板中增加注释.

{# 这里是注释内容}

e. 辅助循环 {@each i in range(m, n)}

辅助循环是 Juicer 为你精心设置的一个语法糖,也许你会在某种情境下需要它.

{@each i in range(5, 10)}
	${i}; //输出 5;6;7;8;9;
{@/each}

f. 子模板嵌套 {@include tpl, data}

子模板嵌套可以让你更灵活的组织你的模板代码,除了可以引入在数据中指定的子模板外,当然你也可以通过指定字符串#id使用写在script标签中的模板代码.

HTML代码:

<script type="text/juicer" id="subTpl">
	I'm sub content, ${name}
</script>

Javascript 代码:

var tpl = 'Hi, {@include "#subTpl", subData}, End.';

juicer(tpl, {
	subData: {
		name: 'juicer'
	}
});

//输出 Hi, I'm sub content, juicer, End.
//或者通过数据引入子模板,下述代码也将会有相同的渲染结果:

var tpl = 'Hi, {@include subTpl, subData}, End.';

juicer(tpl, {
	subTpl: "I'm sub content, ${name}",
	subData: {
		name: 'juicer'
	}
});

* 在 Node.js 环境中运行

在命令行中执行:
npm install juicer

在代码中这么引入:
var juicer = require('juicer');
var html = juicer(tpl, data);

在 Express.js 框架中使用

在 Express 2.x 系列版本中:

npm install juicer
var juicer = require('juicer');
app.set('view engine', 'html');
app.register('.html', {
	compile: function(str, options) {
		return juicer.compile(str, options).render;
	}
});

在 Express 3.x 系列版本中:

npm install juicer
var juicer = require('juicer');
var fs = require('fs');
app.set('view engine', 'html');
app.engine('html', function(path, options, fn){
	fs.readFile(path, 'utf8', function(err, str){
		if (err) return fn(err);
		str = juicer(str, options);
		fn(null, str);
	});
});

在 Express 4.x 系列版本中:

var juicerExpressAdapter = require('juicer-express-adapter');
app.set('view engine', 'html');
app.engine('html', juicerExpressAdapter);

在命令行预编译模板文件:

npm install -g juicer
juicer example.juicer.tmpl -f example.js

// type `juicer` after install for more help.
// 全局模式安装 `juicer` 后,在命令行下输入 `juicer` 可以获得更多帮助信息。

为模板引擎设置外部Cache存储:

var juicer = require('juicer');
var LRUCache = require('lru-native');
var cache = new LRUCache({ maxElements: 1000 });

juicer.set('cachestore', cache);

* 一个完整的例子

HTML 代码:

<script id="tpl" type="text/template">
	<ul>
		{@each list as it,index}
			<li>${it.name} (index: ${index})</li>
		{@/each}
		{@each blah as it}
			<li>
				num: ${it.num} <br />
				{@if it.num==3}
					{@each it.inner as it2}
						${it2.time} <br />
					{@/each}
				{@/if}
			</li>
		{@/each}
	</ul>
</script>

Javascript 代码:

var data = {
	list: [
		{name:' guokai', show: true},
		{name:' benben', show: false},
		{name:' dierbaby', show: true}
	],
	blah: [
		{num: 1},
		{num: 2},
		{num: 3, inner:[
			{'time': '15:00'},
			{'time': '16:00'},
			{'time': '17:00'},
			{'time': '18:00'}
		]},
		{num: 4}
	]
};

var tpl = document.getElementById('tpl').innerHTML;
var html = juicer(tpl, data);
Comments
  • juicer编译异常

    juicer编译异常

    • 问题:juicer编译模板时在firfox14下报如下异常, chrome下正常, 异常信息:Juicer Compile Exception: Illegal operation on WrappedNative prototype object
    • 模板:``` ['', '${name}(${memberIds.length})', ''].join('')
    opened by chenboxiang 9
  • run in ie occur exception : Juicer Compile Exception: Unexpected token

    run in ie occur exception : Juicer Compile Exception: Unexpected token

    Hello,everyone,

    I just use juicer to use my custom function,and in ie it occur exception, and in chrome and firfox is well,

    my custom function is in below: function default_value(self_value, default_val){ if(!self_value || self_value == "undefined") { return default_val; } return self_value;

    } juicer.register('default', default_value);

    and the template write like: image

    if I delete the "|default,80", it can run well in ie.

    doesn't id support custom function?

    does anybody know? Thanks a lot.

    opened by Shelley 7
  • 建议forstart规则中增加对数组运算符的过滤,否则有些嵌套的循环无法使用

    建议forstart规则中增加对数组运算符的过滤,否则有些嵌套的循环无法使用

    //临时修改了一下,

    var forstart = juicer.tags.operationOpen + 'each\s_([\w.[]]?)\s_as\s(\w_?)\s_(,\s_\w_?)?' + juicer.tags.operationClose;

    //这样就可以使用如下的循环方式了

    {@each a as name, i} {@each b[name] as item, index} ${item.foo} {@/each} {@/each}

    否则会提示错误:

    “Missing catch or finally after try”

    opened by ciroyong 4
  • 循环会污染外部变量

    循环会污染外部变量

    var html = '{@each array as item} ${item} {@/each} ${item}' var data = {array: [1,2], item: 'a'} juicer.to_html(html, data)

    输出===> " 1 2 2"

    预期应该是 "1 2 a"

    opened by wuguixiong 4
  • npm 获取错误

    npm 获取错误

    命令: npm install --save juicer 错误信息: npm WARN package.json [email protected] No description npm WARN package.json [email protected] No repository field. npm WARN package.json [email protected] No README data npm WARN package.json [email protected] No license field. npm ERR! fetch failed http://registry.npmjs.org/juicer/-/juicer-0.2.2.tgz npm WARN retry will retry, error on last attempt: Error: fetch failed with status code 404 npm ERR! fetch failed http://registry.npmjs.org/juicer/-/juicer-0.2.2.tgz npm WARN retry will retry, error on last attempt: Error: fetch failed with status code 404 npm ERR! fetch failed http://registry.npmjs.org/juicer/-/juicer-0.2.2.tgz npm ERR! Windows_NT 6.3.9600 ...

    opened by 4781121 3
  • 0.6.9 版本不支持ie8

    0.6.9 版本不支持ie8

    0.6.9 再ie8下报不支持trim方法。 master 中 juicer.min.js 不是最新版,不支持 helper 标签 helper 标签中 定义一个 字符串,中间不能出现 双斜杠 "//" 比如 定义一个 var str = ‘https://github.com/’ ,就会报错。

    暂时就发现这么多。

    opened by igfz 2
  • 标签属性被转成小写的问题。

    标签属性被转成小写的问题。

    我有一段模板定义:

    <script id="resourceConfiguration" type="text/template">
    <div id="resourcePropertiesDiv" configurationCode="${_.configurationCode}">
        ......
    </div>
    </script>
    

    juicer渲染后变成:

    <div id="resourcePropertiesDiv" configurationcode="xxx">
        ......
    </div>
    

    它把div的configurationCode属性名转成configurationcode小写了? 是我哪里用错了吗,多谢。

    opened by sleeplessman 2
  • 比如我的json里面没有内容,是一个空的数组,我怎么获得这个数组的长度

    比如我的json里面没有内容,是一个空的数组,我怎么获得这个数组的长度

    json代码如下: var data={ "httop10" : [{"pid":"1", "ftpuser":"tianyi", "domainname":"webabc.com", "starttime":"2013-1-1", "endtime":"2015-1-1", "state":"1"}]}; 这个是正常情况下,我可以获得一条结果,但是有的查询条件得到的结果是空的。 var data={ "httop10" : []}; 我想在判断如果是空的话,我要显示一句话 “没有查询到结果”,但是没有找到判断这个长度的方法。 {@each httop10 as ht,index} {@if httop10.length==0} //关键是这句,是不是如果是空的,就不会走each了 没有查询到结果 {@else} {#这事正常情况下的} {@/if} {/each} 起初是认为不走each那里了,我把那一句单独拿到了外面 {@if httop10.length==0}

    没有查询到结果 {/if} 这样会输出一个undefined。。。 麻烦告诉一下怎么解决,谢谢了
    opened by tianyirenjian 2
  •  辅助循环中的m,n不能使用变量

    辅助循环中的m,n不能使用变量

    辅助循环 {@each i in range(m, n)}中,当m或n用变量就会出错,提示“Juicer Compile Exception: Missing catch or finally after try” 代码: var seat_data={ desks:[ {type:"VIP席",amount:20}, {type:"普通席",amount:60} ] } 模板: {@each desks as desk} {@each i in range(1,desk.amount)} ${i} {@/each} {@/each}

    opened by moxuanyuan 2
  • twice loop problem!

    twice loop problem!

    var data={ list:[ {name:'guokai',show:true}, {name:'benben',show:false}, {name:'dier',show:true} ], blah:[ {num:1}, {num:2,inner:[ {'time':'15:00'}, {'time':'16:00'} ]}, {num:3,inner:[ {'time':'15:00'}, {'time':'16:00'}, {'time':'16:00'} ]}, {num:4,inner:[ {'time':'15:00'}, {'time':'16:00'}, {'time':'16:00'} ]} ] }; var tpl=[ '

      ', '{@each list as it,k}', '
    • ${it.name} (index: ${k})
    • ', '{@/each}', '{# first level attribute must specify the "data." prefix}', '{@each blah as it}', '
    • ', 'num: ${it.num}
      ', '{@if it.num==3}', '{@each it.inner as it2}', '${it2.time}
      ', '{@/each}', '{@/if}', '
    • ', '{@/each}', '
    ' ].join('');

    console.log(juicer(tpl,data));

    output only three items limited by the max number of the second loop,but the first loop have full 4 items?why?

    opened by xcnbanba 2
  • Fail to compile when write a helper in template, which contains an URI

    Fail to compile when write a helper in template, which contains an URI

    I have a helper in template like below.

    <!--
    {@helper uri}
        function uri(input) {
            return 'http://github.com';
        }
    {@/helper}
    -->
    

    Then juicer raise an exception Juicer Compile Exception: Unexpected token ILLEGAL

    I think issue #76 is the same situation.

    opened by lordfriend 1
Lightweight JavaScript (ES6) tweening engine

Lightweight JavaScript (ES6) tweening library. EXAMPLES Examples collection DOCUMENTATION Purpose Install With npm Or fetch from CDN Basic usage Modul

Alexander Buzin 705 Dec 25, 2022
Minimal template engine with compiled output for JavaScript.

@fnando/seagull Minimal template engine with compiled output for JavaScript. Installation This package is available as a NPM package. To install it, u

Nando Vieira 5 Mar 1, 2022
A lightweight, powerful and highly extensible templating engine. In the browser or on Node.js, with or without jQuery.

JsRender: best-of-breed templating Simple and intuitive, powerful and extensible, lightning fast For templated content in the browser or on Node.js (w

Boris Moore 2.7k Jan 2, 2023
A simple and safe template engine.

TagScript A simple and safe template engine. Description TagScript is a drop in easy to use string interpreter that lets you provide users with ways o

Parbez 13 Dec 31, 2022
A template for a vanilla(no ui-framework) project with webgi engine in typescript using parcel bundler.

WebGi starter project A template for a vanilla(no ui-framework) project with webgi engine in typescript using parcel bundler. For the latest version a

null 40 Jan 3, 2023
Out-of-the-box MPA plugin for Vite, with html template engine and virtual files support.

vite-plugin-virtual-mpa Out-of-the-box MPA plugin for Vite, with html template engine and virtual files support, generate multiple files using only on

QinXuYang 21 Dec 16, 2022
A template for buildind scrollable landing pages with Gsap, ScrollTrigger and webgi engine in typescript using parcel bundler.

Threejs + GSAP + WEBGi 100% Free Course This is a template used in my fast course "building scrolable pages with ScrollTrigger and Threejs" for a vani

Anderson Mancini 62 Dec 17, 2022
EggyJS is a Javascript micro Library for simple, lightweight toast popups focused on being dependency-less, lightweight, quick and efficient.

EggyJS EggyJS is a Javascript micro Library for simple, lightweight toast popups. The goal of this library was to create something that meets the foll

Sam 10 Jan 8, 2023
Discord.js bot starter template, Slash Commands only (Raymond forced me to make a bot template)

boat-template Raymond forced me to make a bot template This template is meant is just for stupidness ig Getting Started Rename the config.example.ts t

Drxckzyz tha idiot 3 Jan 5, 2022
Tiny and powerful JavaScript full-text search engine for browser and Node

MiniSearch MiniSearch is a tiny but powerful in-memory fulltext search engine written in JavaScript. It is respectful of resources, and it can comfort

Luca Ongaro 2k Jan 3, 2023
Javascript engine to make fast games.

G3 Javascript Basic javascript engine to make fast games and write clean code. ??️ Example code: const g3 = new G3() const Window = g3.createWindow("

Starship Code 2 Feb 13, 2022
cptcity for the Google Earth Engine JavaScript API (Code Editor)

cptcity for the Google Earth Engine JavaScript API (Code Editor) ?? Table of contents What is Google Earth Engine ? What is cptcity and why ? Top of t

Antony Barja 17 Aug 2, 2022
An ASCII (technically PETSCII :)) "Game Engine" for JavaScript

Announcement! I'm putting this project on hold, because I remembered how much I hate JavaScript. (Please don't take offense, it's just my preference.)

eboatwright 16 Nov 12, 2022
The 2D Game Engine written on JavaScript.

CherryEngine The 2D Game Engine written in JavaScript. NEW UPDATE Version 1.2 Added: TypeObjectError.js Changed: static methods are not static now, yo

> sazix 4 Oct 26, 2022
Tempo is an easy, intuitive JavaScript rendering engine that enables you to craft data templates in pure HTML.

Tempo 2.0 Tempo is an easy, intuitive JavaScript rendering engine that enables you to craft data templates in pure HTML. Why use Tempo? Clear separati

Twigkit 707 Jan 3, 2023
High performance JavaScript templating engine

art-template English document | 中文文档 art-template is a simple and superfast templating engine that optimizes template rendering speed by scope pre-dec

糖饼 9.7k Jan 3, 2023
Jcrop - The Javascript Image Cropping Engine

Jcrop Image Cropping Plugin Jcrop is the quick and easy way to add image cropping functionality to your web application. It combines the ease-of-use o

Kelly Hallman 4.3k Dec 20, 2022
Search Engine for YouTuber Ali Abdaal's videos

Ali Abdaal Search Engine This is a personalized search engine for my favorite YouTubers, Ali Abdaal. I used selenium to scrape all his videos, youtube

Hassan El Mghari 24 Oct 14, 2022
An example project to how to integrate Chat Engine into a marketplace

Add Chat to Your Marketplace This is a example online marketplace with Chat Engine fully integrated. It's meant to help people building online marketp

Adam La Morre 13 Dec 22, 2022