/ajax/libs/dustjs-linkedin/0.4.0/dust-core.js
JavaScript | 577 lines | 492 code | 72 blank | 13 comment | 84 complexity | a07f22f7292ac6926aff7b513045f817 MD5 | raw file
- //
- // Dust - Asynchronous Templating v0.4.0
- // http://akdubya.github.com/dustjs
- //
- // Copyright (c) 2010, Aleksander Williams
- // Released under the MIT License.
- //
- var dust = {};
- (function(dust) {
- dust.cache = {};
- dust.register = function(name, tmpl) {
- if (!name) return;
- dust.cache[name] = tmpl;
- };
- dust.render = function(name, context, callback) {
- var chunk = new Stub(callback).head;
- dust.load(name, chunk, Context.wrap(context)).end();
- };
- dust.stream = function(name, context) {
- var stream = new Stream();
- dust.nextTick(function() {
- dust.load(name, stream.head, Context.wrap(context)).end();
- });
- return stream;
- };
- dust.renderSource = function(source, context, callback) {
- return dust.compileFn(source)(context, callback);
- };
- dust.compileFn = function(source, name) {
- var tmpl = dust.loadSource(dust.compile(source, name));
- return function(context, callback) {
- var master = callback ? new Stub(callback) : new Stream();
- dust.nextTick(function() {
- tmpl(master.head, Context.wrap(context)).end();
- });
- return master;
- }
- };
- dust.load = function(name, chunk, context) {
- var tmpl = dust.cache[name];
- if (tmpl) {
- return tmpl(chunk, context);
- } else {
- if (dust.onLoad) {
- return chunk.map(function(chunk) {
- dust.onLoad(name, function(err, src) {
- if (err) return chunk.setError(err);
- if (!dust.cache[name]) dust.loadSource(dust.compile(src, name));
- dust.cache[name](chunk, context).end();
- });
- });
- }
- return chunk.setError(new Error("Template Not Found: " + name));
- }
- };
- dust.loadSource = function(source, path) {
- return eval(source);
- };
- if (Array.isArray) {
- dust.isArray = Array.isArray;
- } else {
- dust.isArray = function(arr) {
- return Object.prototype.toString.call(arr) == "[object Array]";
- };
- }
- dust.nextTick = function(callback) {
- setTimeout(callback, 0);
- }
- dust.isEmpty = function(value) {
- if (dust.isArray(value) && !value.length) return true;
- if (value === 0) return false;
- return (!value);
- };
- dust.filter = function(string, auto, filters) {
- if (filters) {
- for (var i=0, len=filters.length; i<len; i++) {
- var name = filters[i];
- if (name === "s") {
- auto = null;
- } else {
- string = dust.filters[name](string);
- }
- }
- }
- if (auto) {
- string = dust.filters[auto](string);
- }
- return string;
- };
- dust.filters = {
- h: function(value) { return dust.escapeHtml(value); },
- j: function(value) { return dust.escapeJs(value); },
- u: encodeURI,
- uc: encodeURIComponent
- }
- function Context(stack, global, blocks) {
- this.stack = stack;
- this.global = global;
- this.blocks = blocks;
- }
- dust.makeBase = function(global) {
- return new Context(new Stack(), global);
- }
- Context.wrap = function(context) {
- if (context instanceof Context) {
- return context;
- }
- return new Context(new Stack(context));
- }
- Context.prototype.get = function(key) {
- var ctx = this.stack, value;
- while(ctx) {
- if (ctx.isObject) {
- value = ctx.head[key];
- if (!(value === undefined)) {
- return value;
- }
- }
- ctx = ctx.tail;
- }
- return this.global ? this.global[key] : undefined;
- };
- Context.prototype.getPath = function(cur, down) {
- var ctx = this.stack,
- len = down.length;
- if (cur && len === 0) return ctx.head;
- if (!ctx.isObject) return undefined;
- ctx = ctx.head;
- var i = 0;
- while(ctx && i < len) {
- ctx = ctx[down[i]];
- i++;
- }
- return ctx;
- };
- Context.prototype.push = function(head, idx, len) {
- if( head ){
- // loop index for a block section
- head['$idx'] = idx;
- // loop size for a block section
- head['$len'] = len;
- }
- return new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks);
- };
- Context.prototype.rebase = function(head) {
- return new Context(new Stack(head), this.global, this.blocks);
- };
- Context.prototype.current = function() {
- return this.stack.head;
- };
- Context.prototype.getBlock = function(key) {
- var blocks = this.blocks;
- if (!blocks) return;
- var len = blocks.length, fn;
- while (len--) {
- fn = blocks[len][key];
- if (fn) return fn;
- }
- }
- Context.prototype.shiftBlocks = function(locals) {
- var blocks = this.blocks;
- if (locals) {
- if (!blocks) {
- newBlocks = [locals];
- } else {
- newBlocks = blocks.concat([locals]);
- }
- return new Context(this.stack, this.global, newBlocks);
- }
- return this;
- }
- function Stack(head, tail, idx, len) {
- this.tail = tail;
- this.isObject = !dust.isArray(head) && head && typeof head === "object";
- this.head = head;
- this.index = idx;
- this.of = len;
- }
- function Stub(callback) {
- this.head = new Chunk(this);
- this.callback = callback;
- this.out = '';
- }
- Stub.prototype.flush = function() {
- var chunk = this.head;
- while (chunk) {
- if (chunk.flushable) {
- this.out += chunk.data;
- } else if (chunk.error) {
- this.callback(chunk.error);
- this.flush = function() {};
- return;
- } else {
- return;
- }
- chunk = chunk.next;
- this.head = chunk;
- }
- this.callback(null, this.out);
- }
- function Stream() {
- this.head = new Chunk(this);
- }
- Stream.prototype.flush = function() {
- var chunk = this.head;
- while(chunk) {
- if (chunk.flushable) {
- this.emit('data', chunk.data);
- } else if (chunk.error) {
- this.emit('error', chunk.error);
- this.flush = function() {};
- return;
- } else {
- return;
- }
- chunk = chunk.next;
- this.head = chunk;
- }
- this.emit('end');
- }
- Stream.prototype.emit = function(type, data) {
- var events = this.events;
- if (events && events[type]) {
- events[type](data);
- }
- }
- Stream.prototype.on = function(type, callback) {
- if (!this.events) {
- this.events = {};
- }
- this.events[type] = callback;
- return this;
- }
- function Chunk(root, next, taps) {
- this.root = root;
- this.next = next;
- this.data = '';
- this.flushable = false;
- this.taps = taps;
- }
- Chunk.prototype.write = function(data) {
- var taps = this.taps;
- if (taps) {
- data = taps.go(data);
- }
- this.data += data;
- return this;
- }
- Chunk.prototype.end = function(data) {
- if (data) {
- this.write(data);
- }
- this.flushable = true;
- this.root.flush();
- return this;
- }
- Chunk.prototype.map = function(callback) {
- var cursor = new Chunk(this.root, this.next, this.taps),
- branch = new Chunk(this.root, cursor, this.taps);
- this.next = branch;
- this.flushable = true;
- callback(branch);
- return cursor;
- }
- Chunk.prototype.tap = function(tap) {
- var taps = this.taps;
- if (taps) {
- this.taps = taps.push(tap);
- } else {
- this.taps = new Tap(tap);
- }
- return this;
- }
- Chunk.prototype.untap = function() {
- this.taps = this.taps.tail;
- return this;
- }
- Chunk.prototype.render = function(body, context) {
- return body(this, context);
- }
- Chunk.prototype.reference = function(elem, context, auto, filters) {
- if (typeof elem === "function") {
- elem = elem(this, context, null, {auto: auto, filters: filters});
- if (elem instanceof Chunk) {
- return elem;
- }
- }
- if (!dust.isEmpty(elem)) {
- return this.write(dust.filter(elem, auto, filters));
- } else {
- return this;
- }
- };
- Chunk.prototype.section = function(elem, context, bodies, params) {
- if (typeof elem === "function") {
- elem = elem(this, context, bodies, params);
- if (elem instanceof Chunk) {
- return elem;
- }
- }
- var body = bodies.block,
- skip = bodies['else'];
- if (params) {
- context = context.push(params);
- }
- if (dust.isArray(elem)) {
- if (body) {
- var len = elem.length, chunk = this;
- for (var i=0; i<len; i++) {
- chunk = body(chunk, context.push(elem[i], i, len));
- }
- return chunk;
- }
- } else if (elem === true) {
- if (body) return body(this, context);
- } else if (elem || elem === 0) {
- if (body) return body(this, context.push(elem));
- } else if (skip) {
- return skip(this, context);
- }
- return this;
- };
- Chunk.prototype.exists = function(elem, context, bodies) {
- var body = bodies.block,
- skip = bodies['else'];
- if (!dust.isEmpty(elem)) {
- if (body) return body(this, context);
- } else if (skip) {
- return skip(this, context);
- }
- return this;
- }
- Chunk.prototype.notexists = function(elem, context, bodies) {
- var body = bodies.block,
- skip = bodies['else'];
- if (dust.isEmpty(elem)) {
- if (body) return body(this, context);
- } else if (skip) {
- return skip(this, context);
- }
- return this;
- }
- Chunk.prototype.block = function(elem, context, bodies) {
- var body = bodies.block;
- if (elem) {
- body = elem;
- }
- if (body) {
- return body(this, context);
- }
- return this;
- };
- Chunk.prototype.partial = function(elem, context, params) {
- var ctx = context.stack, tempHead = ctx.head;
- if (params){
- //put the params context second to match what section does. {.} matches the current context without parameters
- //remove head
- context = context.rebase(ctx.tail);
- //put params on
- context = context.push(params);
- //reattach the head
- context = context.push(tempHead);
- }
- if (typeof elem === "function") {
- return this.capture(elem, context, function(name, chunk) {
- dust.load(name, chunk, context).end();
- });
- }
- return dust.load(elem, this, context);
- };
- Chunk.prototype.helper = function(name, context, bodies, params) {
- return dust.helpers[name](this, context, bodies, params);
- };
- Chunk.prototype.capture = function(body, context, callback) {
- return this.map(function(chunk) {
- var stub = new Stub(function(err, out) {
- if (err) {
- chunk.setError(err);
- } else {
- callback(out, chunk);
- }
- });
- body(stub.head, context).end();
- });
- };
- Chunk.prototype.setError = function(err) {
- this.error = err;
- this.root.flush();
- return this;
- };
- function Tap(head, tail) {
- this.head = head;
- this.tail = tail;
- }
- Tap.prototype.push = function(tap) {
- return new Tap(tap, this);
- };
- Tap.prototype.go = function(value) {
- var tap = this;
- while(tap) {
- value = tap.head(value);
- tap = tap.tail;
- }
- return value;
- };
- var HCHARS = new RegExp(/[&<>\"]/),
- AMP = /&/g,
- LT = /</g,
- GT = />/g,
- QUOT = /\"/g;
- dust.escapeHtml = function(s) {
- if (typeof s === "string") {
- if (!HCHARS.test(s)) {
- return s;
- }
- return s.replace(AMP,'&').replace(LT,'<').replace(GT,'>').replace(QUOT,'"');
- }
- return s;
- };
- var BS = /\\/g,
- CR = /\r/g,
- LS = /\u2028/g,
- PS = /\u2029/g,
- NL = /\n/g,
- LF = /\f/g,
- SQ = /'/g,
- DQ = /"/g,
- TB = /\t/g;
- dust.escapeJs = function(s) {
- if (typeof s === "string") {
- return s
- .replace(BS, '\\\\')
- .replace(DQ, '\\"')
- .replace(SQ, "\\'")
- .replace(CR, '\\r')
- .replace(LS, '\\u2028')
- .replace(PS, '\\u2029')
- .replace(NL, '\\n')
- .replace(LF, '\\f')
- .replace(TB, "\\t");
- }
- return s;
- };
- })(dust);
- if (typeof exports !== "undefined") {
- dust.helpers = require("./dust-helpers").helpers;
- if (typeof process !== "undefined" && typeof window === "undefined") {
- require('./server')(dust);
- }
- module.exports = dust;
- }
- (function(dust){
-
- var helpers = {
-
- sep: function(chunk, context, bodies) {
- if (context.stack.index === context.stack.of - 1) {
- return chunk;
- }
- return bodies.block(chunk, context);
- },
- idx: function(chunk, context, bodies) {
- return bodies.block(chunk, context.push(context.stack.index));
- },
-
- "if": function( chunk, context, bodies, params ){
- var cond = ( params.cond );
-
- if( params && params.cond ){
- // resolve dust references in the expression
- if( typeof cond === "function" ){
- cond = '';
- chunk.tap( function( data ){
- cond += data;
- return '';
- } ).render( params.cond, context ).untap();
- if( cond === '' ){
- cond = false;
- }
- }
- // eval expressions with no dust references
- if( eval( cond ) ){
- return chunk.render( bodies.block, context );
- }
- if( bodies['else'] ){
- return chunk.render( bodies['else'], context );
- }
- }
- // no condition
- else {
- if( window.console ){
- window.console.log( "No expression given!" );
- }
- }
- return chunk;
- }
- };
- dust.helpers = helpers;
- })(typeof exports !== 'undefined' ? exports : window.dust);