1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | (function(undefined) {
|
9 | var Mock = {
|
10 | version: "0.1.2",
|
11 | _mocked: {}
|
12 | };
|
13 |
|
14 | var Util = function() {
|
15 | var Util = {};
|
16 | Util.extend = function extend() {
|
17 | var target = arguments[0] || {}, i = 1, length = arguments.length, options, name, src, copy, clone;
|
18 | if (length === 1) {
|
19 | target = this;
|
20 | i = 0;
|
21 | }
|
22 | for (;i < length; i++) {
|
23 | options = arguments[i];
|
24 | if (!options) continue;
|
25 | for (name in options) {
|
26 | src = target[name];
|
27 | copy = options[name];
|
28 | if (target === copy) continue;
|
29 | if (copy === undefined) continue;
|
30 | if (Util.isArray(copy) || Util.isObject(copy)) {
|
31 | if (Util.isArray(copy)) clone = src && Util.isArray(src) ? src : [];
|
32 | if (Util.isObject(copy)) clone = src && Util.isObject(src) ? src : {};
|
33 | target[name] = Util.extend(clone, copy);
|
34 | } else {
|
35 | target[name] = copy;
|
36 | }
|
37 | }
|
38 | }
|
39 | return target;
|
40 | };
|
41 | Util.each = function each(obj, iterator, context) {
|
42 | var i, key;
|
43 | if (this.type(obj) === "number") {
|
44 | for (i = 0; i < obj; i++) {
|
45 | iterator(i, i);
|
46 | }
|
47 | } else if (obj.length === +obj.length) {
|
48 | for (i = 0; i < obj.length; i++) {
|
49 | if (iterator.call(context, obj[i], i, obj) === false) break;
|
50 | }
|
51 | } else {
|
52 | for (key in obj) {
|
53 | if (iterator.call(context, obj[key], key, obj) === false) break;
|
54 | }
|
55 | }
|
56 | };
|
57 | Util.type = function type(obj) {
|
58 | return obj === null || obj === undefined ? String(obj) : Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1].toLowerCase();
|
59 | };
|
60 | Util.each("String Object Array RegExp Function".split(" "), function(value) {
|
61 | Util["is" + value] = function(obj) {
|
62 | return Util.type(obj) === value.toLowerCase();
|
63 | };
|
64 | });
|
65 | Util.isObjectOrArray = function(value) {
|
66 | return Util.isObject(value) || Util.isArray(value);
|
67 | };
|
68 | Util.isNumeric = function(value) {
|
69 | return !isNaN(parseFloat(value)) && isFinite(value);
|
70 | };
|
71 | Util.keys = function(obj) {
|
72 | var keys = [];
|
73 | for (var key in obj) {
|
74 | if (obj.hasOwnProperty(key)) keys.push(key);
|
75 | }
|
76 | return keys;
|
77 | };
|
78 | Util.values = function(obj) {
|
79 | var values = [];
|
80 | for (var key in obj) {
|
81 | if (obj.hasOwnProperty(key)) values.push(obj[key]);
|
82 | }
|
83 | return values;
|
84 | };
|
85 | Util.heredoc = function heredoc(fn) {
|
86 | return fn.toString().replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, "").replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, "");
|
87 | };
|
88 | Util.noop = function() {};
|
89 | return Util;
|
90 | }();
|
91 |
|
92 | var Random = function() {
|
93 | var Random = {
|
94 | extend: Util.extend
|
95 | };
|
96 | Random.extend({
|
97 | "boolean": function(min, max, cur) {
|
98 | if (cur !== undefined) {
|
99 | min = typeof min !== "undefined" && !isNaN(min) ? parseInt(min, 10) : 1;
|
100 | max = typeof max !== "undefined" && !isNaN(max) ? parseInt(max, 10) : 1;
|
101 | return Math.random() > 1 / (min + max) * min ? !cur : cur;
|
102 | }
|
103 | return Math.random() >= .5;
|
104 | },
|
105 | bool: function(min, max, cur) {
|
106 | return this.boolean(min, max, cur);
|
107 | },
|
108 | natural: function(min, max) {
|
109 | min = typeof min !== "undefined" ? parseInt(min, 10) : 0;
|
110 | max = typeof max !== "undefined" ? parseInt(max, 10) : 9007199254740992;
|
111 | return Math.round(Math.random() * (max - min)) + min;
|
112 | },
|
113 | integer: function(min, max) {
|
114 | min = typeof min !== "undefined" ? parseInt(min, 10) : -9007199254740992;
|
115 | max = typeof max !== "undefined" ? parseInt(max, 10) : 9007199254740992;
|
116 | return Math.round(Math.random() * (max - min)) + min;
|
117 | },
|
118 | "int": function(min, max) {
|
119 | return this.integer(min, max);
|
120 | },
|
121 | "float": function(min, max, dmin, dmax) {
|
122 | dmin = dmin === undefined ? 0 : dmin;
|
123 | dmin = Math.max(Math.min(dmin, 17), 0);
|
124 | dmax = dmax === undefined ? 17 : dmax;
|
125 | dmax = Math.max(Math.min(dmax, 17), 0);
|
126 | var ret = this.integer(min, max) + ".";
|
127 | for (var i = 0, dcount = this.natural(dmin, dmax); i < dcount; i++) {
|
128 | ret += this.character("number");
|
129 | }
|
130 | return parseFloat(ret, 10);
|
131 | },
|
132 | character: function(pool) {
|
133 | var pools = {
|
134 | lower: "abcdefghijklmnopqrstuvwxyz",
|
135 | upper: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
136 | number: "0123456789",
|
137 | symbol: "!@#$%^&*()[]"
|
138 | };
|
139 | pools.alpha = pools.lower + pools.upper;
|
140 | pools["undefined"] = pools.lower + pools.upper + pools.number + pools.symbol;
|
141 | pool = pools[("" + pool).toLowerCase()] || pool;
|
142 | return pool.charAt(Random.natural(0, pool.length - 1));
|
143 | },
|
144 | "char": function(pool) {
|
145 | return this.character(pool);
|
146 | },
|
147 | string: function(pool, min, max) {
|
148 | var length;
|
149 | if (arguments.length === 3) {
|
150 | length = Random.natural(min, max);
|
151 | }
|
152 | if (arguments.length === 2) {
|
153 | if (typeof arguments[0] === "string") {
|
154 | length = min;
|
155 | } else {
|
156 | length = Random.natural(pool, min);
|
157 | pool = undefined;
|
158 | }
|
159 | }
|
160 | if (arguments.length === 1) {
|
161 | length = pool;
|
162 | pool = undefined;
|
163 | }
|
164 | if (arguments.length === 0) {
|
165 | length = Random.natural(3, 7);
|
166 | }
|
167 | var text = "";
|
168 | for (var i = 0; i < length; i++) {
|
169 | text += Random.character(pool);
|
170 | }
|
171 | return text;
|
172 | },
|
173 | str: function(pool, min, max) {
|
174 | return this.string(pool, min, max);
|
175 | },
|
176 | range: function(start, stop, step) {
|
177 | if (arguments.length <= 1) {
|
178 | stop = start || 0;
|
179 | start = 0;
|
180 | }
|
181 | step = arguments[2] || 1;
|
182 | start = +start, stop = +stop, step = +step;
|
183 | var len = Math.max(Math.ceil((stop - start) / step), 0);
|
184 | var idx = 0;
|
185 | var range = new Array(len);
|
186 | while (idx < len) {
|
187 | range[idx++] = start;
|
188 | start += step;
|
189 | }
|
190 | return range;
|
191 | }
|
192 | });
|
193 | Random.extend({
|
194 | patternLetters: {
|
195 | yyyy: "getFullYear",
|
196 | yy: function(date) {
|
197 | return ("" + date.getFullYear()).slice(2);
|
198 | },
|
199 | y: "yy",
|
200 | MM: function(date) {
|
201 | var m = date.getMonth() + 1;
|
202 | return m < 10 ? "0" + m : m;
|
203 | },
|
204 | M: function(date) {
|
205 | return date.getMonth() + 1;
|
206 | },
|
207 | dd: function(date) {
|
208 | var d = date.getDate();
|
209 | return d < 10 ? "0" + d : d;
|
210 | },
|
211 | d: "getDate",
|
212 | HH: function(date) {
|
213 | var h = date.getHours();
|
214 | return h < 10 ? "0" + h : h;
|
215 | },
|
216 | H: "getHours",
|
217 | hh: function(date) {
|
218 | var h = date.getHours() % 12;
|
219 | return h < 10 ? "0" + h : h;
|
220 | },
|
221 | h: function(date) {
|
222 | return date.getHours() % 12;
|
223 | },
|
224 | mm: function(date) {
|
225 | var m = date.getMinutes();
|
226 | return m < 10 ? "0" + m : m;
|
227 | },
|
228 | m: "getMinutes",
|
229 | ss: function(date) {
|
230 | var s = date.getSeconds();
|
231 | return s < 10 ? "0" + s : s;
|
232 | },
|
233 | s: "getSeconds",
|
234 | SS: function(date) {
|
235 | var ms = date.getMilliseconds();
|
236 | return ms < 10 && "00" + ms || ms < 100 && "0" + ms || ms;
|
237 | },
|
238 | S: "getMilliseconds",
|
239 | A: function(date) {
|
240 | return date.getHours() < 12 ? "AM" : "PM";
|
241 | },
|
242 | a: function(date) {
|
243 | return date.getHours() < 12 ? "am" : "pm";
|
244 | },
|
245 | T: "getTime"
|
246 | }
|
247 | });
|
248 | Random.extend({
|
249 | rformat: new RegExp(function() {
|
250 | var re = [];
|
251 | for (var i in Random.patternLetters) re.push(i);
|
252 | return "(" + re.join("|") + ")";
|
253 | }(), "g"),
|
254 | format: function(date, format) {
|
255 | var patternLetters = Random.patternLetters, rformat = Random.rformat;
|
256 | return format.replace(rformat, function($0, flag) {
|
257 | return typeof patternLetters[flag] === "function" ? patternLetters[flag](date) : patternLetters[flag] in patternLetters ? arguments.callee($0, patternLetters[flag]) : date[patternLetters[flag]]();
|
258 | });
|
259 | },
|
260 | randomDate: function(min, max) {
|
261 | min = min === undefined ? new Date(0) : min;
|
262 | max = max === undefined ? new Date() : max;
|
263 | return new Date(Math.random() * (max.getTime() - min.getTime()));
|
264 | },
|
265 | date: function(format) {
|
266 | format = format || "yyyy-MM-dd";
|
267 | return this.format(this.randomDate(), format);
|
268 | },
|
269 | time: function(format) {
|
270 | format = format || "HH:mm:ss";
|
271 | return this.format(this.randomDate(), format);
|
272 | },
|
273 | datetime: function(format) {
|
274 | format = format || "yyyy-MM-dd HH:mm:ss";
|
275 | return this.format(this.randomDate(), format);
|
276 | },
|
277 | now: function(unit, format) {
|
278 | if (arguments.length === 1) {
|
279 | if (!/year|month|week|day|hour|minute|second|week/.test(unit)) {
|
280 | format = unit;
|
281 | unit = "";
|
282 | }
|
283 | }
|
284 | unit = (unit || "").toLowerCase();
|
285 | format = format || "yyyy-MM-dd HH:mm:ss";
|
286 | var date = new Date();
|
287 | switch (unit) {
|
288 | case "year":
|
289 | date.setMonth(0);
|
290 |
|
291 | case "month":
|
292 | date.setDate(1);
|
293 |
|
294 | case "week":
|
295 | case "day":
|
296 | date.setHours(0);
|
297 |
|
298 | case "hour":
|
299 | date.setMinutes(0);
|
300 |
|
301 | case "minute":
|
302 | date.setSeconds(0);
|
303 |
|
304 | case "second":
|
305 | date.setMilliseconds(0);
|
306 | }
|
307 | switch (unit) {
|
308 | case "week":
|
309 | date.setDate(date.getDate() - date.getDay());
|
310 | }
|
311 | return this.format(date, format);
|
312 | }
|
313 | });
|
314 | Random.extend({
|
315 | ad_size: [ "300x250", "250x250", "240x400", "336x280", "180x150", "720x300", "468x60", "234x60", "88x31", "120x90", "120x60", "120x240", "125x125", "728x90", "160x600", "120x600", "300x600" ],
|
316 | screen_size: [ "320x200", "320x240", "640x480", "800x480", "800x480", "1024x600", "1024x768", "1280x800", "1440x900", "1920x1200", "2560x1600" ],
|
317 | video_size: [ "720x480", "768x576", "1280x720", "1920x1080" ],
|
318 | image: function(size, background, foreground, format, text) {
|
319 | if (arguments.length === 4) {
|
320 | text = format;
|
321 | format = undefined;
|
322 | }
|
323 | if (arguments.length === 3) {
|
324 | text = foreground;
|
325 | foreground = undefined;
|
326 | }
|
327 | if (!size) size = this.pick(this.ad_size);
|
328 | if (background && ~background.indexOf("#")) background = background.slice(1);
|
329 | if (foreground && ~foreground.indexOf("#")) foreground = foreground.slice(1);
|
330 | return "http://dummyimage.com/" + size + (background ? "/" + background : "") + (foreground ? "/" + foreground : "") + (format ? "." + format : "") + (text ? "&text=" + text : "");
|
331 | },
|
332 | img: function() {
|
333 | return this.image.apply(this, arguments);
|
334 | }
|
335 | });
|
336 | Random.extend({
|
337 | brandColors: {
|
338 | "4ormat": "#fb0a2a",
|
339 | "500px": "#02adea",
|
340 | "About.me (blue)": "#00405d",
|
341 | "About.me (yellow)": "#ffcc33",
|
342 | Addvocate: "#ff6138",
|
343 | Adobe: "#ff0000",
|
344 | Aim: "#fcd20b",
|
345 | Amazon: "#e47911",
|
346 | Android: "#a4c639",
|
347 | "Angie's List": "#7fbb00",
|
348 | AOL: "#0060a3",
|
349 | Atlassian: "#003366",
|
350 | Behance: "#053eff",
|
351 | "Big Cartel": "#97b538",
|
352 | bitly: "#ee6123",
|
353 | Blogger: "#fc4f08",
|
354 | Boeing: "#0039a6",
|
355 | "Booking.com": "#003580",
|
356 | Carbonmade: "#613854",
|
357 | Cheddar: "#ff7243",
|
358 | "Code School": "#3d4944",
|
359 | Delicious: "#205cc0",
|
360 | Dell: "#3287c1",
|
361 | Designmoo: "#e54a4f",
|
362 | Deviantart: "#4e6252",
|
363 | "Designer News": "#2d72da",
|
364 | Devour: "#fd0001",
|
365 | DEWALT: "#febd17",
|
366 | "Disqus (blue)": "#59a3fc",
|
367 | "Disqus (orange)": "#db7132",
|
368 | Dribbble: "#ea4c89",
|
369 | Dropbox: "#3d9ae8",
|
370 | Drupal: "#0c76ab",
|
371 | Dunked: "#2a323a",
|
372 | eBay: "#89c507",
|
373 | Ember: "#f05e1b",
|
374 | Engadget: "#00bdf6",
|
375 | Envato: "#528036",
|
376 | Etsy: "#eb6d20",
|
377 | Evernote: "#5ba525",
|
378 | "Fab.com": "#dd0017",
|
379 | Facebook: "#3b5998",
|
380 | Firefox: "#e66000",
|
381 | "Flickr (blue)": "#0063dc",
|
382 | "Flickr (pink)": "#ff0084",
|
383 | Forrst: "#5b9a68",
|
384 | Foursquare: "#25a0ca",
|
385 | Garmin: "#007cc3",
|
386 | GetGlue: "#2d75a2",
|
387 | Gimmebar: "#f70078",
|
388 | GitHub: "#171515",
|
389 | "Google Blue": "#0140ca",
|
390 | "Google Green": "#16a61e",
|
391 | "Google Red": "#dd1812",
|
392 | "Google Yellow": "#fcca03",
|
393 | "Google+": "#dd4b39",
|
394 | Grooveshark: "#f77f00",
|
395 | Groupon: "#82b548",
|
396 | "Hacker News": "#ff6600",
|
397 | HelloWallet: "#0085ca",
|
398 | "Heroku (light)": "#c7c5e6",
|
399 | "Heroku (dark)": "#6567a5",
|
400 | HootSuite: "#003366",
|
401 | Houzz: "#73ba37",
|
402 | HTML5: "#ec6231",
|
403 | IKEA: "#ffcc33",
|
404 | IMDb: "#f3ce13",
|
405 | Instagram: "#3f729b",
|
406 | Intel: "#0071c5",
|
407 | Intuit: "#365ebf",
|
408 | Kickstarter: "#76cc1e",
|
409 | kippt: "#e03500",
|
410 | Kodery: "#00af81",
|
411 | LastFM: "#c3000d",
|
412 | LinkedIn: "#0e76a8",
|
413 | Livestream: "#cf0005",
|
414 | Lumo: "#576396",
|
415 | Mixpanel: "#a086d3",
|
416 | Meetup: "#e51937",
|
417 | Nokia: "#183693",
|
418 | NVIDIA: "#76b900",
|
419 | Opera: "#cc0f16",
|
420 | Path: "#e41f11",
|
421 | "PayPal (dark)": "#1e477a",
|
422 | "PayPal (light)": "#3b7bbf",
|
423 | Pinboard: "#0000e6",
|
424 | Pinterest: "#c8232c",
|
425 | PlayStation: "#665cbe",
|
426 | Pocket: "#ee4056",
|
427 | Prezi: "#318bff",
|
428 | Pusha: "#0f71b4",
|
429 | Quora: "#a82400",
|
430 | "QUOTE.fm": "#66ceff",
|
431 | Rdio: "#008fd5",
|
432 | Readability: "#9c0000",
|
433 | "Red Hat": "#cc0000",
|
434 | Resource: "#7eb400",
|
435 | Rockpack: "#0ba6ab",
|
436 | Roon: "#62b0d9",
|
437 | RSS: "#ee802f",
|
438 | Salesforce: "#1798c1",
|
439 | Samsung: "#0c4da2",
|
440 | Shopify: "#96bf48",
|
441 | Skype: "#00aff0",
|
442 | Snagajob: "#f47a20",
|
443 | Softonic: "#008ace",
|
444 | SoundCloud: "#ff7700",
|
445 | "Space Box": "#f86960",
|
446 | Spotify: "#81b71a",
|
447 | Sprint: "#fee100",
|
448 | Squarespace: "#121212",
|
449 | StackOverflow: "#ef8236",
|
450 | Staples: "#cc0000",
|
451 | "Status Chart": "#d7584f",
|
452 | Stripe: "#008cdd",
|
453 | StudyBlue: "#00afe1",
|
454 | StumbleUpon: "#f74425",
|
455 | "T-Mobile": "#ea0a8e",
|
456 | Technorati: "#40a800",
|
457 | "The Next Web": "#ef4423",
|
458 | Treehouse: "#5cb868",
|
459 | Trulia: "#5eab1f",
|
460 | Tumblr: "#34526f",
|
461 | "Twitch.tv": "#6441a5",
|
462 | Twitter: "#00acee",
|
463 | TYPO3: "#ff8700",
|
464 | Ubuntu: "#dd4814",
|
465 | Ustream: "#3388ff",
|
466 | Verizon: "#ef1d1d",
|
467 | Vimeo: "#86c9ef",
|
468 | Vine: "#00a478",
|
469 | Virb: "#06afd8",
|
470 | "Virgin Media": "#cc0000",
|
471 | Wooga: "#5b009c",
|
472 | "WordPress (blue)": "#21759b",
|
473 | "WordPress (orange)": "#d54e21",
|
474 | "WordPress (grey)": "#464646",
|
475 | Wunderlist: "#2b88d9",
|
476 | XBOX: "#9bc848",
|
477 | XING: "#126567",
|
478 | "Yahoo!": "#720e9e",
|
479 | Yandex: "#ffcc00",
|
480 | Yelp: "#c41200",
|
481 | YouTube: "#c4302b",
|
482 | Zalongo: "#5498dc",
|
483 | Zendesk: "#78a300",
|
484 | Zerply: "#9dcc7a",
|
485 | Zootool: "#5e8b1d"
|
486 | },
|
487 | brands: function() {
|
488 | var brands = [];
|
489 | for (var b in this.brandColors) {
|
490 | brands.push(b);
|
491 | }
|
492 | return brands;
|
493 | },
|
494 | dataImage: function(size, text) {
|
495 | var canvas = typeof document !== "undefined" && document.createElement("canvas"), ctx = canvas && canvas.getContext && canvas.getContext("2d");
|
496 | if (!canvas || !ctx) return "";
|
497 | if (!size) size = this.pick(this.ad_size);
|
498 | text = text !== undefined ? text : size;
|
499 | size = size.split("x");
|
500 | var width = parseInt(size[0], 10), height = parseInt(size[1], 10), background = this.brandColors[this.pick(this.brands())], foreground = "#FFF", text_height = 14, font = "sans-serif";
|
501 | canvas.width = width;
|
502 | canvas.height = height;
|
503 | ctx.textAlign = "center";
|
504 | ctx.textBaseline = "middle";
|
505 | ctx.fillStyle = background;
|
506 | ctx.fillRect(0, 0, width, height);
|
507 | ctx.fillStyle = foreground;
|
508 | ctx.font = "bold " + text_height + "px " + font;
|
509 | ctx.fillText(text, width / 2, height / 2, width);
|
510 | return canvas.toDataURL("image/png");
|
511 | }
|
512 | });
|
513 | Random.extend({
|
514 | color: function() {
|
515 | var colour = Math.floor(Math.random() * (16 * 16 * 16 * 16 * 16 * 16 - 1)).toString(16);
|
516 | colour = "#" + ("000000" + colour).slice(-6);
|
517 | return colour;
|
518 | }
|
519 | });
|
520 | Random.extend({
|
521 | capitalize: function(word) {
|
522 | return (word + "").charAt(0).toUpperCase() + (word + "").substr(1);
|
523 | },
|
524 | upper: function(str) {
|
525 | return (str + "").toUpperCase();
|
526 | },
|
527 | lower: function(str) {
|
528 | return (str + "").toLowerCase();
|
529 | },
|
530 | pick: function(arr) {
|
531 | arr = arr || [];
|
532 | return arr[this.natural(0, arr.length - 1)];
|
533 | },
|
534 | shuffle: function(arr) {
|
535 | arr = arr || [];
|
536 | var old = arr.slice(0), result = [], index = 0, length = old.length;
|
537 | for (var i = 0; i < length; i++) {
|
538 | index = this.natural(0, old.length - 1);
|
539 | result.push(old[index]);
|
540 | old.splice(index, 1);
|
541 | }
|
542 | return result;
|
543 | }
|
544 | });
|
545 | Random.extend({
|
546 | paragraph: function(min, max) {
|
547 | var len;
|
548 | if (arguments.length === 0) len = Random.natural(3, 7);
|
549 | if (arguments.length === 1) len = max = min;
|
550 | if (arguments.length === 2) {
|
551 | min = parseInt(min, 10);
|
552 | max = parseInt(max, 10);
|
553 | len = Random.natural(min, max);
|
554 | }
|
555 | var arr = [];
|
556 | for (var i = 0; i < len; i++) {
|
557 | arr.push(Random.sentence());
|
558 | }
|
559 | return arr.join(" ");
|
560 | },
|
561 | sentence: function(min, max) {
|
562 | var len;
|
563 | if (arguments.length === 0) len = Random.natural(12, 18);
|
564 | if (arguments.length === 1) len = max = min;
|
565 | if (arguments.length === 2) {
|
566 | min = parseInt(min, 10);
|
567 | max = parseInt(max, 10);
|
568 | len = Random.natural(min, max);
|
569 | }
|
570 | var arr = [];
|
571 | for (var i = 0; i < len; i++) {
|
572 | arr.push(Random.word());
|
573 | }
|
574 | return Random.capitalize(arr.join(" ")) + ".";
|
575 | },
|
576 | word: function(min, max) {
|
577 | var len;
|
578 | if (arguments.length === 0) len = Random.natural(3, 10);
|
579 | if (arguments.length === 1) len = max = min;
|
580 | if (arguments.length === 2) {
|
581 | min = parseInt(min, 10);
|
582 | max = parseInt(max, 10);
|
583 | len = Random.natural(min, max);
|
584 | }
|
585 | var result = "";
|
586 | for (var i = 0; i < len; i++) {
|
587 | result += Random.character("lower");
|
588 | }
|
589 | return result;
|
590 | },
|
591 | title: function(min, max) {
|
592 | var len, result = [];
|
593 | if (arguments.length === 0) len = Random.natural(3, 7);
|
594 | if (arguments.length === 1) len = max = min;
|
595 | if (arguments.length === 2) {
|
596 | min = parseInt(min, 10);
|
597 | max = parseInt(max, 10);
|
598 | len = Random.natural(min, max);
|
599 | }
|
600 | for (var i = 0; i < len; i++) {
|
601 | result.push(this.capitalize(this.word()));
|
602 | }
|
603 | return result.join(" ");
|
604 | }
|
605 | });
|
606 | Random.extend({
|
607 | first: function() {
|
608 | var names = [ "James", "John", "Robert", "Michael", "William", "David", "Richard", "Charles", "Joseph", "Thomas", "Christopher", "Daniel", "Paul", "Mark", "Donald", "George", "Kenneth", "Steven", "Edward", "Brian", "Ronald", "Anthony", "Kevin", "Jason", "Matthew", "Gary", "Timothy", "Jose", "Larry", "Jeffrey", "Frank", "Scott", "Eric" ].concat([ "Mary", "Patricia", "Linda", "Barbara", "Elizabeth", "Jennifer", "Maria", "Susan", "Margaret", "Dorothy", "Lisa", "Nancy", "Karen", "Betty", "Helen", "Sandra", "Donna", "Carol", "Ruth", "Sharon", "Michelle", "Laura", "Sarah", "Kimberly", "Deborah", "Jessica", "Shirley", "Cynthia", "Angela", "Melissa", "Brenda", "Amy", "Anna" ]);
|
609 | return this.pick(names);
|
610 | return this.capitalize(this.word());
|
611 | },
|
612 | last: function() {
|
613 | var names = [ "Smith", "Johnson", "Williams", "Brown", "Jones", "Miller", "Davis", "Garcia", "Rodriguez", "Wilson", "Martinez", "Anderson", "Taylor", "Thomas", "Hernandez", "Moore", "Martin", "Jackson", "Thompson", "White", "Lopez", "Lee", "Gonzalez", "Harris", "Clark", "Lewis", "Robinson", "Walker", "Perez", "Hall", "Young", "Allen" ];
|
614 | return this.pick(names);
|
615 | return this.capitalize(this.word());
|
616 | },
|
617 | name: function(middle) {
|
618 | return this.first() + " " + (middle ? this.first() + " " : "") + this.last();
|
619 | }
|
620 | });
|
621 | Random.extend({
|
622 | url: function() {
|
623 | return "http://" + this.domain() + "/" + this.word();
|
624 | },
|
625 | domain: function(tld) {
|
626 | return this.word() + "." + (tld || this.tld());
|
627 | },
|
628 | email: function(domain) {
|
629 | return this.character("lower") + "." + this.last().toLowerCase() + "@" + this.last().toLowerCase() + "." + this.tld();
|
630 | return this.word() + "@" + (domain || this.domain());
|
631 | },
|
632 | ip: function() {
|
633 | return this.natural(0, 255) + "." + this.natural(0, 255) + "." + this.natural(0, 255) + "." + this.natural(0, 255);
|
634 | },
|
635 | tlds: [ "com", "org", "edu", "gov", "co.uk", "net", "io" ],
|
636 | tld: function() {
|
637 | return this.pick(this.tlds);
|
638 | }
|
639 | });
|
640 | Random.extend({
|
641 | areas: [ "东北", "华北", "华东", "华中", "华南", "西南", "西北" ],
|
642 | area: function() {
|
643 | return this.pick(this.areas);
|
644 | },
|
645 | regions: [ "110000 北京市", "120000 天津市", "130000 河北省", "140000 山西省", "150000 内蒙古自治区", "210000 辽宁省", "220000 吉林省", "230000 黑龙江省", "310000 上海市", "320000 江苏省", "330000 浙江省", "340000 安徽省", "350000 福建省", "360000 江西省", "370000 山东省", "410000 河南省", "420000 湖北省", "430000 湖南省", "440000 广东省", "450000 广西壮族自治区", "460000 海南省", "500000 重庆市", "510000 四川省", "520000 贵州省", "530000 云南省", "540000 西藏自治区", "610000 陕西省", "620000 甘肃省", "630000 青海省", "640000 宁夏回族自治区", "650000 新疆维吾尔自治区", "650000 新疆维吾尔自治区", "710000 台湾省", "810000 香港特别行政区", "820000 澳门特别行政区" ],
|
646 | region: function() {
|
647 | return this.pick(this.regions).split(" ")[1];
|
648 | },
|
649 | address: function() {},
|
650 | city: function() {},
|
651 | phone: function() {},
|
652 | areacode: function() {},
|
653 | street: function() {},
|
654 | street_suffixes: function() {},
|
655 | street_suffix: function() {},
|
656 | states: function() {},
|
657 | state: function() {},
|
658 | zip: function(len) {
|
659 | var zip = "";
|
660 | for (var i = 0; i < (len || 6); i++) zip += this.natural(0, 9);
|
661 | return zip;
|
662 | }
|
663 | });
|
664 | Random.extend({
|
665 | todo: function() {
|
666 | return "todo";
|
667 | }
|
668 | });
|
669 | Random.extend({
|
670 | d4: function() {
|
671 | return this.natural(1, 4);
|
672 | },
|
673 | d6: function() {
|
674 | return this.natural(1, 6);
|
675 | },
|
676 | d8: function() {
|
677 | return this.natural(1, 8);
|
678 | },
|
679 | d12: function() {
|
680 | return this.natural(1, 12);
|
681 | },
|
682 | d20: function() {
|
683 | return this.natural(1, 20);
|
684 | },
|
685 | d100: function() {
|
686 | return this.natural(1, 100);
|
687 | },
|
688 | guid: function() {
|
689 | var pool = "ABCDEF1234567890", guid = this.string(pool, 8) + "-" + this.string(pool, 4) + "-" + this.string(pool, 4) + "-" + this.string(pool, 4) + "-" + this.string(pool, 12);
|
690 | return guid;
|
691 | },
|
692 | id: function() {
|
693 | var id, sum = 0, rank = [ "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2" ], last = [ "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" ];
|
694 | id = this.pick(this.regions).split(" ")[0] + this.date("yyyyMMdd") + this.string("number", 3);
|
695 | for (var i = 0; i < id.length; i++) {
|
696 | sum += id[i] * rank[i];
|
697 | }
|
698 | id += last[sum % 11];
|
699 | return id;
|
700 | },
|
701 | autoIncrementInteger: 0,
|
702 | increment: function(step) {
|
703 | return this.autoIncrementInteger += +step || 1;
|
704 | },
|
705 | inc: function(step) {
|
706 | return this.increment(step);
|
707 | }
|
708 | });
|
709 | return Random;
|
710 | }();
|
711 |
|
712 | var rkey = /(.+)\|(?:\+(\d+)|([\+\-]?\d+-?[\+\-]?\d*)?(?:\.(\d+-?\d*))?)/, rrange = /([\+\-]?\d+)-?([\+\-]?\d+)?/, rplaceholder = /\\*@([^@#%&()\?\s\/\.]+)(?:\((.*?)\))?/g;
|
713 | Mock.extend = Util.extend;
|
714 | Mock.mock = function(rurl, rtype, template) {
|
715 | if (arguments.length === 1) {
|
716 | return Handle.gen(rurl);
|
717 | }
|
718 | if (arguments.length === 2) {
|
719 | template = rtype;
|
720 | rtype = undefined;
|
721 | }
|
722 | Mock._mocked[rurl + (rtype || "")] = {
|
723 | rurl: rurl,
|
724 | rtype: rtype,
|
725 | template: template
|
726 | };
|
727 | return Mock;
|
728 | };
|
729 | var Handle = {
|
730 | extend: Util.extend
|
731 | };
|
732 | Handle.rule = function(name) {
|
733 | name = (name || "") + "";
|
734 | var parameters = (name || "").match(rkey), range = parameters && parameters[3] && parameters[3].match(rrange), min = range && parseInt(range[1], 10), max = range && parseInt(range[2], 10), count = range ? !range[2] && parseInt(range[1], 10) || Random.integer(min, max) : 1, decimal = parameters && parameters[4] && parameters[4].match(rrange), dmin = decimal && parseInt(decimal[1], 10), dmax = decimal && parseInt(decimal[2], 10), dcount = decimal ? !decimal[2] && parseInt(decimal[1], 10) || Random.integer(dmin, dmax) : 0, point = parameters && parameters[4];
|
735 | return {
|
736 | parameters: parameters,
|
737 | range: range,
|
738 | min: min,
|
739 | max: max,
|
740 | count: count,
|
741 | decimal: decimal,
|
742 | dmin: dmin,
|
743 | dmax: dmax,
|
744 | dcount: dcount,
|
745 | point: point
|
746 | };
|
747 | };
|
748 | Handle.gen = function(template, name, context) {
|
749 | name = name = (name || "") + "";
|
750 | context = context || {};
|
751 | context = {
|
752 | path: context.path || [],
|
753 | templatePath: context.templatePath || [],
|
754 | currentContext: context.currentContext,
|
755 | templateCurrentContext: context.templateCurrentContext || template,
|
756 | root: context.root,
|
757 | templateRoot: context.templateRoot
|
758 | };
|
759 | var rule = Handle.rule(name);
|
760 | var type = Util.type(template);
|
761 | if (Handle[type]) {
|
762 | return Handle[type]({
|
763 | type: type,
|
764 | template: template,
|
765 | name: name,
|
766 | parsedName: name ? name.replace(rkey, "$1") : name,
|
767 | rule: rule,
|
768 | context: context
|
769 | });
|
770 | }
|
771 | return template;
|
772 | };
|
773 | Handle.extend({
|
774 | array: function(options) {
|
775 | var result = [], i, j;
|
776 | if (!options.rule.parameters) {
|
777 | for (i = 0; i < options.template.length; i++) {
|
778 | options.context.path.push(i);
|
779 | result.push(Handle.gen(options.template[i], i, {
|
780 | currentContext: result,
|
781 | templateCurrentContext: options.template,
|
782 | path: options.context.path
|
783 | }));
|
784 | options.context.path.pop();
|
785 | }
|
786 | } else {
|
787 | if (options.rule.count === 1 && options.template.length > 1) {
|
788 | options.context.path.push(options.name);
|
789 | result = Random.pick(Handle.gen(options.template, undefined, {
|
790 | currentContext: result,
|
791 | templateCurrentContext: options.template,
|
792 | path: options.context.path
|
793 | }));
|
794 | options.context.path.pop();
|
795 | } else {
|
796 | for (i = 0; i < options.rule.count; i++) {
|
797 | j = 0;
|
798 | do {
|
799 | result.push(Handle.gen(options.template[j++]));
|
800 | } while (j < options.template.length);
|
801 | }
|
802 | }
|
803 | }
|
804 | return result;
|
805 | },
|
806 | object: function(options) {
|
807 | var result = {}, keys, fnKeys, key, parsedKey, inc, i;
|
808 | if (options.rule.min) {
|
809 | keys = Util.keys(options.template);
|
810 | keys = Random.shuffle(keys);
|
811 | keys = keys.slice(0, options.rule.count);
|
812 | for (i = 0; i < keys.length; i++) {
|
813 | key = keys[i];
|
814 | parsedKey = key.replace(rkey, "$1");
|
815 | options.context.path.push(parsedKey);
|
816 | result[parsedKey] = Handle.gen(options.template[key], key, {
|
817 | currentContext: result,
|
818 | templateCurrentContext: options.template,
|
819 | path: options.context.path
|
820 | });
|
821 | options.context.path.pop();
|
822 | }
|
823 | } else {
|
824 | keys = [];
|
825 | fnKeys = [];
|
826 | for (key in options.template) {
|
827 | (typeof options.template[key] === "function" ? fnKeys : keys).push(key);
|
828 | }
|
829 | keys = keys.concat(fnKeys);
|
830 | for (i = 0; i < keys.length; i++) {
|
831 | key = keys[i];
|
832 | parsedKey = key.replace(rkey, "$1");
|
833 | options.context.path.push(parsedKey);
|
834 | result[parsedKey] = Handle.gen(options.template[key], key, {
|
835 | currentContext: result,
|
836 | templateCurrentContext: options.template,
|
837 | path: options.context.path
|
838 | });
|
839 | options.context.path.pop();
|
840 | inc = key.match(rkey);
|
841 | if (inc && inc[2] && Util.type(options.template[key]) === "number") {
|
842 | options.template[key] += parseInt(inc[2], 10);
|
843 | }
|
844 | }
|
845 | }
|
846 | return result;
|
847 | },
|
848 | number: function(options) {
|
849 | var result, parts, i;
|
850 | if (options.rule.point) {
|
851 | options.template += "";
|
852 | parts = options.template.split(".");
|
853 | parts[0] = options.rule.range ? options.rule.count : parts[0];
|
854 | parts[1] = (parts[1] || "").slice(0, options.rule.dcount);
|
855 | for (i = 0; parts[1].length < options.rule.dcount; i++) {
|
856 | parts[1] += Random.character("number");
|
857 | }
|
858 | result = parseFloat(parts.join("."), 10);
|
859 | } else {
|
860 | result = options.rule.range && !options.rule.parameters[2] ? options.rule.count : options.template;
|
861 | }
|
862 | return result;
|
863 | },
|
864 | "boolean": function(options) {
|
865 | var result;
|
866 | result = options.rule.parameters ? Random.bool(options.rule.min, options.rule.max, options.template) : options.template;
|
867 | return result;
|
868 | },
|
869 | string: function(options) {
|
870 | var result = "", i, placeholders, ph, phed;
|
871 | if (options.template.length) {
|
872 | for (i = 0; i < options.rule.count; i++) {
|
873 | result += options.template;
|
874 | }
|
875 | placeholders = result.match(rplaceholder) || [];
|
876 | for (i = 0; i < placeholders.length; i++) {
|
877 | ph = placeholders[i];
|
878 | if (/^\\/.test(ph)) {
|
879 | placeholders.splice(i--, 1);
|
880 | continue;
|
881 | }
|
882 | phed = Handle.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext);
|
883 | if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) {
|
884 | result = phed;
|
885 | break;
|
886 | if (Util.isNumeric(phed)) {
|
887 | result = parseFloat(phed, 10);
|
888 | break;
|
889 | }
|
890 | if (/^(true|false)$/.test(phed)) {
|
891 | result = phed === "true" ? true : phed === "false" ? false : phed;
|
892 | break;
|
893 | }
|
894 | }
|
895 | result = result.replace(ph, phed);
|
896 | }
|
897 | } else {
|
898 | result = options.rule.range ? Random.string(options.rule.count) : options.template;
|
899 | }
|
900 | return result;
|
901 | },
|
902 | "function": function(options) {
|
903 | return options.template.call(options.context.currentContext);
|
904 | }
|
905 | });
|
906 | Handle.extend({
|
907 | _all: function() {
|
908 | var re = {};
|
909 | for (var key in Random) re[key.toLowerCase()] = key;
|
910 | return re;
|
911 | },
|
912 | placeholder: function(placeholder, obj, templateContext) {
|
913 | rplaceholder.exec("");
|
914 | var parts = rplaceholder.exec(placeholder), key = parts && parts[1], lkey = key && key.toLowerCase(), okey = this._all()[lkey], params = parts && parts[2] || "";
|
915 | try {
|
916 | params = eval("(function(){ return [].splice.call(arguments, 0 ) })(" + params + ")");
|
917 | } catch (error) {
|
918 | params = parts[2].split(/,\s*/);
|
919 | }
|
920 | if (obj && key in obj) return obj[key];
|
921 | if (templateContext && typeof templateContext === "object" && key in templateContext && placeholder !== templateContext[key]) {
|
922 | templateContext[key] = Handle.gen(templateContext[key], key, {
|
923 | currentContext: obj,
|
924 | templateCurrentContext: templateContext
|
925 | });
|
926 | return templateContext[key];
|
927 | }
|
928 | if (!(key in Random) && !(lkey in Random) && !(okey in Random)) return placeholder;
|
929 | for (var i = 0; i < params.length; i++) {
|
930 | rplaceholder.exec("");
|
931 | if (rplaceholder.test(params[i])) {
|
932 | params[i] = Handle.placeholder(params[i], obj);
|
933 | }
|
934 | }
|
935 | var handle = Random[key] || Random[lkey] || Random[okey];
|
936 | switch (Util.type(handle)) {
|
937 | case "array":
|
938 | return Random.pick(handle);
|
939 |
|
940 | case "function":
|
941 | var re = handle.apply(Random, params);
|
942 | if (re === undefined) re = "";
|
943 | return re;
|
944 | }
|
945 | }
|
946 | });
|
947 |
|
948 | function find(options) {
|
949 | for (var sUrlType in Mock._mocked) {
|
950 | var item = Mock._mocked[sUrlType];
|
951 | if ((!item.rurl || match(item.rurl, options.url)) && (!item.rtype || match(item.rtype, options.type.toLowerCase()))) {
|
952 | return item;
|
953 | }
|
954 | }
|
955 | function match(expected, actual) {
|
956 | if (Util.type(expected) === "string") {
|
957 | return expected === actual;
|
958 | }
|
959 | if (Util.type(expected) === "regexp") {
|
960 | return expected.test(actual);
|
961 | }
|
962 | }
|
963 | }
|
964 | function convert(item, options) {
|
965 | return Util.isFunction(item.template) ? item.template(options) : Mock.mock(item.template);
|
966 | }
|
967 | Mock.mockjax = function mockjax(jQuery) {
|
968 | function mockxhr() {
|
969 | return {
|
970 | readyState: 4,
|
971 | status: 200,
|
972 | statusText: "",
|
973 | open: jQuery.noop,
|
974 | send: function() {
|
975 | this.onload();
|
976 | },
|
977 | setRequestHeader: jQuery.noop,
|
978 | getAllResponseHeaders: jQuery.noop,
|
979 | getResponseHeader: jQuery.noop,
|
980 | statusCode: jQuery.noop,
|
981 | abort: jQuery.noop
|
982 | };
|
983 | }
|
984 | function prefilter(options, originalOptions, jqXHR) {
|
985 | var item = find(options);
|
986 | if (item) {
|
987 | options.dataFilter = options.converters["text json"] = options.converters["text jsonp"] = options.converters["text script"] = options.converters["script json"] = function() {
|
988 | return convert(item, options);
|
989 | };
|
990 | options.xhr = mockxhr;
|
991 | if (originalOptions.dataType !== "script") return "json";
|
992 | }
|
993 | }
|
994 | jQuery.ajaxPrefilter("json jsonp script", prefilter);
|
995 | return Mock;
|
996 | };
|
997 | if (typeof jQuery != "undefined") Mock.mockjax(jQuery);
|
998 | if (typeof Zepto != "undefined") {
|
999 | Mock.mockjax = function(Zepto) {
|
1000 | var __original_ajax = Zepto.ajax;
|
1001 | var xhr = {
|
1002 | readyState: 4,
|
1003 | responseText: "",
|
1004 | responseXML: null,
|
1005 | state: 2,
|
1006 | status: 200,
|
1007 | statusText: "success",
|
1008 | timeoutTimer: null
|
1009 | };
|
1010 | Zepto.ajax = function(options) {
|
1011 | var item = find(options);
|
1012 | if (item) {
|
1013 | var data = Mock.mock(item.template);
|
1014 | if (options.success) options.success(data, xhr, options);
|
1015 | if (options.complete) options.complete(xhr.status, xhr, options);
|
1016 | return xhr;
|
1017 | }
|
1018 | return __original_ajax.call(Zepto, options);
|
1019 | };
|
1020 | };
|
1021 | Mock.mockjax(Zepto);
|
1022 | }
|
1023 | if (typeof KISSY != "undefined" && KISSY.add) {
|
1024 | Mock.mockjax = function mockjax(KISSY) {
|
1025 | var _original_ajax = KISSY.io;
|
1026 | var xhr = {
|
1027 | readyState: 4,
|
1028 | responseText: "",
|
1029 | responseXML: null,
|
1030 | state: 2,
|
1031 | status: 200,
|
1032 | statusText: "success",
|
1033 | timeoutTimer: null
|
1034 | };
|
1035 | KISSY.io = function(options) {
|
1036 | var item = find(options);
|
1037 | if (item) {
|
1038 | var data = Mock.mock(item.template);
|
1039 | if (options.success) options.success(data, xhr, options);
|
1040 | if (options.complete) options.complete(xhr.status, xhr, options);
|
1041 | return xhr;
|
1042 | }
|
1043 | return _original_ajax.apply(this, arguments);
|
1044 | };
|
1045 | for (var name in _original_ajax) {
|
1046 | KISSY.io[name] = _original_ajax[name];
|
1047 | }
|
1048 | };
|
1049 | }
|
1050 |
|
1051 | Mock.Util = Util;
|
1052 | Mock.Random = Random;
|
1053 | Mock.heredoc = Util.heredoc;
|
1054 | if (typeof module === "object" && module.exports) {
|
1055 | module.exports = Mock;
|
1056 | } else if (typeof define === "function" && define.amd) {
|
1057 | define(function() {
|
1058 | return Mock;
|
1059 | });
|
1060 | } else if (typeof define === "function" && define.cmd) {
|
1061 | define(function() {
|
1062 | return Mock;
|
1063 | });
|
1064 | }
|
1065 | this.Mock = Mock;
|
1066 | this.Random = Random;
|
1067 | if (typeof KISSY != "undefined") {
|
1068 | Util.each([ "mock", "components/mock/", "mock/dist/mock", "gallery/Mock/0.1.1/", "gallery/Mock/0.1.2/", "gallery/Mock/0.1.3/" ], function register(name) {
|
1069 | KISSY.add(name, function(S) {
|
1070 | Mock.mockjax(S);
|
1071 | return Mock;
|
1072 | }, {
|
1073 | requires: [ "ajax" ]
|
1074 | });
|
1075 | });
|
1076 | }
|
1077 |
|
1078 | (function(undefined) {
|
1079 | var Mock4Tpl = {
|
1080 | version: "0.0.1"
|
1081 | };
|
1082 | if (!this.Mock) module.exports = Mock4Tpl;
|
1083 | Mock.tpl = function(input, options, helpers, partials) {
|
1084 | return Mock4Tpl.mock(input, options, helpers, partials);
|
1085 | };
|
1086 | Mock.parse = function(input) {
|
1087 | return Handlebars.parse(input);
|
1088 | };
|
1089 | Mock4Tpl.mock = function(input, options, helpers, partials) {
|
1090 | helpers = helpers ? Util.extend({}, helpers, Handlebars.helpers) : Handlebars.helpers;
|
1091 | partials = partials ? Util.extend({}, partials, Handlebars.partials) : Handlebars.partials;
|
1092 | return Handle.gen(input, null, options, helpers, partials);
|
1093 | };
|
1094 | var Handle = {
|
1095 | debug: Mock4Tpl.debug || false,
|
1096 | extend: Util.extend
|
1097 | };
|
1098 | Handle.gen = function(node, context, options, helpers, partials) {
|
1099 | if (Util.isString(node)) {
|
1100 | var ast = Handlebars.parse(node);
|
1101 | options = Handle.parseOptions(node, options);
|
1102 | var data = Handle.gen(ast, context, options, helpers, partials);
|
1103 | return data;
|
1104 | }
|
1105 | context = context || [ {} ];
|
1106 | options = options || {};
|
1107 | if (this[node.type] === Util.noop) return;
|
1108 | options.__path = options.__path || [];
|
1109 | if (Mock4Tpl.debug || Handle.debug) {
|
1110 | console.log();
|
1111 | console.group("[" + node.type + "]", JSON.stringify(node));
|
1112 | console.log("[options]", options.__path.length, JSON.stringify(options));
|
1113 | }
|
1114 | var preLength = options.__path.length;
|
1115 | this[node.type](node, context, options, helpers, partials);
|
1116 | options.__path.splice(preLength);
|
1117 | if (Mock4Tpl.debug || Handle.debug) {
|
1118 | console.groupEnd();
|
1119 | }
|
1120 | return context[context.length - 1];
|
1121 | };
|
1122 | Handle.parseOptions = function(input, options) {
|
1123 | var rComment = /<!--\s*\n*Mock\s*\n*([\w\W]+?)\s*\n*-->/g;
|
1124 | var comments = input.match(rComment), ret = {}, i, ma, option;
|
1125 | for (i = 0; comments && i < comments.length; i++) {
|
1126 | rComment.lastIndex = 0;
|
1127 | ma = rComment.exec(comments[i]);
|
1128 | if (ma) {
|
1129 | option = new Function("return " + ma[1]);
|
1130 | option = option();
|
1131 | Util.extend(ret, option);
|
1132 | }
|
1133 | }
|
1134 | return Util.extend(ret, options);
|
1135 | };
|
1136 | Handle.val = function(name, options, context, def) {
|
1137 | if (name !== options.__path[options.__path.length - 1]) throw new Error(name + "!==" + options.__path);
|
1138 | if (Mock4Tpl.debug || Handle.debug) console.log("[options]", name, options.__path);
|
1139 | if (def !== undefined) def = Mock.mock(def);
|
1140 | if (options) {
|
1141 | var mocked = Mock.mock(options);
|
1142 | if (Util.isString(mocked)) return mocked;
|
1143 | if (name in mocked) {
|
1144 | return mocked[name];
|
1145 | }
|
1146 | }
|
1147 | if (Util.isArray(context[0])) return {};
|
1148 | return def !== undefined ? def : name || Random.word();
|
1149 | };
|
1150 | Handle.program = function(node, context, options, helpers, partials) {
|
1151 | for (var i = 0; i < node.statements.length; i++) {
|
1152 | this.gen(node.statements[i], context, options, helpers, partials);
|
1153 | }
|
1154 | };
|
1155 | Handle.mustache = function(node, context, options, helpers, partials) {
|
1156 | var i, currentContext = context[0], contextLength = context.length;
|
1157 | if (Util.type(currentContext) === "array") {
|
1158 | currentContext.push({});
|
1159 | currentContext = currentContext[currentContext.length - 1];
|
1160 | context.unshift(currentContext);
|
1161 | }
|
1162 | if (node.isHelper || helpers && helpers[node.id.string]) {
|
1163 | if (node.params.length === 0) {} else {
|
1164 | for (i = 0; i < node.params.length; i++) {
|
1165 | this.gen(node.params[i], context, options, helpers, partials);
|
1166 | }
|
1167 | }
|
1168 | if (node.hash) this.gen(node.hash, context, options, helpers, partials);
|
1169 | } else {
|
1170 | this.gen(node.id, context, options, helpers, partials);
|
1171 | }
|
1172 | if (context.length > contextLength) context.splice(0, context.length - contextLength);
|
1173 | };
|
1174 | Handle.block = function(node, context, options, helpers, partials) {
|
1175 | var parts = node.mustache.id.parts, i, len, cur, val, type, currentContext = context[0], contextLength = context.length;
|
1176 | if (node.inverse) {}
|
1177 | if (node.mustache.isHelper || helpers && helpers[node.mustache.id.string]) {
|
1178 | type = parts[0];
|
1179 | val = (Helpers[type] || Helpers.custom).apply(this, arguments);
|
1180 | currentContext = context[0];
|
1181 | } else {
|
1182 | for (i = 0; i < parts.length; i++) {
|
1183 | options.__path.push(parts[i]);
|
1184 | cur = parts[i];
|
1185 | val = this.val(cur, options, context, {});
|
1186 | currentContext[cur] = Util.isArray(val) && [] || val;
|
1187 | type = Util.type(currentContext[cur]);
|
1188 | if (type === "object" || type === "array") {
|
1189 | currentContext = currentContext[cur];
|
1190 | context.unshift(currentContext);
|
1191 | }
|
1192 | }
|
1193 | }
|
1194 | if (node.program) {
|
1195 | if (Util.type(currentContext) === "array") {
|
1196 | len = val.length || Random.integer(3, 7);
|
1197 | for (i = 0; i < len; i++) {
|
1198 | currentContext.push(typeof val[i] !== "undefined" ? val[i] : {});
|
1199 | options.__path.push("[]");
|
1200 | context.unshift(currentContext[currentContext.length - 1]);
|
1201 | this.gen(node.program, context, options, helpers, partials);
|
1202 | options.__path.pop();
|
1203 | context.shift();
|
1204 | }
|
1205 | } else this.gen(node.program, context, options, helpers, partials);
|
1206 | }
|
1207 | if (context.length > contextLength) context.splice(0, context.length - contextLength);
|
1208 | };
|
1209 | Handle.hash = function(node, context, options, helpers, partials) {
|
1210 | var pairs = node.pairs, pair, i, j;
|
1211 | for (i = 0; i < pairs.length; i++) {
|
1212 | pair = pairs[i];
|
1213 | for (j = 1; j < pair.length; j++) {
|
1214 | this.gen(pair[j], context, options, helpers, partials);
|
1215 | }
|
1216 | }
|
1217 | };
|
1218 | Handle.ID = function(node, context, options) {
|
1219 | var parts = node.parts, i, len, cur, prev, def, val, type, valType, preOptions, currentContext = context[node.depth], contextLength = context.length;
|
1220 | if (Util.isArray(currentContext)) currentContext = context[node.depth + 1];
|
1221 | if (!parts.length) {} else {
|
1222 | for (i = 0, len = parts.length; i < len; i++) {
|
1223 | options.__path.push(parts[i]);
|
1224 | cur = parts[i];
|
1225 | prev = parts[i - 1];
|
1226 | preOptions = options[prev];
|
1227 | def = i === len - 1 ? currentContext[cur] : {};
|
1228 | val = this.val(cur, options, context, def);
|
1229 | type = Util.type(currentContext[cur]);
|
1230 | valType = Util.type(val);
|
1231 | if (type === "undefined") {
|
1232 | if (i < len - 1 && valType !== "object" && valType !== "array") {
|
1233 | currentContext[cur] = {};
|
1234 | } else {
|
1235 | currentContext[cur] = Util.isArray(val) && [] || val;
|
1236 | }
|
1237 | } else {
|
1238 | if (i < len - 1 && type !== "object" && type !== "array") {
|
1239 | currentContext[cur] = Util.isArray(val) && [] || {};
|
1240 | }
|
1241 | }
|
1242 | type = Util.type(currentContext[cur]);
|
1243 | if (type === "object" || type === "array") {
|
1244 | currentContext = currentContext[cur];
|
1245 | context.unshift(currentContext);
|
1246 | }
|
1247 | }
|
1248 | }
|
1249 | if (context.length > contextLength) context.splice(0, context.length - contextLength);
|
1250 | };
|
1251 | Handle.partial = function(node, context, options, helpers, partials) {
|
1252 | var name = node.partialName.name, partial = partials && partials[name], contextLength = context.length;
|
1253 | if (partial) Handle.gen(partial, context, options, helpers, partials);
|
1254 | if (context.length > contextLength) context.splice(0, context.length - contextLength);
|
1255 | };
|
1256 | Handle.content = Util.noop;
|
1257 | Handle.PARTIAL_NAME = Util.noop;
|
1258 | Handle.DATA = Util.noop;
|
1259 | Handle.STRING = Util.noop;
|
1260 | Handle.INTEGER = Util.noop;
|
1261 | Handle.BOOLEAN = Util.noop;
|
1262 | Handle.comment = Util.noop;
|
1263 | var Helpers = {};
|
1264 | Helpers.each = function(node, context, options) {
|
1265 | var i, len, cur, val, parts, def, type, currentContext = context[0];
|
1266 | parts = node.mustache.params[0].parts;
|
1267 | for (i = 0, len = parts.length; i < len; i++) {
|
1268 | options.__path.push(parts[i]);
|
1269 | cur = parts[i];
|
1270 | def = i === len - 1 ? [] : {};
|
1271 | val = this.val(cur, options, context, def);
|
1272 | currentContext[cur] = Util.isArray(val) && [] || val;
|
1273 | type = Util.type(currentContext[cur]);
|
1274 | if (type === "object" || type === "array") {
|
1275 | currentContext = currentContext[cur];
|
1276 | context.unshift(currentContext);
|
1277 | }
|
1278 | }
|
1279 | return val;
|
1280 | };
|
1281 | Helpers["if"] = Helpers.unless = function(node, context, options) {
|
1282 | var params = node.mustache.params, i, j, cur, val, parts, def, type, currentContext = context[0];
|
1283 | for (i = 0; i < params.length; i++) {
|
1284 | parts = params[i].parts;
|
1285 | for (j = 0; j < parts.length; j++) {
|
1286 | if (i === 0) options.__path.push(parts[j]);
|
1287 | cur = parts[j];
|
1288 | def = j === parts.length - 1 ? "@BOOL(2,1,true)" : {};
|
1289 | val = this.val(cur, options, context, def);
|
1290 | if (j === parts.length - 1) {
|
1291 | val = val === "true" ? true : val === "false" ? false : val;
|
1292 | }
|
1293 | currentContext[cur] = Util.isArray(val) ? [] : val;
|
1294 | type = Util.type(currentContext[cur]);
|
1295 | if (type === "object" || type === "array") {
|
1296 | currentContext = currentContext[cur];
|
1297 | context.unshift(currentContext);
|
1298 | }
|
1299 | }
|
1300 | }
|
1301 | return val;
|
1302 | };
|
1303 | Helpers["with"] = function(node, context, options) {
|
1304 | var i, cur, val, parts, def, currentContext = context[0];
|
1305 | parts = node.mustache.params[0].parts;
|
1306 | for (i = 0; i < parts.length; i++) {
|
1307 | options.__path.push(parts[i]);
|
1308 | cur = parts[i];
|
1309 | def = {};
|
1310 | val = this.val(cur, options, context, def);
|
1311 | currentContext = currentContext[cur] = val;
|
1312 | context.unshift(currentContext);
|
1313 | }
|
1314 | return val;
|
1315 | };
|
1316 | Helpers.log = function() {};
|
1317 | Helpers.custom = function(node, context, options) {
|
1318 | var i, len, cur, val, parts, def, type, currentContext = context[0];
|
1319 | if (node.mustache.params.length === 0) {
|
1320 | return;
|
1321 | options.__path.push(node.mustache.id.string);
|
1322 | cur = node.mustache.id.string;
|
1323 | def = "@BOOL(2,1,true)";
|
1324 | val = this.val(cur, options, context, def);
|
1325 | currentContext[cur] = Util.isArray(val) && [] || val;
|
1326 | type = Util.type(currentContext[cur]);
|
1327 | if (type === "object" || type === "array") {
|
1328 | currentContext = currentContext[cur];
|
1329 | context.unshift(currentContext);
|
1330 | }
|
1331 | } else {
|
1332 | parts = node.mustache.params[0].parts;
|
1333 | for (i = 0, len = parts.length; i < len; i++) {
|
1334 | options.__path.push(parts[i]);
|
1335 | cur = parts[i];
|
1336 | def = i === len - 1 ? [] : {};
|
1337 | val = this.val(cur, options, context, def);
|
1338 | currentContext[cur] = Util.isArray(val) && [] || val;
|
1339 | type = Util.type(currentContext[cur]);
|
1340 | if (type === "object" || type === "array") {
|
1341 | currentContext = currentContext[cur];
|
1342 | context.unshift(currentContext);
|
1343 | }
|
1344 | }
|
1345 | }
|
1346 | return val;
|
1347 | };
|
1348 | }).call(this);
|
1349 |
|
1350 | (function(undefined) {
|
1351 | if (typeof KISSY === "undefined") return;
|
1352 | var Mock4XTpl = {
|
1353 | debug: false
|
1354 | };
|
1355 | var XTemplate;
|
1356 | KISSY.use("xtemplate", function(S, T) {
|
1357 | XTemplate = T;
|
1358 | });
|
1359 | if (!this.Mock) module.exports = Mock4XTpl;
|
1360 | Mock.xtpl = function(input, options, helpers, partials) {
|
1361 | return Mock4XTpl.mock(input, options, helpers, partials);
|
1362 | };
|
1363 | Mock.xparse = function(input) {
|
1364 | return XTemplate.compiler.parse(input);
|
1365 | };
|
1366 | Mock4XTpl.mock = function(input, options, helpers, partials) {
|
1367 | helpers = helpers ? Util.extend({}, helpers, XTemplate.RunTime.commands) : XTemplate.RunTime.commands;
|
1368 | partials = partials ? Util.extend({}, partials, XTemplate.RunTime.subTpls) : XTemplate.RunTime.subTpls;
|
1369 | return this.gen(input, null, options, helpers, partials, {});
|
1370 | };
|
1371 | Mock4XTpl.parse = function(input) {
|
1372 | return XTemplate.compiler.parse(input);
|
1373 | };
|
1374 | Mock4XTpl.gen = function(node, context, options, helpers, partials, other) {
|
1375 | if (typeof node === "string") {
|
1376 | if (Mock4XTpl.debug) {
|
1377 | console.log("[tpl ]\n", node);
|
1378 | }
|
1379 | var ast = this.parse(node);
|
1380 | options = this.parseOptions(node, options);
|
1381 | var data = this.gen(ast, context, options, helpers, partials, other);
|
1382 | return data;
|
1383 | }
|
1384 | context = context || [ {} ];
|
1385 | options = options || {};
|
1386 | node.type = node.type;
|
1387 | if (this[node.type] === Util.noop) return;
|
1388 | options.__path = options.__path || [];
|
1389 | if (Mock4XTpl.debug) {
|
1390 | console.log();
|
1391 | console.group("[" + node.type + "]", JSON.stringify(node));
|
1392 | console.log("[context]", "[before]", context.length, JSON.stringify(context));
|
1393 | console.log("[options]", "[before]", options.__path.length, JSON.stringify(options));
|
1394 | console.log("[other ]", "[before]", JSON.stringify(other));
|
1395 | }
|
1396 | var preLength = options.__path.length;
|
1397 | this[node.type](node, context, options, helpers, partials, other);
|
1398 | if (Mock4XTpl.debug) {
|
1399 | console.log("[__path ]", "[after ]", options.__path);
|
1400 | }
|
1401 | if (!other.hold || typeof other.hold === "function" && !other.hold(node, options, context)) {
|
1402 | options.__path.splice(preLength);
|
1403 | }
|
1404 | if (Mock4XTpl.debug) {
|
1405 | console.log("[context]", "[after ]", context.length, JSON.stringify(context));
|
1406 | console.groupEnd();
|
1407 | }
|
1408 | return context[context.length - 1];
|
1409 | };
|
1410 | Mock4XTpl.parseOptions = function(input, options) {
|
1411 | var rComment = /<!--\s*\n*Mock\s*\n*([\w\W]+?)\s*\n*-->/g;
|
1412 | var comments = input.match(rComment), ret = {}, i, ma, option;
|
1413 | for (i = 0; comments && i < comments.length; i++) {
|
1414 | rComment.lastIndex = 0;
|
1415 | ma = rComment.exec(comments[i]);
|
1416 | if (ma) {
|
1417 | option = new Function("return " + ma[1]);
|
1418 | option = option();
|
1419 | Util.extend(ret, option);
|
1420 | }
|
1421 | }
|
1422 | return Util.extend(ret, options);
|
1423 | };
|
1424 | Mock4XTpl.parseVal = function(expr, object) {
|
1425 | function queryArray(prop, context) {
|
1426 | if (typeof context === "object" && prop in context) return [ context[prop] ];
|
1427 | var ret = [];
|
1428 | for (var i = 0; i < context.length; i++) {
|
1429 | ret.push.apply(ret, query(prop, [ context[i] ]));
|
1430 | }
|
1431 | return ret;
|
1432 | }
|
1433 | function queryObject(prop, context) {
|
1434 | if (typeof context === "object" && prop in context) return [ context[prop] ];
|
1435 | var ret = [];
|
1436 | for (var key in context) {
|
1437 | ret.push.apply(ret, query(prop, [ context[key] ]));
|
1438 | }
|
1439 | return ret;
|
1440 | }
|
1441 | function query(prop, set) {
|
1442 | var ret = [];
|
1443 | for (var i = 0; i < set.length; i++) {
|
1444 | if (typeof set[i] !== "object") continue;
|
1445 | if (prop in set[i]) ret.push(set[i][prop]); else {
|
1446 | ret.push.apply(ret, Util.isArray(set[i]) ? queryArray(prop, set[i]) : queryObject(prop, set[i]));
|
1447 | }
|
1448 | }
|
1449 | return ret;
|
1450 | }
|
1451 | function parse(expr, context) {
|
1452 | var parts = typeof expr === "string" ? expr.split(".") : expr.slice(0), set = [ context ];
|
1453 | while (parts.length) {
|
1454 | set = query(parts.shift(), set);
|
1455 | }
|
1456 | return set;
|
1457 | }
|
1458 | return parse(expr, object);
|
1459 | };
|
1460 | Mock4XTpl.val = function(name, options, context, def) {
|
1461 | if (name !== options.__path[options.__path.length - 1]) throw new Error(name + "!==" + options.__path);
|
1462 | if (def !== undefined) def = Mock.mock(def);
|
1463 | if (options) {
|
1464 | var mocked = Mock.mock(options);
|
1465 | if (Util.isString(mocked)) return mocked;
|
1466 | var ret = Mock4XTpl.parseVal(options.__path, mocked);
|
1467 | if (ret.length > 0) return ret[0];
|
1468 | if (name in mocked) {
|
1469 | return mocked[name];
|
1470 | }
|
1471 | }
|
1472 | if (Util.isArray(context[0])) return {};
|
1473 | return def !== undefined ? def : name;
|
1474 | };
|
1475 | Mock4XTpl.program = function(node, context, options, helpers, partials, other) {
|
1476 | for (var i = 0; i < node.statements.length; i++) {
|
1477 | this.gen(node.statements[i], context, options, helpers, partials, other);
|
1478 | }
|
1479 | for (var j = 0; node.inverse && j < node.inverse.length; j++) {
|
1480 | this.gen(node.inverse[j], context, options, helpers, partials, other);
|
1481 | }
|
1482 | };
|
1483 | Mock4XTpl.block = function(node, context, options, helpers, partials, other) {
|
1484 | var contextLength = context.length;
|
1485 | this.gen(node.tpl, context, options, helpers, partials, Util.extend({}, other, {
|
1486 | def: {},
|
1487 | hold: true
|
1488 | }));
|
1489 | var currentContext = context[0], mocked, i, len;
|
1490 | if (Util.type(currentContext) === "array") {
|
1491 | mocked = this.val(options.__path[options.__path.length - 1], options, context);
|
1492 | len = mocked && mocked.length || Random.integer(3, 7);
|
1493 | for (i = 0; i < len; i++) {
|
1494 | currentContext.push(mocked && mocked[i] !== undefined ? mocked[i] : {});
|
1495 | options.__path.push(i);
|
1496 | context.unshift(currentContext[currentContext.length - 1]);
|
1497 | this.gen(node.program, context, options, helpers, partials, other);
|
1498 | options.__path.pop();
|
1499 | context.shift();
|
1500 | }
|
1501 | } else this.gen(node.program, context, options, helpers, partials, other);
|
1502 | if (!other.hold || typeof other.hold === "function" && !other.hold(node, options, context)) {
|
1503 | context.splice(0, context.length - contextLength);
|
1504 | }
|
1505 | };
|
1506 | Mock4XTpl.tpl = function(node, context, options, helpers, partials, other) {
|
1507 | if (node.params && node.params.length) {
|
1508 | other = Util.extend({}, other, {
|
1509 | def: {
|
1510 | each: [],
|
1511 | "if": "@BOOL(2,1,true)",
|
1512 | unless: "@BOOL(2,1,false)",
|
1513 | "with": {}
|
1514 | }[node.path.string],
|
1515 | hold: {
|
1516 | each: true,
|
1517 | "if": function(_, __, ___, name, value) {
|
1518 | return typeof value === "object";
|
1519 | },
|
1520 | unless: function(_, __, ___, name, value) {
|
1521 | return typeof value === "object";
|
1522 | },
|
1523 | "with": true,
|
1524 | include: false
|
1525 | }[node.path.string]
|
1526 | });
|
1527 | for (var i = 0, input; i < node.params.length; i++) {
|
1528 | if (node.path.string === "include") {
|
1529 | input = partials && partials[node.params[i].value];
|
1530 | } else input = node.params[i];
|
1531 | if (input) this.gen(input, context, options, helpers, partials, other);
|
1532 | }
|
1533 | if (node.hash) {
|
1534 | this.gen(node.hash, context, options, helpers, partials, other);
|
1535 | }
|
1536 | } else {
|
1537 | this.gen(node.path, context, options, helpers, partials, other);
|
1538 | }
|
1539 | };
|
1540 | Mock4XTpl.tplExpression = function(node, context, options, helpers, partials, other) {
|
1541 | this.gen(node.expression, context, options, helpers, partials, other);
|
1542 | };
|
1543 | Mock4XTpl.content = Util.noop;
|
1544 | Mock4XTpl.unaryExpression = Util.noop;
|
1545 | Mock4XTpl.multiplicativeExpression = Mock4XTpl.additiveExpression = function(node, context, options, helpers, partials, other) {
|
1546 | this.gen(node.op1, context, options, helpers, partials, Util.extend({}, other, {
|
1547 | def: function() {
|
1548 | return node.op2.type === "number" ? node.op2.value.indexOf(".") > -1 ? Random.float(-Math.pow(10, 10), Math.pow(10, 10), 1, Math.pow(10, 6)) : Random.integer() : undefined;
|
1549 | }()
|
1550 | }));
|
1551 | this.gen(node.op2, context, options, helpers, partials, Util.extend({}, other, {
|
1552 | def: function() {
|
1553 | return node.op1.type === "number" ? node.op1.value.indexOf(".") > -1 ? Random.float(-Math.pow(10, 10), Math.pow(10, 10), 1, Math.pow(10, 6)) : Random.integer() : undefined;
|
1554 | }()
|
1555 | }));
|
1556 | };
|
1557 | Mock4XTpl.relationalExpression = function(node, context, options, helpers, partials, other) {
|
1558 | this.gen(node.op1, context, options, helpers, partials, other);
|
1559 | this.gen(node.op2, context, options, helpers, partials, other);
|
1560 | };
|
1561 | Mock4XTpl.equalityExpression = Util.noop;
|
1562 | Mock4XTpl.conditionalAndExpression = Util.noop;
|
1563 | Mock4XTpl.conditionalOrExpression = Util.noop;
|
1564 | Mock4XTpl.string = Util.noop;
|
1565 | Mock4XTpl.number = Util.noop;
|
1566 | Mock4XTpl.boolean = Util.noop;
|
1567 | Mock4XTpl.hash = function(node, context, options, helpers, partials, other) {
|
1568 | var pairs = node.value, key;
|
1569 | for (key in pairs) {
|
1570 | this.gen(pairs[key], context, options, helpers, partials, other);
|
1571 | }
|
1572 | };
|
1573 | Mock4XTpl.id = function(node, context, options, helpers, partials, other) {
|
1574 | var contextLength = context.length;
|
1575 | var parts = node.parts, currentContext = context[node.depth], i, len, cur, def, val;
|
1576 | function fix(currentContext, index, length, name, val) {
|
1577 | var type = Util.type(currentContext[name]), valType = Util.type(val);
|
1578 | val = val === "true" ? true : val === "false" ? false : val;
|
1579 | if (type === "undefined") {
|
1580 | if (index < length - 1 && !Util.isObjectOrArray(val)) {
|
1581 | currentContext[name] = {};
|
1582 | } else {
|
1583 | currentContext[name] = Util.isArray(val) && [] || val;
|
1584 | }
|
1585 | } else {
|
1586 | if (index < length - 1 && type !== "object" && type !== "array") {
|
1587 | currentContext[name] = Util.isArray(val) && [] || {};
|
1588 | } else {
|
1589 | if (type !== "object" && type !== "array" && valType !== "object" && valType !== "array") {
|
1590 | currentContext[name] = val;
|
1591 | }
|
1592 | }
|
1593 | }
|
1594 | return currentContext[name];
|
1595 | }
|
1596 | if (Util.isArray(currentContext)) currentContext = context[node.depth + 1];
|
1597 | for (i = 0, len = parts.length; i < len; i++) {
|
1598 | if (i === 0 && parts[i] === "this") continue;
|
1599 | if (/^(xindex|xcount|xkey)$/.test(parts[i])) continue;
|
1600 | if (i === 0 && len === 1 && parts[i] in helpers) continue;
|
1601 | options.__path.push(parts[i]);
|
1602 | cur = parts[i];
|
1603 | def = i === len - 1 ? other.def !== undefined ? other.def : context[0][cur] : {};
|
1604 | val = this.val(cur, options, context, def);
|
1605 | if (Mock4XTpl.debug) {
|
1606 | console.log("[def ]", JSON.stringify(def));
|
1607 | console.log("[val ]", JSON.stringify(val));
|
1608 | }
|
1609 | val = fix(currentContext, i, len, cur, val);
|
1610 | if (Util.isObjectOrArray(currentContext[cur])) {
|
1611 | context.unshift(currentContext = currentContext[cur]);
|
1612 | }
|
1613 | }
|
1614 | if (!other.hold || typeof other.hold === "function" && !other.hold(node, options, context, cur, val)) {
|
1615 | context.splice(0, context.length - contextLength);
|
1616 | }
|
1617 | };
|
1618 | }).call(this);
|
1619 | }).call(this); |
\ | No newline at end of file |