quintype-liquid 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|