quintype-liquid 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/README.md +36 -0
- data/Rakefile +2 -0
- data/assets/javascripts/quintype-liquid.js.erb +34 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/quintype/liquid/file_system.rb +53 -0
- data/lib/quintype/liquid/liquid_template_caching_module.rb +27 -0
- data/lib/quintype/liquid/railtie.rb +19 -0
- data/lib/quintype/liquid/templates.rb +28 -0
- data/lib/quintype/liquid/version.rb +5 -0
- data/lib/quintype/liquid.rb +10 -0
- data/quintype-liquid.gemspec +24 -0
- data/vendor/assets/javascripts/liquid.js +1532 -0
- metadata +114 -0
@@ -0,0 +1,1532 @@
|
|
1
|
+
var Liquid = {
|
2
|
+
|
3
|
+
author: 'Matt McCray <darthapo@gmail.com>',
|
4
|
+
version: '1.3.2',
|
5
|
+
|
6
|
+
readTemplateFile: function(path) {
|
7
|
+
throw ("This liquid context does not allow includes.");
|
8
|
+
},
|
9
|
+
|
10
|
+
registerFilters: function(filters) {
|
11
|
+
Liquid.Template.registerFilter(filters);
|
12
|
+
},
|
13
|
+
|
14
|
+
parse: function(src) {
|
15
|
+
return Liquid.Template.parse(src);
|
16
|
+
}
|
17
|
+
|
18
|
+
};
|
19
|
+
|
20
|
+
Liquid.extensions = {};
|
21
|
+
Liquid.extensions.object = {};
|
22
|
+
|
23
|
+
Liquid.extensions.object.update = function(newObj) {
|
24
|
+
for (var p in newObj) {
|
25
|
+
this[p] = newObj[p];
|
26
|
+
}
|
27
|
+
|
28
|
+
return this;
|
29
|
+
};
|
30
|
+
|
31
|
+
Liquid.extensions.object.hasKey = function(arg) {
|
32
|
+
return !!this[arg];
|
33
|
+
};
|
34
|
+
|
35
|
+
Liquid.extensions.object.hasValue = function(arg) {
|
36
|
+
for (var p in this) {
|
37
|
+
if (this[p] == arg) return true;
|
38
|
+
}
|
39
|
+
|
40
|
+
return false;
|
41
|
+
};
|
42
|
+
|
43
|
+
Liquid.extensions.object.isEmpty = function(obj) {
|
44
|
+
if (!obj || Liquid.extensions.stringTools.strip(obj.toString()) === "") return true;
|
45
|
+
if (obj.length && obj.length > 0) return false;
|
46
|
+
if (typeof obj === 'number') return false;
|
47
|
+
|
48
|
+
for (var prop in obj) if (obj[prop]) return false;
|
49
|
+
return true;
|
50
|
+
};
|
51
|
+
|
52
|
+
|
53
|
+
Liquid.extensions.stringTools = {};
|
54
|
+
Liquid.extensions.stringTools.capitalize = function(str) {
|
55
|
+
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
|
56
|
+
};
|
57
|
+
|
58
|
+
Liquid.extensions.stringTools.strip = function(str) {
|
59
|
+
return str.replace(/^\s+/, '').replace(/\s+$/, '');
|
60
|
+
};
|
61
|
+
|
62
|
+
|
63
|
+
Liquid.extensions.arrayTools = {};
|
64
|
+
|
65
|
+
Liquid.extensions.arrayTools.last = function(array) {
|
66
|
+
return array[array.length - 1];
|
67
|
+
};
|
68
|
+
|
69
|
+
Liquid.extensions.arrayTools.indexOf = function(array, obj) {
|
70
|
+
for (var i=0; i<array.length; i++) {
|
71
|
+
if (array[i] == obj) return i;
|
72
|
+
}
|
73
|
+
return -1;
|
74
|
+
};
|
75
|
+
|
76
|
+
Liquid.extensions.arrayTools.map = function(obj, fun) {
|
77
|
+
var len = obj.length;
|
78
|
+
if (typeof fun != "function")
|
79
|
+
throw 'Liquid.extensions.arrayTools.map requires first argument to be a function';
|
80
|
+
|
81
|
+
var res = new Array(len);
|
82
|
+
var thisp = arguments[2];
|
83
|
+
for (var i = 0; i < len; i++) {
|
84
|
+
if (i in obj)
|
85
|
+
res[i] = fun.call(thisp, obj[i], i, obj);
|
86
|
+
}
|
87
|
+
return res;
|
88
|
+
};
|
89
|
+
|
90
|
+
Liquid.extensions.arrayTools.flatten = function(array) {
|
91
|
+
var len = array.length;
|
92
|
+
var arr = [];
|
93
|
+
for (var i = 0; i < len; i++) {
|
94
|
+
if (array[i] instanceof Array) {
|
95
|
+
arr = arr.concat(array[i]);
|
96
|
+
} else {
|
97
|
+
arr.push(array[i]);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
return arr;
|
102
|
+
};
|
103
|
+
|
104
|
+
Liquid.extensions.arrayTools.each = function(obj, fun) {
|
105
|
+
var len = obj.length;
|
106
|
+
if (typeof fun != "function") {
|
107
|
+
throw 'Liquid.extensions.arrayTools.each requires first argument to be a function';
|
108
|
+
}
|
109
|
+
|
110
|
+
var thisp = arguments[2];
|
111
|
+
for (var i = 0; i < len; i++) {
|
112
|
+
if (i in obj) {
|
113
|
+
fun.call(thisp, obj[i], i, obj);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
return null;
|
118
|
+
};
|
119
|
+
|
120
|
+
Liquid.extensions.arrayTools.include = function(array, arg) {
|
121
|
+
var len = array.length;
|
122
|
+
|
123
|
+
return Liquid.extensions.arrayTools.indexOf(array, arg) >= 0;
|
124
|
+
for (var i = 0; i < len; i++) {
|
125
|
+
if (arg == array[i]) return true;
|
126
|
+
}
|
127
|
+
|
128
|
+
return false;
|
129
|
+
};
|
130
|
+
/* Simple JavaScript Inheritance
|
131
|
+
* By John Resig http://ejohn.org/
|
132
|
+
* MIT Licensed.
|
133
|
+
*/
|
134
|
+
(function(){
|
135
|
+
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
|
136
|
+
|
137
|
+
this.Class = function(){};
|
138
|
+
|
139
|
+
this.Class.extend = function(prop) {
|
140
|
+
var _super = this.prototype;
|
141
|
+
|
142
|
+
initializing = true;
|
143
|
+
var prototype = new this();
|
144
|
+
initializing = false;
|
145
|
+
|
146
|
+
for (var name in prop) {
|
147
|
+
prototype[name] = typeof prop[name] == "function" &&
|
148
|
+
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
149
|
+
(function(name, fn){
|
150
|
+
return function() {
|
151
|
+
var tmp = this._super;
|
152
|
+
|
153
|
+
this._super = _super[name];
|
154
|
+
|
155
|
+
var ret = fn.apply(this, arguments);
|
156
|
+
this._super = tmp;
|
157
|
+
|
158
|
+
return ret;
|
159
|
+
};
|
160
|
+
})(name, prop[name]) :
|
161
|
+
prop[name];
|
162
|
+
}
|
163
|
+
|
164
|
+
function Class() {
|
165
|
+
if ( !initializing && this.init )
|
166
|
+
this.init.apply(this, arguments);
|
167
|
+
}
|
168
|
+
|
169
|
+
Class.prototype = prototype;
|
170
|
+
|
171
|
+
Class.prototype.constructor = Class;
|
172
|
+
|
173
|
+
Class.extend = arguments.callee;
|
174
|
+
|
175
|
+
return Class;
|
176
|
+
};
|
177
|
+
}).call(Liquid);
|
178
|
+
|
179
|
+
Liquid.Tag = Liquid.Class.extend({
|
180
|
+
|
181
|
+
init: function(tagName, markup, tokens) {
|
182
|
+
this.tagName = tagName;
|
183
|
+
this.markup = markup;
|
184
|
+
this.nodelist = this.nodelist || [];
|
185
|
+
this.parse(tokens);
|
186
|
+
},
|
187
|
+
|
188
|
+
parse: function(tokens) {
|
189
|
+
},
|
190
|
+
|
191
|
+
render: function(context) {
|
192
|
+
return '';
|
193
|
+
}
|
194
|
+
|
195
|
+
});
|
196
|
+
Liquid.Block = Liquid.Tag.extend({
|
197
|
+
|
198
|
+
init: function(tagName, markup, tokens){
|
199
|
+
this.blockName = tagName;
|
200
|
+
this.blockDelimiter = "end"+ this.blockName;
|
201
|
+
this._super(tagName, markup, tokens);
|
202
|
+
},
|
203
|
+
|
204
|
+
parse: function(tokens) {
|
205
|
+
if (!this.nodelist) this.nodelist = [];
|
206
|
+
this.nodelist.length = 0;
|
207
|
+
|
208
|
+
var token = tokens.shift();
|
209
|
+
tokens.push(''); // To ensure we don't lose the last token passed in...
|
210
|
+
while(tokens.length) {
|
211
|
+
|
212
|
+
if( /^\{\%/.test(token) ) { // It's a tag...
|
213
|
+
var tagParts = token.match(/^\{\%\s*(\w+)\s*(.*)?\%\}$/);
|
214
|
+
|
215
|
+
if(tagParts) {
|
216
|
+
if( this.blockDelimiter == tagParts[1] ) {
|
217
|
+
this.endTag();
|
218
|
+
return;
|
219
|
+
}
|
220
|
+
if( tagParts[1] in Liquid.Template.tags ) {
|
221
|
+
this.nodelist.push( new Liquid.Template.tags[tagParts[1]]( tagParts[1], tagParts[2], tokens ) );
|
222
|
+
} else {
|
223
|
+
this.unknownTag( tagParts[1], tagParts[2], tokens );
|
224
|
+
}
|
225
|
+
} else {
|
226
|
+
throw ( "Tag '"+ token +"' was not properly terminated with: %}");
|
227
|
+
}
|
228
|
+
} else if(/^\{\{/.test(token)) { // It's a variable...
|
229
|
+
this.nodelist.push( this.createVariable(token) );
|
230
|
+
} else { //if(token != '') {
|
231
|
+
this.nodelist.push( token );
|
232
|
+
} // Ignores tokens that are empty
|
233
|
+
token = tokens.shift(); // Assign the next token to loop again...
|
234
|
+
}
|
235
|
+
|
236
|
+
this.assertMissingDelimitation();
|
237
|
+
},
|
238
|
+
|
239
|
+
endTag: function() {},
|
240
|
+
|
241
|
+
unknownTag: function(tag, params, tokens) {
|
242
|
+
switch(tag) {
|
243
|
+
case 'else': throw (this.blockName +" tag does not expect else tag"); break;
|
244
|
+
case 'end': throw ("'end' is not a valid delimiter for "+ this.blockName +" tags. use "+ this.blockDelimiter); break;
|
245
|
+
default: throw ("Unknown tag: "+ tag);
|
246
|
+
}
|
247
|
+
},
|
248
|
+
|
249
|
+
createVariable: function(token) {
|
250
|
+
var match = token.match(/^\{\{(.*)\}\}$/);
|
251
|
+
if(match) { return new Liquid.Variable(match[1]); }
|
252
|
+
else { throw ("Variable '"+ token +"' was not properly terminated with: }}"); }
|
253
|
+
},
|
254
|
+
|
255
|
+
render: function(context) {
|
256
|
+
return this.renderAll(this.nodelist, context);
|
257
|
+
},
|
258
|
+
|
259
|
+
renderAll: function(list, context) {
|
260
|
+
return Liquid.extensions.arrayTools.map((list || []), function(token, i){
|
261
|
+
var output = '';
|
262
|
+
try { // hmmm... feels a little heavy
|
263
|
+
output = ( token['render'] ) ? token.render(context) : token;
|
264
|
+
} catch(e) {
|
265
|
+
output = context.handleError(e);
|
266
|
+
}
|
267
|
+
return output;
|
268
|
+
});
|
269
|
+
},
|
270
|
+
|
271
|
+
assertMissingDelimitation: function(){
|
272
|
+
throw (this.blockName +" tag was never closed");
|
273
|
+
}
|
274
|
+
});
|
275
|
+
Liquid.Document = Liquid.Block.extend({
|
276
|
+
|
277
|
+
init: function(tokens){
|
278
|
+
this.blockDelimiter = []; // [], really?
|
279
|
+
this.parse(tokens);
|
280
|
+
},
|
281
|
+
|
282
|
+
assertMissingDelimitation: function() {
|
283
|
+
}
|
284
|
+
});
|
285
|
+
Liquid.Strainer = Liquid.Class.extend({
|
286
|
+
|
287
|
+
init: function(context) {
|
288
|
+
this.context = context;
|
289
|
+
},
|
290
|
+
|
291
|
+
respondTo: function(methodName) {
|
292
|
+
methodName = methodName.toString();
|
293
|
+
if (methodName.match(/^__/)) return false;
|
294
|
+
if (Liquid.extensions.arrayTools.include(Liquid.Strainer.requiredMethods, methodName)) return false;
|
295
|
+
return (methodName in this);
|
296
|
+
}
|
297
|
+
});
|
298
|
+
|
299
|
+
Liquid.Strainer.filters = {};
|
300
|
+
|
301
|
+
Liquid.Strainer.globalFilter = function(filters) {
|
302
|
+
for (var f in filters) {
|
303
|
+
Liquid.Strainer.filters[f] = filters[f];
|
304
|
+
}
|
305
|
+
}
|
306
|
+
|
307
|
+
Liquid.Strainer.requiredMethods = ['respondTo', 'context'];
|
308
|
+
|
309
|
+
Liquid.Strainer.create = function(context) {
|
310
|
+
var strainer = new Liquid.Strainer(context);
|
311
|
+
for (var f in Liquid.Strainer.filters) {
|
312
|
+
strainer[f] = Liquid.Strainer.filters[f];
|
313
|
+
}
|
314
|
+
return strainer;
|
315
|
+
}
|
316
|
+
Liquid.Context = Liquid.Class.extend({
|
317
|
+
|
318
|
+
init: function(assigns, registers, rethrowErrors) {
|
319
|
+
this.scopes = [ assigns ? assigns : {} ];
|
320
|
+
this.registers = registers ? registers : {};
|
321
|
+
this.errors = [];
|
322
|
+
this.rethrowErrors = rethrowErrors;
|
323
|
+
this.strainer = Liquid.Strainer.create(this);
|
324
|
+
},
|
325
|
+
|
326
|
+
get: function(varname) {
|
327
|
+
return this.resolve(varname);
|
328
|
+
},
|
329
|
+
|
330
|
+
set: function(varname, value) {
|
331
|
+
this.scopes[0][varname] = value;
|
332
|
+
},
|
333
|
+
|
334
|
+
hasKey: function(key) {
|
335
|
+
return (this.resolve(key)) ? true : false;
|
336
|
+
},
|
337
|
+
|
338
|
+
push: function() {
|
339
|
+
var scpObj = {};
|
340
|
+
this.scopes.unshift(scpObj);
|
341
|
+
return scpObj // Is this right?
|
342
|
+
},
|
343
|
+
|
344
|
+
merge: function(newScope) {
|
345
|
+
return Liquid.extensions.object.update.call(this.scopes[0], newScope);
|
346
|
+
},
|
347
|
+
|
348
|
+
pop: function() {
|
349
|
+
if(this.scopes.length == 1){ throw "Context stack error"; }
|
350
|
+
return this.scopes.shift();
|
351
|
+
},
|
352
|
+
|
353
|
+
stack: function(lambda, bind) {
|
354
|
+
var result = null;
|
355
|
+
this.push();
|
356
|
+
try {
|
357
|
+
result = lambda.apply(bind ? bind : this.strainer);
|
358
|
+
} finally {
|
359
|
+
this.pop();
|
360
|
+
}
|
361
|
+
return result;
|
362
|
+
},
|
363
|
+
|
364
|
+
invoke: function(method, args) {
|
365
|
+
if( this.strainer.respondTo(method) ) {
|
366
|
+
var result = this.strainer[method].apply(this.strainer, args);
|
367
|
+
return result;
|
368
|
+
} else {
|
369
|
+
return (args.length == 0) ? null : args[0]; // was: $pick
|
370
|
+
}
|
371
|
+
},
|
372
|
+
|
373
|
+
resolve: function(key) {
|
374
|
+
switch(key) {
|
375
|
+
case null:
|
376
|
+
case 'nil':
|
377
|
+
case 'null':
|
378
|
+
case '':
|
379
|
+
return null;
|
380
|
+
|
381
|
+
case 'true':
|
382
|
+
return true;
|
383
|
+
|
384
|
+
case 'false':
|
385
|
+
return false;
|
386
|
+
|
387
|
+
case 'blank':
|
388
|
+
case 'empty':
|
389
|
+
return '';
|
390
|
+
|
391
|
+
default:
|
392
|
+
if((/^'(.*)'$/).test(key)) // Single quoted strings
|
393
|
+
{ return key.replace(/^'(.*)'$/, '$1'); }
|
394
|
+
|
395
|
+
else if((/^"(.*)"$/).test(key)) // Double quoted strings
|
396
|
+
{ return key.replace(/^"(.*)"$/, '$1'); }
|
397
|
+
|
398
|
+
else if((/^(\d+)$/).test(key)) // Integer...
|
399
|
+
{ return parseInt( key.replace(/^(\d+)$/ , '$1') ); }
|
400
|
+
|
401
|
+
else if((/^(\d[\d\.]+)$/).test(key)) // Float...
|
402
|
+
{ return parseFloat( key.replace(/^(\d[\d\.]+)$/, '$1') ); }
|
403
|
+
|
404
|
+
else if((/^\((\S+)\.\.(\S+)\)$/).test(key)) {// Ranges
|
405
|
+
var range = key.match(/^\((\S+)\.\.(\S+)\)$/),
|
406
|
+
left = parseInt(range[1]),
|
407
|
+
right = parseInt(range[2]),
|
408
|
+
arr = [];
|
409
|
+
if (isNaN(left) || isNaN(right)) {
|
410
|
+
left = range[1].charCodeAt(0);
|
411
|
+
right = range[2].charCodeAt(0);
|
412
|
+
|
413
|
+
var limit = right-left+1;
|
414
|
+
for (var i=0; i<limit; i++) arr.push(String.fromCharCode(i+left));
|
415
|
+
} else { // okay to make array
|
416
|
+
var limit = right-left+1;
|
417
|
+
for (var i=0; i<limit; i++) arr.push(i+left);
|
418
|
+
}
|
419
|
+
return arr;
|
420
|
+
} else {
|
421
|
+
var result = this.variable(key);
|
422
|
+
return result;
|
423
|
+
}
|
424
|
+
}
|
425
|
+
},
|
426
|
+
|
427
|
+
findVariable: function(key) {
|
428
|
+
for (var i=0; i < this.scopes.length; i++) {
|
429
|
+
var scope = this.scopes[i];
|
430
|
+
if( scope && typeof(scope[key]) !== 'undefined' ) {
|
431
|
+
var variable = scope[key];
|
432
|
+
if(typeof(variable) == 'function'){
|
433
|
+
variable = variable.apply(this);
|
434
|
+
scope[key] = variable;
|
435
|
+
}
|
436
|
+
if(variable && this._isObject(variable) && ('toLiquid' in variable)) {
|
437
|
+
variable = variable.toLiquid();
|
438
|
+
}
|
439
|
+
if(variable && this._isObject(variable) && ('setContext' in variable)){
|
440
|
+
variable.setContext(self);
|
441
|
+
}
|
442
|
+
return variable;
|
443
|
+
}
|
444
|
+
};
|
445
|
+
return null;
|
446
|
+
},
|
447
|
+
|
448
|
+
variable: function(markup) {
|
449
|
+
if(typeof markup != 'string') {
|
450
|
+
return null;
|
451
|
+
}
|
452
|
+
|
453
|
+
var parts = markup.match( /\[[^\]]+\]|(?:[\w\-]\??)+/g ),
|
454
|
+
firstPart = parts.shift(),
|
455
|
+
squareMatch = firstPart.match(/^\[(.*)\]$/);
|
456
|
+
|
457
|
+
if(squareMatch)
|
458
|
+
{ firstPart = this.resolve( squareMatch[1] ); }
|
459
|
+
|
460
|
+
var object = this.findVariable(firstPart),
|
461
|
+
self = this;
|
462
|
+
|
463
|
+
if(object) {
|
464
|
+
Liquid.extensions.arrayTools.each(parts, function(part){
|
465
|
+
var squareMatch = part.match(/^\[(.*)\]$/);
|
466
|
+
if(squareMatch) {
|
467
|
+
var part = self.resolve( squareMatch[1] );
|
468
|
+
if( typeof(object[part]) == 'function'){ object[part] = object[part].apply(this); }// Array?
|
469
|
+
object = object[part];
|
470
|
+
if(self._isObject(object) && ('toLiquid' in object)){ object = object.toLiquid(); }
|
471
|
+
} else {
|
472
|
+
if( (self._isObject(object) || typeof(object) == 'hash') && (part in object)) {
|
473
|
+
var res = object[part];
|
474
|
+
if( typeof(res) == 'function'){ res = object[part] = res.apply(self) ; }
|
475
|
+
if(self._isObject(res) && ('toLiquid' in res)){ object = res.toLiquid(); }
|
476
|
+
else { object = res; }
|
477
|
+
}
|
478
|
+
else if( (/^\d+$/).test(part) ) {
|
479
|
+
var pos = parseInt(part);
|
480
|
+
if( typeof(object[pos]) == 'function') { object[pos] = object[pos].apply(self); }
|
481
|
+
if(self._isObject(object) && self._isObject(object[pos]) && ('toLiquid' in object[pos])) { object = object[pos].toLiquid(); }
|
482
|
+
else { object = object[pos]; }
|
483
|
+
}
|
484
|
+
else if( object && typeof(object[part]) == 'function' && Liquid.extensions.arrayTools.include(['length', 'size', 'first', 'last'], part) ) {
|
485
|
+
object = object[part].apply(part);
|
486
|
+
if('toLiquid' in object){ object = object.toLiquid(); }
|
487
|
+
}
|
488
|
+
else {
|
489
|
+
return object = null;
|
490
|
+
}
|
491
|
+
if(self._isObject(object) && ('setContext' in object)){ object.setContext(self); }
|
492
|
+
}
|
493
|
+
});
|
494
|
+
}
|
495
|
+
return object;
|
496
|
+
},
|
497
|
+
|
498
|
+
addFilters: function(filters) {
|
499
|
+
filters = Liquid.extensions.arrayTools.flatten(filters);
|
500
|
+
Liquid.extensions.arrayTools.each(filters, function(f){
|
501
|
+
if(!this._isObject(f)){ throw ("Expected object but got: "+ typeof(f)) }
|
502
|
+
this.strainer.addMethods(f);
|
503
|
+
});
|
504
|
+
},
|
505
|
+
|
506
|
+
handleError: function(err) {
|
507
|
+
this.errors.push(err);
|
508
|
+
if(this.rethrowErrors){ throw err; }
|
509
|
+
return "Liquid error: " + (err.message ? err.message : (err.description ? err.description : err));
|
510
|
+
},
|
511
|
+
|
512
|
+
_isObject: function(obj) {
|
513
|
+
return obj != null && typeof(obj) == 'object';
|
514
|
+
}
|
515
|
+
|
516
|
+
});
|
517
|
+
Liquid.Template = Liquid.Class.extend({
|
518
|
+
|
519
|
+
init: function() {
|
520
|
+
this.root = null;
|
521
|
+
this.registers = {};
|
522
|
+
this.assigns = {};
|
523
|
+
this.errors = [];
|
524
|
+
this.rethrowErrors = false;
|
525
|
+
},
|
526
|
+
|
527
|
+
parse: function(src) {
|
528
|
+
this.root = new Liquid.Document( Liquid.Template.tokenize(src) );
|
529
|
+
return this;
|
530
|
+
},
|
531
|
+
|
532
|
+
render: function() {
|
533
|
+
if(!this.root){ return ''; }
|
534
|
+
var args = {
|
535
|
+
ctx: arguments[0],
|
536
|
+
filters: arguments[1],
|
537
|
+
registers: arguments[2]
|
538
|
+
}
|
539
|
+
var context = null;
|
540
|
+
|
541
|
+
if(args.ctx instanceof Liquid.Context ) {
|
542
|
+
context = args.ctx;
|
543
|
+
this.assigns = context.assigns;
|
544
|
+
this.registers = context.registers;
|
545
|
+
} else {
|
546
|
+
if(args.ctx){
|
547
|
+
Liquid.extensions.object.update.call(this.assigns, args.ctx);
|
548
|
+
}
|
549
|
+
if(args.registers){
|
550
|
+
Liquid.extensions.object.update.call(this.registers, args.registers);
|
551
|
+
}
|
552
|
+
context = new Liquid.Context(this.assigns, this.registers, this.rethrowErrors)
|
553
|
+
}
|
554
|
+
|
555
|
+
if(args.filters){ context.addFilters(arg.filters); }
|
556
|
+
|
557
|
+
try {
|
558
|
+
return this.root.render(context).join('');
|
559
|
+
} finally {
|
560
|
+
this.errors = context.errors;
|
561
|
+
}
|
562
|
+
},
|
563
|
+
|
564
|
+
renderWithErrors: function() {
|
565
|
+
var savedRethrowErrors = this.rethrowErrors;
|
566
|
+
this.rethrowErrors = true;
|
567
|
+
var res = this.render.apply(this, arguments);
|
568
|
+
this.rethrowErrors = savedRethrowErrors;
|
569
|
+
return res;
|
570
|
+
}
|
571
|
+
});
|
572
|
+
|
573
|
+
|
574
|
+
Liquid.Template.tags = {};
|
575
|
+
|
576
|
+
Liquid.Template.registerTag = function(name, klass) {
|
577
|
+
Liquid.Template.tags[ name ] = klass;
|
578
|
+
}
|
579
|
+
|
580
|
+
Liquid.Template.registerFilter = function(filters) {
|
581
|
+
Liquid.Strainer.globalFilter(filters)
|
582
|
+
}
|
583
|
+
|
584
|
+
Liquid.Template.tokenize = function(src) {
|
585
|
+
var tokens = src.split( /(\{\%.*?\%\}|\{\{.*?\}\}?)/ );
|
586
|
+
if(tokens[0] == ''){ tokens.shift(); }
|
587
|
+
return tokens;
|
588
|
+
}
|
589
|
+
|
590
|
+
|
591
|
+
Liquid.Template.parse = function(src) {
|
592
|
+
return (new Liquid.Template()).parse(src);
|
593
|
+
}
|
594
|
+
Liquid.Variable = Liquid.Class.extend({
|
595
|
+
|
596
|
+
init: function(markup) {
|
597
|
+
this.markup = markup;
|
598
|
+
this.name = null;
|
599
|
+
this.filters = [];
|
600
|
+
var self = this;
|
601
|
+
var match = markup.match(/\s*("[^"]+"|'[^']+'|[^\s,|]+)/);
|
602
|
+
if( match ) {
|
603
|
+
this.name = match[1];
|
604
|
+
var filterMatches = markup.match(/\|\s*(.*)/);
|
605
|
+
if(filterMatches) {
|
606
|
+
var filters = filterMatches[1].split(/\|/);
|
607
|
+
Liquid.extensions.arrayTools.each(filters, function(f){
|
608
|
+
var matches = f.match(/\s*(\w+)/);
|
609
|
+
if(matches) {
|
610
|
+
var filterName = matches[1];
|
611
|
+
var filterArgs = [];
|
612
|
+
Liquid.extensions.arrayTools.each(Liquid.extensions.arrayTools.flatten((f.match(/(?:[:|,]\s*)("[^"]+"|'[^']+'|[^\s,|]+)/g) || [])), function(arg){
|
613
|
+
var cleanupMatch = arg.match(/^[\s|:|,]*(.*?)[\s]*$/);
|
614
|
+
if(cleanupMatch)
|
615
|
+
{ filterArgs.push( cleanupMatch[1] );}
|
616
|
+
});
|
617
|
+
self.filters.push( [filterName, filterArgs] );
|
618
|
+
}
|
619
|
+
});
|
620
|
+
}
|
621
|
+
}
|
622
|
+
},
|
623
|
+
|
624
|
+
render: function(context) {
|
625
|
+
if(this.name == null){ return ''; }
|
626
|
+
var output = context.get(this.name);
|
627
|
+
Liquid.extensions.arrayTools.each(this.filters, function(filter) {
|
628
|
+
var filterName = filter[0],
|
629
|
+
filterArgs = Liquid.extensions.arrayTools.map((filter[1] || []), function(arg){
|
630
|
+
return context.get(arg);
|
631
|
+
});
|
632
|
+
filterArgs.unshift(output); // Push in input value into the first argument spot...
|
633
|
+
output = context.invoke(filterName, filterArgs);
|
634
|
+
});
|
635
|
+
|
636
|
+
return output;
|
637
|
+
}
|
638
|
+
});
|
639
|
+
Liquid.Condition = Liquid.Class.extend({
|
640
|
+
|
641
|
+
init: function(left, operator, right) {
|
642
|
+
this.left = left;
|
643
|
+
this.operator = operator;
|
644
|
+
this.right = right;
|
645
|
+
this.childRelation = null;
|
646
|
+
this.childCondition = null;
|
647
|
+
this.attachment = null;
|
648
|
+
},
|
649
|
+
|
650
|
+
evaluate: function(context) {
|
651
|
+
context = context || new Liquid.Context();
|
652
|
+
var result = this.interpretCondition(this.left, this.right, this.operator, context);
|
653
|
+
switch(this.childRelation) {
|
654
|
+
case 'or':
|
655
|
+
return (result || this.childCondition.evaluate(context));
|
656
|
+
case 'and':
|
657
|
+
return (result && this.childCondition.evaluate(context));
|
658
|
+
default:
|
659
|
+
return result;
|
660
|
+
}
|
661
|
+
},
|
662
|
+
|
663
|
+
or: function(condition) {
|
664
|
+
this.childRelation = 'or';
|
665
|
+
this.childCondition = condition;
|
666
|
+
},
|
667
|
+
|
668
|
+
and: function(condition) {
|
669
|
+
this.childRelation = 'and';
|
670
|
+
this.childCondition = condition;
|
671
|
+
},
|
672
|
+
|
673
|
+
attach: function(attachment) {
|
674
|
+
this.attachment = attachment;
|
675
|
+
return this.attachment;
|
676
|
+
},
|
677
|
+
|
678
|
+
isElse: false,
|
679
|
+
|
680
|
+
interpretCondition: function(left, right, op, context) {
|
681
|
+
if(!op)
|
682
|
+
{ return context.get(left); }
|
683
|
+
|
684
|
+
left = context.get(left);
|
685
|
+
right = context.get(right);
|
686
|
+
op = Liquid.Condition.operators[op];
|
687
|
+
if(!op)
|
688
|
+
{ throw ("Unknown operator "+ op); }
|
689
|
+
|
690
|
+
var results = op(left, right);
|
691
|
+
return results;
|
692
|
+
},
|
693
|
+
|
694
|
+
toString: function() {
|
695
|
+
return "<Condition "+ this.left +" "+ this.operator +" "+ this.right +">";
|
696
|
+
}
|
697
|
+
|
698
|
+
});
|
699
|
+
|
700
|
+
Liquid.Condition.operators = {
|
701
|
+
'==': function(l,r) { return (l == r); },
|
702
|
+
'=': function(l,r) { return (l == r); },
|
703
|
+
'!=': function(l,r) { return (l != r); },
|
704
|
+
'<>': function(l,r) { return (l != r); },
|
705
|
+
'<': function(l,r) { return (l < r); },
|
706
|
+
'>': function(l,r) { return (l > r); },
|
707
|
+
'<=': function(l,r) { return (l <= r); },
|
708
|
+
'>=': function(l,r) { return (l >= r); },
|
709
|
+
|
710
|
+
'contains': function(l,r) {
|
711
|
+
if ( Object.prototype.toString.call(l) === '[object Array]' ) {
|
712
|
+
return Liquid.extensions.arrayTools.indexOf(l, r) >= 0;
|
713
|
+
} else {
|
714
|
+
return l.match(r);
|
715
|
+
}
|
716
|
+
},
|
717
|
+
'hasKey': function(l,r) { return Liquid.extensions.object.hasKey.call(l, r); },
|
718
|
+
'hasValue': function(l,r) { return Liquid.extensions.object.hasValue.call(l, r); }
|
719
|
+
}
|
720
|
+
|
721
|
+
Liquid.ElseCondition = Liquid.Condition.extend({
|
722
|
+
|
723
|
+
isElse: true,
|
724
|
+
|
725
|
+
evaluate: function(context) {
|
726
|
+
return true;
|
727
|
+
},
|
728
|
+
|
729
|
+
toString: function() {
|
730
|
+
return "<ElseCondition>";
|
731
|
+
}
|
732
|
+
|
733
|
+
});
|
734
|
+
Liquid.Drop = Liquid.Class.extend({
|
735
|
+
setContext: function(context) {
|
736
|
+
this.context = context;
|
737
|
+
},
|
738
|
+
beforeMethod: function(method) {
|
739
|
+
|
740
|
+
},
|
741
|
+
invokeDrop: function(method) {
|
742
|
+
var results = this.beforeMethod();
|
743
|
+
if( !results && (method in this) )
|
744
|
+
{ results = this[method].apply(this); }
|
745
|
+
return results;
|
746
|
+
},
|
747
|
+
hasKey: function(name) {
|
748
|
+
return true;
|
749
|
+
}
|
750
|
+
});
|
751
|
+
var hackObjectEach = function(fun /*, thisp*/) {
|
752
|
+
if (typeof fun != "function")
|
753
|
+
throw 'Object.each requires first argument to be a function';
|
754
|
+
|
755
|
+
var i = 0;
|
756
|
+
var thisp = arguments[1];
|
757
|
+
for (var p in this) {
|
758
|
+
var value = this[p], pair = [p, value];
|
759
|
+
pair.key = p;
|
760
|
+
pair.value = value;
|
761
|
+
fun.call(thisp, pair, i, this);
|
762
|
+
i++;
|
763
|
+
}
|
764
|
+
|
765
|
+
return null;
|
766
|
+
};
|
767
|
+
|
768
|
+
Liquid.Template.registerTag( 'assign', Liquid.Tag.extend({
|
769
|
+
|
770
|
+
tagSyntax: /((?:\(?[\w\-\.\[\]]\)?)+)\s*=\s*(.+)/,
|
771
|
+
|
772
|
+
init: function(tagName, markup, tokens) {
|
773
|
+
var parts = markup.match(this.tagSyntax);
|
774
|
+
if( parts ) {
|
775
|
+
this.to = parts[1];
|
776
|
+
this.from = parts[2];
|
777
|
+
} else {
|
778
|
+
throw ("Syntax error in 'assign' - Valid syntax: assign [var] = [source]");
|
779
|
+
}
|
780
|
+
this._super(tagName, markup, tokens)
|
781
|
+
},
|
782
|
+
render: function(context) {
|
783
|
+
var value = new Liquid.Variable(this.from);
|
784
|
+
Liquid.extensions.arrayTools.last(context.scopes)[this.to.toString()] = value.render(context);
|
785
|
+
return '';
|
786
|
+
}
|
787
|
+
}));
|
788
|
+
|
789
|
+
Liquid.Template.registerTag( 'cache', Liquid.Block.extend({
|
790
|
+
tagSyntax: /(\w+)/,
|
791
|
+
|
792
|
+
init: function(tagName, markup, tokens) {
|
793
|
+
var parts = markup.match(this.tagSyntax)
|
794
|
+
if( parts ) {
|
795
|
+
this.to = parts[1];
|
796
|
+
} else {
|
797
|
+
throw ("Syntax error in 'cache' - Valid syntax: cache [var]");
|
798
|
+
}
|
799
|
+
this._super(tagName, markup, tokens);
|
800
|
+
},
|
801
|
+
render: function(context) {
|
802
|
+
var output = this._super(context);
|
803
|
+
Liquid.extensions.arrayTools.last(context.scopes)[this.to] = Liquid.extensions.arrayTools.flatten([output]).join('');
|
804
|
+
return '';
|
805
|
+
}
|
806
|
+
}));
|
807
|
+
|
808
|
+
|
809
|
+
Liquid.Template.registerTag( 'capture', Liquid.Block.extend({
|
810
|
+
tagSyntax: /(\w+)/,
|
811
|
+
|
812
|
+
init: function(tagName, markup, tokens) {
|
813
|
+
var parts = markup.match(this.tagSyntax)
|
814
|
+
if( parts ) {
|
815
|
+
this.to = parts[1];
|
816
|
+
} else {
|
817
|
+
throw ("Syntax error in 'capture' - Valid syntax: capture [var]");
|
818
|
+
}
|
819
|
+
this._super(tagName, markup, tokens);
|
820
|
+
},
|
821
|
+
render: function(context) {
|
822
|
+
var output = this._super(context);
|
823
|
+
Liquid.extensions.arrayTools.last(context.scopes)[this.to.toString()] = Liquid.extensions.arrayTools.flatten([output]).join('');
|
824
|
+
return '';
|
825
|
+
}
|
826
|
+
}));
|
827
|
+
|
828
|
+
Liquid.Template.registerTag( 'case', Liquid.Block.extend({
|
829
|
+
|
830
|
+
tagSyntax : /("[^"]+"|'[^']+'|[^\s,|]+)/,
|
831
|
+
tagWhenSyntax : /("[^"]+"|'[^']+'|[^\s,|]+)(?:(?:\s+or\s+|\s*\,\s*)("[^"]+"|'[^']+'|[^\s,|]+.*))?/,
|
832
|
+
|
833
|
+
init: function(tagName, markup, tokens) {
|
834
|
+
this.blocks = [];
|
835
|
+
this.nodelist = [];
|
836
|
+
|
837
|
+
var parts = markup.match(this.tagSyntax)
|
838
|
+
if( parts ) {
|
839
|
+
this.left = parts[1];
|
840
|
+
} else {
|
841
|
+
throw ("Syntax error in 'case' - Valid syntax: case [condition]");
|
842
|
+
}
|
843
|
+
|
844
|
+
this._super(tagName, markup, tokens);
|
845
|
+
},
|
846
|
+
unknownTag: function(tag, markup, tokens) {
|
847
|
+
switch(tag) {
|
848
|
+
case 'when':
|
849
|
+
this.recordWhenCondition(markup);
|
850
|
+
break;
|
851
|
+
case 'else':
|
852
|
+
this.recordElseCondition(markup);
|
853
|
+
break;
|
854
|
+
default:
|
855
|
+
this._super(tag, markup, tokens);
|
856
|
+
}
|
857
|
+
|
858
|
+
},
|
859
|
+
render: function(context) {
|
860
|
+
var self = this,
|
861
|
+
output = [],
|
862
|
+
execElseBlock = true;
|
863
|
+
|
864
|
+
context.stack(function(){
|
865
|
+
for (var i=0; i < self.blocks.length; i++) {
|
866
|
+
var block = self.blocks[i];
|
867
|
+
if( block.isElse ) {
|
868
|
+
if(execElseBlock == true){ output = Liquid.extensions.arrayTools.flatten([output, self.renderAll(block.attachment, context)]); }
|
869
|
+
return output;
|
870
|
+
} else if( block.evaluate(context) ) {
|
871
|
+
execElseBlock = false;
|
872
|
+
output = Liquid.extensions.arrayTools.flatten([output, self.renderAll(block.attachment, context)]);
|
873
|
+
}
|
874
|
+
};
|
875
|
+
});
|
876
|
+
|
877
|
+
return output;
|
878
|
+
},
|
879
|
+
recordWhenCondition: function(markup) {
|
880
|
+
while(markup) {
|
881
|
+
var parts = markup.match(this.tagWhenSyntax);
|
882
|
+
if(!parts) {
|
883
|
+
throw ("Syntax error in tag 'case' - Valid when condition: {% when [condition] [or condition2...] %} ");
|
884
|
+
}
|
885
|
+
|
886
|
+
markup = parts[2];
|
887
|
+
|
888
|
+
var block = new Liquid.Condition(this.left, '==', parts[1]);
|
889
|
+
this.blocks.push( block );
|
890
|
+
this.nodelist = block.attach([]);
|
891
|
+
}
|
892
|
+
},
|
893
|
+
recordElseCondition: function(markup) {
|
894
|
+
if( Liquid.extensions.stringTools.strip((markup || '')) != '') {
|
895
|
+
throw ("Syntax error in tag 'case' - Valid else condition: {% else %} (no parameters) ")
|
896
|
+
}
|
897
|
+
var block = new Liquid.ElseCondition();
|
898
|
+
this.blocks.push(block);
|
899
|
+
this.nodelist = block.attach([]);
|
900
|
+
}
|
901
|
+
}));
|
902
|
+
|
903
|
+
Liquid.Template.registerTag( 'comment', Liquid.Block.extend({
|
904
|
+
render: function(context) {
|
905
|
+
return '';
|
906
|
+
}
|
907
|
+
}));
|
908
|
+
|
909
|
+
Liquid.Template.registerTag( 'cycle', Liquid.Tag.extend({
|
910
|
+
|
911
|
+
tagSimpleSyntax: /"[^"]+"|'[^']+'|[^\s,|]+/,
|
912
|
+
tagNamedSyntax: /("[^"]+"|'[^']+'|[^\s,|]+)\s*\:\s*(.*)/,
|
913
|
+
|
914
|
+
init: function(tag, markup, tokens) {
|
915
|
+
var matches, variables;
|
916
|
+
matches = markup.match(this.tagNamedSyntax);
|
917
|
+
if(matches) {
|
918
|
+
this.variables = this.variablesFromString(matches[2]);
|
919
|
+
this.name = matches[1];
|
920
|
+
} else {
|
921
|
+
matches = markup.match(this.tagSimpleSyntax);
|
922
|
+
if(matches) {
|
923
|
+
this.variables = this.variablesFromString(markup);
|
924
|
+
this.name = "'"+ this.variables.toString() +"'";
|
925
|
+
} else {
|
926
|
+
throw ("Syntax error in 'cycle' - Valid syntax: cycle [name :] var [, var2, var3 ...]");
|
927
|
+
}
|
928
|
+
}
|
929
|
+
this._super(tag, markup, tokens);
|
930
|
+
},
|
931
|
+
|
932
|
+
render: function(context) {
|
933
|
+
var self = this,
|
934
|
+
key = context.get(self.name),
|
935
|
+
output = '';
|
936
|
+
|
937
|
+
if(!context.registers['cycle']) {
|
938
|
+
context.registers['cycle'] = {};
|
939
|
+
}
|
940
|
+
|
941
|
+
if(!context.registers['cycle'][key]) {
|
942
|
+
context.registers['cycle'][key] = 0;
|
943
|
+
}
|
944
|
+
|
945
|
+
context.stack(function(){
|
946
|
+
var iter = context.registers['cycle'][key],
|
947
|
+
results = context.get( self.variables[iter] );
|
948
|
+
iter += 1;
|
949
|
+
if(iter == self.variables.length){ iter = 0; }
|
950
|
+
context.registers['cycle'][key] = iter;
|
951
|
+
output = results;
|
952
|
+
});
|
953
|
+
|
954
|
+
return output;
|
955
|
+
},
|
956
|
+
|
957
|
+
variablesFromString: function(markup) {
|
958
|
+
return Liquid.extensions.arrayTools.map(markup.split(','), function(varname){
|
959
|
+
var match = varname.match(/\s*("[^"]+"|'[^']+'|[^\s,|]+)\s*/);
|
960
|
+
return (match[1]) ? match[1] : null
|
961
|
+
});
|
962
|
+
}
|
963
|
+
}));
|
964
|
+
|
965
|
+
Liquid.Template.registerTag( 'for', Liquid.Block.extend({
|
966
|
+
tagSyntax: /(\w+)\s+in\s+((?:\(?[\w\-\.\[\]]\)?)+)/,
|
967
|
+
|
968
|
+
init: function(tag, markup, tokens) {
|
969
|
+
var matches = markup.match(this.tagSyntax);
|
970
|
+
if(matches) {
|
971
|
+
this.variableName = matches[1];
|
972
|
+
this.collectionName = matches[2];
|
973
|
+
this.name = this.variableName +"-"+ this.collectionName;
|
974
|
+
this.attributes = {};
|
975
|
+
var attrmarkup = markup.replace(this.tagSyntax, '');
|
976
|
+
var attMatchs = markup.match(/(\w*?)\s*\:\s*("[^"]+"|'[^']+'|[^\s,|]+)/g);
|
977
|
+
if(attMatchs) {
|
978
|
+
Liquid.extensions.arrayTools.each(attMatchs, function(pair){
|
979
|
+
pair = pair.split(":");
|
980
|
+
this.attributes[Liquid.extensions.stringTools.strip(pair[0])] = Liquid.extensions.stringTools.strip(pair[1]);
|
981
|
+
}, this);
|
982
|
+
}
|
983
|
+
} else {
|
984
|
+
throw ("Syntax error in 'for loop' - Valid syntax: for [item] in [collection]");
|
985
|
+
}
|
986
|
+
this._super(tag, markup, tokens);
|
987
|
+
},
|
988
|
+
|
989
|
+
render: function(context) {
|
990
|
+
var self = this,
|
991
|
+
output = [],
|
992
|
+
collection = (context.get(this.collectionName) || []),
|
993
|
+
range = [0, collection.length];
|
994
|
+
|
995
|
+
if(!context.registers['for']){ context.registers['for'] = {}; }
|
996
|
+
|
997
|
+
if(this.attributes['limit'] || this.attributes['offset']) {
|
998
|
+
var offset = 0,
|
999
|
+
limit = 0,
|
1000
|
+
rangeEnd = 0,
|
1001
|
+
segment = null;
|
1002
|
+
|
1003
|
+
if(this.attributes['offset'] == 'continue')
|
1004
|
+
{ offset = context.registers['for'][this.name]; }
|
1005
|
+
else
|
1006
|
+
{ offset = context.get( this.attributes['offset'] ) || 0; }
|
1007
|
+
|
1008
|
+
limit = context.get( this.attributes['limit'] );
|
1009
|
+
|
1010
|
+
rangeEnd = (limit) ? offset + limit + 1 : collection.length;
|
1011
|
+
range = [ offset, rangeEnd - 1 ];
|
1012
|
+
|
1013
|
+
context.registers['for'][this.name] = rangeEnd;
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
segment = collection.slice(range[0], range[1]);
|
1017
|
+
if(!segment || segment.length == 0){ return ''; }
|
1018
|
+
|
1019
|
+
context.stack(function(){
|
1020
|
+
var length = segment.length;
|
1021
|
+
|
1022
|
+
Liquid.extensions.arrayTools.each(segment, function(item, index){
|
1023
|
+
context.set( self.variableName, item );
|
1024
|
+
context.set( 'forloop', {
|
1025
|
+
name: self.name,
|
1026
|
+
length: length,
|
1027
|
+
index: (index + 1),
|
1028
|
+
index0: index,
|
1029
|
+
rindex: (length - index),
|
1030
|
+
rindex0:(length - index - 1),
|
1031
|
+
first: (index == 0),
|
1032
|
+
last: (index == (length - 1))
|
1033
|
+
});
|
1034
|
+
output.push( (self.renderAll(self.nodelist, context) || []).join('') );
|
1035
|
+
});
|
1036
|
+
});
|
1037
|
+
|
1038
|
+
return Liquid.extensions.arrayTools.flatten([output]).join('');
|
1039
|
+
}
|
1040
|
+
}));
|
1041
|
+
|
1042
|
+
Liquid.Template.registerTag( 'if', Liquid.Block.extend({
|
1043
|
+
|
1044
|
+
tagSyntax: /("[^"]+"|'[^']+'|[^\s,|]+)\s*([=!<>a-z_]+)?\s*("[^"]+"|'[^']+'|[^\s,|]+)?/,
|
1045
|
+
|
1046
|
+
init: function(tag, markup, tokens) {
|
1047
|
+
this.nodelist = [];
|
1048
|
+
this.blocks = [];
|
1049
|
+
this.pushBlock('if', markup);
|
1050
|
+
this._super(tag, markup, tokens);
|
1051
|
+
},
|
1052
|
+
|
1053
|
+
unknownTag: function(tag, markup, tokens) {
|
1054
|
+
if( Liquid.extensions.arrayTools.include(['elsif', 'else'], tag) ) {
|
1055
|
+
this.pushBlock(tag, markup);
|
1056
|
+
} else {
|
1057
|
+
this._super(tag, markup, tokens);
|
1058
|
+
}
|
1059
|
+
},
|
1060
|
+
|
1061
|
+
render: function(context) {
|
1062
|
+
var self = this,
|
1063
|
+
output = '';
|
1064
|
+
context.stack(function(){
|
1065
|
+
for (var i=0; i < self.blocks.length; i++) {
|
1066
|
+
var block = self.blocks[i];
|
1067
|
+
if( block.evaluate(context) ) {
|
1068
|
+
output = self.renderAll(block.attachment, context);
|
1069
|
+
return;
|
1070
|
+
}
|
1071
|
+
};
|
1072
|
+
})
|
1073
|
+
return Liquid.extensions.arrayTools.flatten([output]).join('');
|
1074
|
+
},
|
1075
|
+
|
1076
|
+
pushBlock: function(tag, markup) {
|
1077
|
+
var block;
|
1078
|
+
if(tag == 'else') {
|
1079
|
+
block = new Liquid.ElseCondition();
|
1080
|
+
} else {
|
1081
|
+
var expressions = markup.split(/\b(and|or)\b/).reverse(),
|
1082
|
+
expMatches = expressions.shift().match( this.tagSyntax );
|
1083
|
+
|
1084
|
+
if(!expMatches){ throw ("Syntax Error in tag '"+ tag +"' - Valid syntax: "+ tag +" [expression]"); }
|
1085
|
+
|
1086
|
+
var condition = new Liquid.Condition(expMatches[1], expMatches[2], expMatches[3]);
|
1087
|
+
|
1088
|
+
while(expressions.length > 0) {
|
1089
|
+
var operator = expressions.shift(),
|
1090
|
+
expMatches = expressions.shift().match( this.tagSyntax );
|
1091
|
+
if(!expMatches){ throw ("Syntax Error in tag '"+ tag +"' - Valid syntax: "+ tag +" [expression]"); }
|
1092
|
+
|
1093
|
+
var newCondition = new Liquid.Condition(expMatches[1], expMatches[2], expMatches[3]);
|
1094
|
+
newCondition[operator](condition);
|
1095
|
+
condition = newCondition;
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
block = condition;
|
1099
|
+
}
|
1100
|
+
block.attach([]);
|
1101
|
+
this.blocks.push(block);
|
1102
|
+
this.nodelist = block.attachment;
|
1103
|
+
}
|
1104
|
+
}));
|
1105
|
+
|
1106
|
+
Liquid.Template.registerTag( 'ifchanged', Liquid.Block.extend({
|
1107
|
+
|
1108
|
+
render: function(context) {
|
1109
|
+
var self = this,
|
1110
|
+
output = '';
|
1111
|
+
context.stack(function(){
|
1112
|
+
var results = self.renderAll(self.nodelist, context).join('');
|
1113
|
+
if(results != context.registers['ifchanged']) {
|
1114
|
+
output = results;
|
1115
|
+
context.registers['ifchanged'] = output;
|
1116
|
+
}
|
1117
|
+
});
|
1118
|
+
return output;
|
1119
|
+
}
|
1120
|
+
}));
|
1121
|
+
|
1122
|
+
Liquid.Template.registerTag( 'include', Liquid.Tag.extend({
|
1123
|
+
|
1124
|
+
tagSyntax: /((?:"[^"]+"|'[^']+'|[^\s,|]+)+)(\s+(?:with|for)\s+((?:"[^"]+"|'[^']+'|[^\s,|]+)+))?/,
|
1125
|
+
|
1126
|
+
init: function(tag, markup, tokens) {
|
1127
|
+
var matches = (markup || '').match(this.tagSyntax);
|
1128
|
+
if(matches) {
|
1129
|
+
this.templateName = matches[1];
|
1130
|
+
this.templateNameVar = this.templateName.substring(1, this.templateName.length - 1);
|
1131
|
+
this.variableName = matches[3];
|
1132
|
+
this.attributes = {};
|
1133
|
+
|
1134
|
+
var attMatchs = markup.match(/(\w*?)\s*\:\s*("[^"]+"|'[^']+'|[^\s,|]+)/g);
|
1135
|
+
if(attMatchs) {
|
1136
|
+
Liquid.extensions.arrayTools.each(attMatchs, function(pair){
|
1137
|
+
pair = pair.split(":");
|
1138
|
+
this.attributes[Liquid.extensions.stringTools.strip(pair[0])] = Liquid.extensions.stringTools.strip(pair[1]);
|
1139
|
+
}, this);
|
1140
|
+
}
|
1141
|
+
} else {
|
1142
|
+
throw ("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]");
|
1143
|
+
}
|
1144
|
+
this._super(tag, markup, tokens);
|
1145
|
+
},
|
1146
|
+
|
1147
|
+
render: function(context) {
|
1148
|
+
var self = this,
|
1149
|
+
source = Liquid.readTemplateFile( context.get(this.templateName) ),
|
1150
|
+
partial = Liquid.parse(source),
|
1151
|
+
variable = context.get((this.variableName || this.templateNameVar)),
|
1152
|
+
output = '';
|
1153
|
+
context.stack(function(){
|
1154
|
+
self.attributes.each = hackObjectEach;
|
1155
|
+
self.attributes.each(function(pair){
|
1156
|
+
context.set(pair.key, context.get(pair.value));
|
1157
|
+
})
|
1158
|
+
|
1159
|
+
if(variable instanceof Array) {
|
1160
|
+
output = Liquid.extensions.arrayTools.map(variable, function(variable){
|
1161
|
+
context.set( self.templateNameVar, variable );
|
1162
|
+
return partial.render(context);
|
1163
|
+
});
|
1164
|
+
} else {
|
1165
|
+
context.set(self.templateNameVar, variable);
|
1166
|
+
output = partial.render(context);
|
1167
|
+
}
|
1168
|
+
});
|
1169
|
+
output = Liquid.extensions.arrayTools.flatten([output]).join('');
|
1170
|
+
return output
|
1171
|
+
}
|
1172
|
+
}));
|
1173
|
+
|
1174
|
+
Liquid.Template.registerTag( 'unless', Liquid.Template.tags['if'].extend({
|
1175
|
+
|
1176
|
+
render: function(context) {
|
1177
|
+
var self = this,
|
1178
|
+
output = '';
|
1179
|
+
context.stack(function(){
|
1180
|
+
var block = self.blocks[0];
|
1181
|
+
if( !block.evaluate(context) ) {
|
1182
|
+
output = self.renderAll(block.attachment, context);
|
1183
|
+
return;
|
1184
|
+
}
|
1185
|
+
for (var i=1; i < self.blocks.length; i++) {
|
1186
|
+
var block = self.blocks[i];
|
1187
|
+
if( block.evaluate(context) ) {
|
1188
|
+
output = self.renderAll(block.attachment, context);
|
1189
|
+
return;
|
1190
|
+
}
|
1191
|
+
};
|
1192
|
+
})
|
1193
|
+
return Liquid.extensions.arrayTools.flatten([output]).join('');
|
1194
|
+
}
|
1195
|
+
}));
|
1196
|
+
|
1197
|
+
Liquid.Template.registerTag( 'raw', Liquid.Block.extend({
|
1198
|
+
parse: function(tokens) {
|
1199
|
+
if (!this.nodelist) this.nodelist = [];
|
1200
|
+
this.nodelist.length = 0;
|
1201
|
+
|
1202
|
+
var token = tokens.shift();
|
1203
|
+
tokens.push('');
|
1204
|
+
while(tokens.length) {
|
1205
|
+
|
1206
|
+
if( /^\{\%/.test(token) ) { // It's a tag...
|
1207
|
+
var tagParts = token.match(/^\{\%\s*(\w+)\s*(.*)?\%\}$/);
|
1208
|
+
|
1209
|
+
if(tagParts) {
|
1210
|
+
if( this.blockDelimiter == tagParts[1] ) {
|
1211
|
+
this.endTag();
|
1212
|
+
return;
|
1213
|
+
}
|
1214
|
+
}
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
this.nodelist.push( token || '');
|
1218
|
+
token = tokens.shift(); // Assign the next token to loop again...
|
1219
|
+
}
|
1220
|
+
this.assertMissingDelimitation();
|
1221
|
+
},
|
1222
|
+
|
1223
|
+
render: function(context) {
|
1224
|
+
return this.nodelist.join('');
|
1225
|
+
}
|
1226
|
+
}));
|
1227
|
+
Liquid.Template.registerFilter({
|
1228
|
+
|
1229
|
+
_HTML_ESCAPE_MAP: {
|
1230
|
+
'&': '&',
|
1231
|
+
'>': '>',
|
1232
|
+
'<': '<',
|
1233
|
+
'"': '"',
|
1234
|
+
"'": '''
|
1235
|
+
},
|
1236
|
+
|
1237
|
+
size: function(iterable) {
|
1238
|
+
return (iterable['length']) ? iterable.length : 0;
|
1239
|
+
},
|
1240
|
+
|
1241
|
+
downcase: function(input) {
|
1242
|
+
return input.toString().toLowerCase();
|
1243
|
+
},
|
1244
|
+
|
1245
|
+
upcase: function(input) {
|
1246
|
+
return input.toString().toUpperCase();
|
1247
|
+
},
|
1248
|
+
|
1249
|
+
capitalize: function(input) {
|
1250
|
+
return Liquid.extensions.stringTools.capitalize(input.toString());
|
1251
|
+
},
|
1252
|
+
|
1253
|
+
escape: function(input) {
|
1254
|
+
var self = this;
|
1255
|
+
return input.replace(/[&<>"']/g, function(chr) {
|
1256
|
+
return self._HTML_ESCAPE_MAP[chr];
|
1257
|
+
});
|
1258
|
+
},
|
1259
|
+
|
1260
|
+
h: function(input) {
|
1261
|
+
var self = this;
|
1262
|
+
return input.replace(/[&<>"']/g, function(chr) {
|
1263
|
+
return self._HTML_ESCAPE_MAP[chr];
|
1264
|
+
});
|
1265
|
+
},
|
1266
|
+
|
1267
|
+
default: function(input, default_value) {
|
1268
|
+
return Liquid.extensions.object.isEmpty(input) ? default_value : input;
|
1269
|
+
},
|
1270
|
+
|
1271
|
+
truncate: function(input, length, string) {
|
1272
|
+
if(!input || input == ''){ return ''; }
|
1273
|
+
length = length || 50;
|
1274
|
+
string = string || "...";
|
1275
|
+
|
1276
|
+
var seg = input.slice(0, length);
|
1277
|
+
return (input.length > length ?
|
1278
|
+
input.slice(0, length) + string :
|
1279
|
+
input);
|
1280
|
+
},
|
1281
|
+
|
1282
|
+
truncatewords: function(input, words, string) {
|
1283
|
+
if(!input || input == ''){ return ''; }
|
1284
|
+
words = parseInt(words || 15);
|
1285
|
+
string = string || '...';
|
1286
|
+
var wordlist = input.toString().split(" "),
|
1287
|
+
l = Math.max((words), 0);
|
1288
|
+
return (wordlist.length > l) ? wordlist.slice(0,l).join(' ') + string : input;
|
1289
|
+
},
|
1290
|
+
|
1291
|
+
truncate_words: function(input, words, string) {
|
1292
|
+
if(!input || input == ''){ return ''; }
|
1293
|
+
words = parseInt(words || 15);
|
1294
|
+
string = string || '...';
|
1295
|
+
var wordlist = input.toString().split(" "),
|
1296
|
+
l = Math.max((words), 0);
|
1297
|
+
return (wordlist.length > l) ? wordlist.slice(0,l).join(' ') + string : input;
|
1298
|
+
},
|
1299
|
+
|
1300
|
+
strip_html: function(input) {
|
1301
|
+
return input.toString().replace(/<.*?>/g, '');
|
1302
|
+
},
|
1303
|
+
|
1304
|
+
strip_newlines: function(input) {
|
1305
|
+
return input.toString().replace(/\n/g, '')
|
1306
|
+
},
|
1307
|
+
|
1308
|
+
join: function(input, separator) {
|
1309
|
+
separator = separator || ' ';
|
1310
|
+
return input.join(separator);
|
1311
|
+
},
|
1312
|
+
|
1313
|
+
split: function(input, separator) {
|
1314
|
+
separator = separator || ' ';
|
1315
|
+
return input.split(separator);
|
1316
|
+
},
|
1317
|
+
|
1318
|
+
sort: function(input) {
|
1319
|
+
return input.sort();
|
1320
|
+
},
|
1321
|
+
|
1322
|
+
reverse: function(input) {
|
1323
|
+
return input.reverse();
|
1324
|
+
},
|
1325
|
+
|
1326
|
+
replace: function(input, string, replacement) {
|
1327
|
+
replacement = replacement || '';
|
1328
|
+
return input.toString().replace(new RegExp(string, 'g'), replacement);
|
1329
|
+
},
|
1330
|
+
|
1331
|
+
replace_first: function(input, string, replacement) {
|
1332
|
+
replacement = replacement || '';
|
1333
|
+
return input.toString().replace(new RegExp(string, ""), replacement);
|
1334
|
+
},
|
1335
|
+
|
1336
|
+
newline_to_br: function(input) {
|
1337
|
+
return input.toString().replace(/\n/g, "<br/>\n");
|
1338
|
+
},
|
1339
|
+
|
1340
|
+
date: function(input, format) {
|
1341
|
+
var date;
|
1342
|
+
if( input instanceof Date ){ date = input; }
|
1343
|
+
if(!(date instanceof Date) && input == 'now'){ date = new Date(); }
|
1344
|
+
if(!(date instanceof Date) && typeof(input) == 'number'){ date = new Date(input * 1000); }
|
1345
|
+
if(!(date instanceof Date) && typeof(input) == 'string'){ date = new Date(Date.parse(input));}
|
1346
|
+
if(!(date instanceof Date)){ return input; } // Punt
|
1347
|
+
return date.strftime(format);
|
1348
|
+
},
|
1349
|
+
|
1350
|
+
first: function(input) {
|
1351
|
+
return input[0];
|
1352
|
+
},
|
1353
|
+
|
1354
|
+
last: function(input) {
|
1355
|
+
input = input;
|
1356
|
+
return input[input.length -1];
|
1357
|
+
},
|
1358
|
+
|
1359
|
+
minus: function(input, number) {
|
1360
|
+
return (Number(input) || 0) - (Number(number) || 0);
|
1361
|
+
},
|
1362
|
+
|
1363
|
+
plus: function(input, number) {
|
1364
|
+
return (Number(input) || 0) + (Number(number) || 0);
|
1365
|
+
},
|
1366
|
+
|
1367
|
+
times: function(input, number) {
|
1368
|
+
return (Number(input) || 0) * (Number(number) || 0);
|
1369
|
+
},
|
1370
|
+
|
1371
|
+
divided_by: function(input, number) {
|
1372
|
+
return (Number(input) || 0) / (Number(number) || 0);
|
1373
|
+
},
|
1374
|
+
|
1375
|
+
modulo: function(input, number) {
|
1376
|
+
return (Number(input) || 0) % (Number(number) || 0);
|
1377
|
+
},
|
1378
|
+
|
1379
|
+
map: function(input, property) {
|
1380
|
+
input = input || [];
|
1381
|
+
var results = [];
|
1382
|
+
for (var i = 0; i < input.length; i++) {
|
1383
|
+
results.push(input[i][property]);
|
1384
|
+
}
|
1385
|
+
return results;
|
1386
|
+
},
|
1387
|
+
escape_once: function(input) {
|
1388
|
+
var self = this;
|
1389
|
+
return input.replace(/["><']|&(?!([a-zA-Z]+|(#\d+));)/g, function(chr) {
|
1390
|
+
return self._HTML_ESCAPE_MAP[chr];
|
1391
|
+
});
|
1392
|
+
},
|
1393
|
+
|
1394
|
+
remove: function(input, string) {
|
1395
|
+
return input.toString().replace(new RegExp(string, 'g'), '');
|
1396
|
+
},
|
1397
|
+
|
1398
|
+
remove_first: function(input, string) {
|
1399
|
+
return input.toString().replace(string, '');
|
1400
|
+
},
|
1401
|
+
|
1402
|
+
prepend: function(input, string) {
|
1403
|
+
return '' + (string || '').toString() + (input || '').toString();
|
1404
|
+
},
|
1405
|
+
|
1406
|
+
append: function(input, string) {
|
1407
|
+
return '' + (input || '').toString() + (string || '').toString();
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
});
|
1411
|
+
|
1412
|
+
|
1413
|
+
if(!(new Date()).strftime) {(function(){
|
1414
|
+
Date.ext={};Date.ext.util={};Date.ext.util.xPad=function(x,pad,r){if(typeof (r)=="undefined"){r=10}for(;parseInt(x,10)<r&&r>1;r/=10){x=pad.toString()+x}return x.toString()};Date.prototype.locale="en-GB";if(document.getElementsByTagName("html")&&document.getElementsByTagName("html")[0].lang){Date.prototype.locale=document.getElementsByTagName("html")[0].lang}Date.ext.locales={};Date.ext.locales.en={a:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],A:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],b:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],B:["January","February","March","April","May","June","July","August","September","October","November","December"],c:"%a %d %b %Y %T %Z",p:["AM","PM"],P:["am","pm"],x:"%d/%m/%y",X:"%T"};
|
1415
|
+
if(typeof JSON != 'undefined'){ Date.ext.locales['en-US'] = JSON.parse(JSON.stringify(Date.ext.locales.en)); } else { Date.ext.locales["en-US"]=Date.ext.locales.en;};
|
1416
|
+
Date.ext.locales["en-US"].c="%a %d %b %Y %r %Z";Date.ext.locales["en-US"].x="%D";Date.ext.locales["en-US"].X="%r";Date.ext.locales["en-GB"]=Date.ext.locales.en;Date.ext.locales["en-AU"]=Date.ext.locales["en-GB"];Date.ext.formats={a:function(d){return Date.ext.locales[d.locale].a[d.getDay()]},A:function(d){return Date.ext.locales[d.locale].A[d.getDay()]},b:function(d){return Date.ext.locales[d.locale].b[d.getMonth()]},B:function(d){return Date.ext.locales[d.locale].B[d.getMonth()]},c:"toLocaleString",C:function(d){return Date.ext.util.xPad(parseInt(d.getFullYear()/100,10),0)},d:["getDate","0"],e:["getDate"," "],g:function(d){return Date.ext.util.xPad(parseInt(Date.ext.util.G(d)/100,10),0)},G:function(d){var y=d.getFullYear();var V=parseInt(Date.ext.formats.V(d),10);var W=parseInt(Date.ext.formats.W(d),10);if(W>V){y++}else{if(W===0&&V>=52){y--}}return y},H:["getHours","0"],I:function(d){var I=d.getHours()%12;return Date.ext.util.xPad(I===0?12:I,0)},j:function(d){var ms=d-new Date(""+d.getFullYear()+"/1/1 GMT");ms+=d.getTimezoneOffset()*60000;var doy=parseInt(ms/60000/60/24,10)+1;return Date.ext.util.xPad(doy,0,100)},m:function(d){return Date.ext.util.xPad(d.getMonth()+1,0)},M:["getMinutes","0"],p:function(d){return Date.ext.locales[d.locale].p[d.getHours()>=12?1:0]},P:function(d){return Date.ext.locales[d.locale].P[d.getHours()>=12?1:0]},S:["getSeconds","0"],u:function(d){var dow=d.getDay();return dow===0?7:dow},U:function(d){var doy=parseInt(Date.ext.formats.j(d),10);var rdow=6-d.getDay();var woy=parseInt((doy+rdow)/7,10);return Date.ext.util.xPad(woy,0)},V:function(d){var woy=parseInt(Date.ext.formats.W(d),10);var dow1_1=(new Date(""+d.getFullYear()+"/1/1")).getDay();var idow=woy+(dow1_1>4||dow1_1<=1?0:1);if(idow==53&&(new Date(""+d.getFullYear()+"/12/31")).getDay()<4){idow=1}else{if(idow===0){idow=Date.ext.formats.V(new Date(""+(d.getFullYear()-1)+"/12/31"))}}return Date.ext.util.xPad(idow,0)},w:"getDay",W:function(d){var doy=parseInt(Date.ext.formats.j(d),10);var rdow=7-Date.ext.formats.u(d);var woy=parseInt((doy+rdow)/7,10);return Date.ext.util.xPad(woy,0,10)},y:function(d){return Date.ext.util.xPad(d.getFullYear()%100,0)},Y:"getFullYear",z:function(d){var o=d.getTimezoneOffset();var H=Date.ext.util.xPad(parseInt(Math.abs(o/60),10),0);var M=Date.ext.util.xPad(o%60,0);return(o>0?"-":"+")+H+M},Z:function(d){return d.toString().replace(/^.*\(([^)]+)\)$/,"$1")},"%":function(d){return"%"}};Date.ext.aggregates={c:"locale",D:"%m/%d/%y",h:"%b",n:"\n",r:"%I:%M:%S %p",R:"%H:%M",t:"\t",T:"%H:%M:%S",x:"locale",X:"locale"};Date.ext.aggregates.z=Date.ext.formats.z(new Date());Date.ext.aggregates.Z=Date.ext.formats.Z(new Date());Date.ext.unsupported={};Date.prototype.strftime=function(fmt){if(!(this.locale in Date.ext.locales)){if(this.locale.replace(/-[a-zA-Z]+$/,"") in Date.ext.locales){this.locale=this.locale.replace(/-[a-zA-Z]+$/,"")}else{this.locale="en-GB"}}var d=this;while(fmt.match(/%[cDhnrRtTxXzZ]/)){fmt=fmt.replace(/%([cDhnrRtTxXzZ])/g,function(m0,m1){var f=Date.ext.aggregates[m1];return(f=="locale"?Date.ext.locales[d.locale][m1]:f)})}var str=fmt.replace(/%([aAbBCdegGHIjmMpPSuUVwWyY%])/g,function(m0,m1){var f=Date.ext.formats[m1];if(typeof (f)=="string"){return d[f]()}else{if(typeof (f)=="function"){return f.call(d,d)}else{if(typeof (f)=="object"&&typeof (f[0])=="string"){return Date.ext.util.xPad(d[f[0]](),f[1])}else{return m1}}}});d=null;return str};
|
1417
|
+
})();}
|
1418
|
+
/*!
|
1419
|
+
* Cross-Browser Split 1.1.1
|
1420
|
+
* Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
|
1421
|
+
* Available under the MIT License
|
1422
|
+
* ECMAScript compliant, uniform cross-browser split method
|
1423
|
+
*/
|
1424
|
+
|
1425
|
+
/**
|
1426
|
+
* Splits a string into an array of strings using a regex or string separator. Matches of the
|
1427
|
+
* separator are not included in the result array. However, if `separator` is a regex that contains
|
1428
|
+
* capturing groups, backreferences are spliced into the result each time `separator` is matched.
|
1429
|
+
* Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
|
1430
|
+
* cross-browser.
|
1431
|
+
* @param {String} str String to split.
|
1432
|
+
* @param {RegExp|String} separator Regex or string to use for separating the string.
|
1433
|
+
* @param {Number} [limit] Maximum number of items to include in the result array.
|
1434
|
+
* @returns {Array} Array of substrings.
|
1435
|
+
* @example
|
1436
|
+
*
|
1437
|
+
* // Basic use
|
1438
|
+
* split('a b c d', ' ');
|
1439
|
+
* // -> ['a', 'b', 'c', 'd']
|
1440
|
+
*
|
1441
|
+
* // With limit
|
1442
|
+
* split('a b c d', ' ', 2);
|
1443
|
+
* // -> ['a', 'b']
|
1444
|
+
*
|
1445
|
+
* // Backreferences in result array
|
1446
|
+
* split('..word1 word2..', /([a-z]+)(\d+)/i);
|
1447
|
+
* // -> ['..', 'word', '1', ' ', 'word', '2', '..']
|
1448
|
+
*/
|
1449
|
+
var split;
|
1450
|
+
|
1451
|
+
split = split || function (undef) {
|
1452
|
+
|
1453
|
+
var nativeSplit = String.prototype.split,
|
1454
|
+
compliantExecNpcg = /()??/.exec("")[1] === undef, // NPCG: nonparticipating capturing group
|
1455
|
+
self;
|
1456
|
+
|
1457
|
+
self = function (str, separator, limit) {
|
1458
|
+
if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
|
1459
|
+
return nativeSplit.call(str, separator, limit);
|
1460
|
+
}
|
1461
|
+
var output = [],
|
1462
|
+
flags = (separator.ignoreCase ? "i" : "") +
|
1463
|
+
(separator.multiline ? "m" : "") +
|
1464
|
+
(separator.extended ? "x" : "") + // Proposed for ES6
|
1465
|
+
(separator.sticky ? "y" : ""), // Firefox 3+
|
1466
|
+
lastLastIndex = 0,
|
1467
|
+
separator = new RegExp(separator.source, flags + "g"),
|
1468
|
+
separator2, match, lastIndex, lastLength;
|
1469
|
+
str += ""; // Type-convert
|
1470
|
+
if (!compliantExecNpcg) {
|
1471
|
+
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
|
1472
|
+
}
|
1473
|
+
/* Values for `limit`, per the spec:
|
1474
|
+
* If undefined: 4294967295 // Math.pow(2, 32) - 1
|
1475
|
+
* If 0, Infinity, or NaN: 0
|
1476
|
+
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
|
1477
|
+
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
|
1478
|
+
* If other: Type-convert, then use the above rules
|
1479
|
+
*/
|
1480
|
+
limit = limit === undef ?
|
1481
|
+
-1 >>> 0 : // Math.pow(2, 32) - 1
|
1482
|
+
limit >>> 0; // ToUint32(limit)
|
1483
|
+
while (match = separator.exec(str)) {
|
1484
|
+
lastIndex = match.index + match[0].length;
|
1485
|
+
if (lastIndex > lastLastIndex) {
|
1486
|
+
output.push(str.slice(lastLastIndex, match.index));
|
1487
|
+
if (!compliantExecNpcg && match.length > 1) {
|
1488
|
+
match[0].replace(separator2, function () {
|
1489
|
+
for (var i = 1; i < arguments.length - 2; i++) {
|
1490
|
+
if (arguments[i] === undef) {
|
1491
|
+
match[i] = undef;
|
1492
|
+
}
|
1493
|
+
}
|
1494
|
+
});
|
1495
|
+
}
|
1496
|
+
if (match.length > 1 && match.index < str.length) {
|
1497
|
+
Array.prototype.push.apply(output, match.slice(1));
|
1498
|
+
}
|
1499
|
+
lastLength = match[0].length;
|
1500
|
+
lastLastIndex = lastIndex;
|
1501
|
+
if (output.length >= limit) {
|
1502
|
+
break;
|
1503
|
+
}
|
1504
|
+
}
|
1505
|
+
if (separator.lastIndex === match.index) {
|
1506
|
+
separator.lastIndex++; // Avoid an infinite loop
|
1507
|
+
}
|
1508
|
+
}
|
1509
|
+
if (lastLastIndex === str.length) {
|
1510
|
+
if (lastLength || !separator.test("")) {
|
1511
|
+
output.push("");
|
1512
|
+
}
|
1513
|
+
} else {
|
1514
|
+
output.push(str.slice(lastLastIndex));
|
1515
|
+
}
|
1516
|
+
return output.length > limit ? output.slice(0, limit) : output;
|
1517
|
+
};
|
1518
|
+
|
1519
|
+
String.prototype.split = function (separator, limit) {
|
1520
|
+
return self(this, separator, limit);
|
1521
|
+
};
|
1522
|
+
|
1523
|
+
return self;
|
1524
|
+
|
1525
|
+
}();
|
1526
|
+
|
1527
|
+
if (typeof exports !== 'undefined') {
|
1528
|
+
if (typeof module !== 'undefined' && module.exports) {
|
1529
|
+
exports = module.exports = Liquid;
|
1530
|
+
}
|
1531
|
+
exports.Liquid = Liquid;
|
1532
|
+
}
|