awestruct 0.5.6 → 0.5.7.RC1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,126 @@
1
+ require 'awestruct/page'
2
+ require 'json'
3
+ require 'rack'
4
+
5
+ module Awestruct
6
+ module Rack
7
+ class Debug
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ engine = ::Awestruct::Engine.instance
14
+
15
+ debug = false
16
+
17
+ query = ::Rack::Utils.parse_query(env['QUERY_STRING'])
18
+ path = env['REQUEST_PATH']
19
+ path = path + 'index.html' if path.end_with? '/'
20
+
21
+ page = engine.site.pages_by_output_path[path]
22
+
23
+ debug = true if !page.nil? and query.include? 'debug'
24
+
25
+ if debug
26
+ debug_exp = []
27
+ debug_exp = query['debug'].split('.').reverse unless query['debug'].nil?
28
+
29
+ if debug_exp.size == 0
30
+ html = IO.read(File.join(File.dirname(__FILE__), 'trace.html'))
31
+ return [200,
32
+ {'Content-Type'.freeze => 'text/html', 'Content-Length'.freeze => html.size.to_s},
33
+ [html] ]
34
+ else
35
+ json = ''
36
+ begin
37
+ json = dump(introspect(page, {}, debug_exp))
38
+ rescue Exception => e
39
+ json += e.message
40
+ end
41
+
42
+ return [200,
43
+ {'Content-Type'.freeze => 'application/json', 'Content-Length'.freeze => json.size.to_s},
44
+ [json] ]
45
+ end
46
+ else
47
+ source_call = @app.call(env)
48
+ if source_call[1]['Content-Type'].eql? 'text/html'
49
+ html = source_call[2][0]
50
+ html += %Q(
51
+ <script>
52
+ document.addEventListener("keypress", function(event) {
53
+ if(event.shiftKey && (event.key === '?' || event.keyCode === 63 || event.charCode === 63)) {
54
+ window.open(window.location.pathname + '?debug', '_blank')
55
+ }
56
+ });
57
+ </script>
58
+ )
59
+ source_call[1]['Content-Length'] = html.size.to_s
60
+ source_call[2][0] = html
61
+ end
62
+ source_call
63
+ end
64
+ end
65
+
66
+ def introspect(source, target, exp, depth = 0)
67
+ return target if source.nil?
68
+
69
+ exp_all_curr = exp.clone
70
+ exp_curr = exp_all_curr.pop
71
+
72
+ if source.is_a? Array
73
+ if !exp_curr.nil? and exp_curr[/^-?\d+$/]
74
+ target_arr = []
75
+ (0...source.size).each {|x| target_arr[x] = {}}
76
+ target_arr[exp_curr.to_i] = introspect(source[exp_curr.to_i], {}, exp_all_curr, depth+1)
77
+ return target_arr
78
+ else
79
+ target_arr = []
80
+ source.each{ |var| target_arr << introspect(var, {}, exp, depth+1)}
81
+ return target_arr
82
+ end
83
+ end
84
+
85
+ return target if exp_curr.nil?
86
+
87
+ data = nil
88
+
89
+ if source.is_a? Awestruct::Page
90
+ data = source.original_entries
91
+ elsif source.is_a? Hash
92
+ data = source
93
+ elsif source.is_a? OpenStruct
94
+ data = source.to_h
95
+ end
96
+
97
+ return source.to_s if data.nil?
98
+
99
+ data.each do |key, value|
100
+ if key.to_s == exp_curr or exp_curr == '*'
101
+ if value.is_a? Hash or value.is_a? OpenStruct or value.is_a? Awestruct::Page
102
+ target[key] = introspect(value, {}, exp_all_curr, depth+1)
103
+ elsif value.is_a? Array
104
+ target[key] = introspect(value, {}, exp_all_curr, depth+1)
105
+ else
106
+ target[key] = value
107
+ end
108
+ elsif exp_curr[/^-?\d+$/]
109
+ if value.is_a? Array
110
+ target_arr = []
111
+ target_arr << introspect(value[exp_curr.to_i], {}, exp_all_curr, depth+1)
112
+ target[key] = target_arr
113
+ end
114
+ end
115
+
116
+ end
117
+ target
118
+ end
119
+
120
+ def dump(value)
121
+ value = value.to_h if value.is_a? OpenStruct
122
+ JSON.pretty_generate(value)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -14,16 +14,16 @@ module Awestruct
14
14
 
15
15
  req_path = env['REQUEST_PATH']
16
16
  path = req_path
17
- path = req_path + "index.html" if req_path.end_with? '/'
17
+ path = req_path + 'index.html' if req_path.end_with? '/'
18
18
 
19
19
  page = engine.site.pages_by_output_path[path]
20
20
  if page.nil? and !req_path.end_with? '/'
21
- path = req_path + "/index.html"
21
+ path = req_path + '/index.html'
22
22
  page = engine.site.pages_by_output_path[path]
23
23
  end
24
24
 
25
- if !page.nil?
26
- generate_path = File.join( engine.site.config.output_dir, page.output_path )
25
+ unless page.nil?
26
+ generate_path = File.join(engine.site.config.output_dir, page.output_path)
27
27
 
28
28
  generate = true if page.stale_output? generate_path
29
29
  generate = true if path.end_with? '.html'
@@ -0,0 +1,881 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Trace</title>
6
+ <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js">
7
+
8
+
9
+ </script>
10
+ </head>
11
+ <body>
12
+ <div><pre id="content"></pre></div>
13
+ </body>
14
+
15
+ <script>
16
+
17
+
18
+
19
+ /*
20
+ Copyright (c) 2009 James Padolsey. All rights reserved.
21
+
22
+ Redistribution and use in source and binary forms, with or without
23
+ modification, are permitted provided that the following conditions
24
+ are met:
25
+
26
+ 1. Redistributions of source code must retain the above copyright
27
+ notice, this list of conditions and the following disclaimer.
28
+
29
+ 2. Redistributions in binary form must reproduce the above copyright
30
+ notice, this list of conditions and the following disclaimer in the
31
+ documentation and/or other materials provided with the distribution.
32
+
33
+ THIS SOFTWARE IS PROVIDED BY James Padolsey ``AS IS'' AND
34
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36
+ ARE DISCLAIMED. IN NO EVENT SHALL James Padolsey OR CONTRIBUTORS BE LIABLE
37
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43
+ SUCH DAMAGE.
44
+
45
+ The views and conclusions contained in the software and documentation are
46
+ those of the authors and should not be interpreted as representing official
47
+ policies, either expressed or implied, of James Padolsey.
48
+
49
+ AUTHOR James Padolsey (http://james.padolsey.com)
50
+ VERSION 1.03.0
51
+ UPDATED 29-10-2011
52
+ CONTRIBUTORS
53
+ David Waller
54
+ Benjamin Drucker
55
+
56
+ */
57
+
58
+ var prettyPrint = (function() {
59
+
60
+ /* These "util" functions are not part of the core
61
+ functionality but are all necessary - mostly DOM helpers */
62
+
63
+ var util = {
64
+
65
+ el: function(type, attrs) {
66
+
67
+ /* Create new element */
68
+ var el = document.createElement(type), attr;
69
+
70
+ /*Copy to single object */
71
+ attrs = util.merge({}, attrs);
72
+
73
+ /* Add attributes to el */
74
+ if (attrs && attrs.style) {
75
+ var styles = attrs.style;
76
+ util.applyCSS(el, attrs.style);
77
+ delete attrs.style;
78
+ }
79
+ for (attr in attrs) {
80
+ if (attrs.hasOwnProperty(attr)) {
81
+ el[attr] = attrs[attr];
82
+ }
83
+ }
84
+
85
+ return el;
86
+
87
+ },
88
+
89
+ applyCSS: function(el, styles) {
90
+ /* Applies CSS to a single element */
91
+ for (var prop in styles) {
92
+ if (styles.hasOwnProperty(prop)) {
93
+ try {
94
+ /* Yes, IE6 SUCKS! */
95
+ el.style[prop] = styles[prop];
96
+ } catch (e) {
97
+ }
98
+ }
99
+ }
100
+ },
101
+
102
+ txt: function(t) {
103
+ /* Create text node */
104
+ return document.createTextNode(t);
105
+ },
106
+
107
+ row: function(cells, type, cellType) {
108
+
109
+ /* Creates new <tr> */
110
+ cellType = cellType || 'td';
111
+
112
+ /* colSpan is calculated by length of null items in array */
113
+ var colSpan = util.count(cells, null) + 1,
114
+ tr = util.el('tr'), td,
115
+ attrs = {
116
+ style: util.getStyles(cellType, type),
117
+ colSpan: colSpan,
118
+ onmouseover: function() {
119
+ var tds = this.parentNode.childNodes;
120
+ util.forEach(tds, function(cell) {
121
+ if (cell.nodeName.toLowerCase() !== 'td') {
122
+ return;
123
+ }
124
+ util.applyCSS(cell, util.getStyles('td_hover', type));
125
+ });
126
+ },
127
+ onmouseout: function() {
128
+ var tds = this.parentNode.childNodes;
129
+ util.forEach(tds, function(cell) {
130
+ if (cell.nodeName.toLowerCase() !== 'td') {
131
+ return;
132
+ }
133
+ util.applyCSS(cell, util.getStyles('td', type));
134
+ });
135
+ }
136
+ };
137
+
138
+ util.forEach(cells, function(cell) {
139
+
140
+ if (cell === null) {
141
+ return;
142
+ }
143
+ /* Default cell type is <td> */
144
+ td = util.el(cellType, attrs);
145
+
146
+ if (cell.nodeType) {
147
+ /* IsDomElement */
148
+ td.appendChild(cell);
149
+ } else {
150
+ /* IsString */
151
+ td.innerHTML = util.shorten(cell.toString());
152
+ //td.innerHTML = cell.toString();
153
+ }
154
+
155
+ tr.appendChild(td);
156
+ });
157
+
158
+ return tr;
159
+ },
160
+
161
+ hRow: function(cells, type) {
162
+ /* Return new <th> */
163
+ return util.row(cells, type, 'th');
164
+ },
165
+
166
+ table: function(headings, type) {
167
+
168
+ headings = headings || [];
169
+
170
+ /* Creates new table: */
171
+ var attrs = {
172
+ thead: {
173
+ style: util.getStyles('thead', type)
174
+ },
175
+ tbody: {
176
+ style: util.getStyles('tbody', type)
177
+ },
178
+ table: {
179
+ style: util.getStyles('table', type)
180
+ }
181
+ },
182
+ tbl = util.el('table', attrs.table),
183
+ thead = util.el('thead', attrs.thead),
184
+ tbody = util.el('tbody', attrs.tbody);
185
+
186
+ if (headings.length) {
187
+ tbl.appendChild(thead);
188
+ thead.appendChild(util.hRow(headings, type));
189
+ }
190
+ tbl.appendChild(tbody);
191
+
192
+ return {
193
+ /* Facade for dealing with table/tbody
194
+ Actual table node is this.node: */
195
+ node: tbl,
196
+ tbody: tbody,
197
+ thead: thead,
198
+ appendChild: function(node) {
199
+ this.tbody.appendChild(node);
200
+ },
201
+ addRow: function(cells, _type, cellType) {
202
+ this.appendChild(util.row.call(util, cells, (_type || type), cellType));
203
+ return this;
204
+ }
205
+ };
206
+ },
207
+
208
+ shorten: function(str) {
209
+ var max = 40;
210
+ str = str.replace(/^\s\s*|\s\s*$|\n/g, '');
211
+ return str
212
+ //return str.length > max ? (str.substring(0, max-1) + '...') : str;
213
+ },
214
+
215
+ htmlentities: function(str) {
216
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
217
+ },
218
+
219
+ merge: function(target, source) {
220
+
221
+ /* Merges two (or more) objects,
222
+ giving the last one precedence */
223
+
224
+ if (typeof target !== 'object') {
225
+ target = {};
226
+ }
227
+
228
+ for (var property in source) {
229
+
230
+ if (source.hasOwnProperty(property)) {
231
+
232
+ var sourceProperty = source[property];
233
+
234
+ if (typeof sourceProperty === 'object') {
235
+ target[property] = util.merge(target[property], sourceProperty);
236
+ continue;
237
+ }
238
+
239
+ target[property] = sourceProperty;
240
+
241
+ }
242
+
243
+ }
244
+
245
+ for (var a = 2, l = arguments.length; a < l; a++) {
246
+ util.merge(target, arguments[a]);
247
+ }
248
+
249
+ return target;
250
+ },
251
+
252
+ count: function(arr, item) {
253
+ var count = 0;
254
+ for (var i = 0, l = arr.length; i < l; i++) {
255
+ if (arr[i] === item) {
256
+ count++;
257
+ }
258
+ }
259
+ return count;
260
+ },
261
+
262
+ thead: function(tbl) {
263
+ return tbl.getElementsByTagName('thead')[0];
264
+ },
265
+
266
+ forEach: function(arr, max, fn) {
267
+
268
+ if (!fn) {
269
+ fn = max;
270
+ }
271
+
272
+ /* Helper: iteration */
273
+ var len = arr.length,
274
+ index = -1;
275
+
276
+ while (++index < len) {
277
+ if (fn(arr[index], index, arr) === false) {
278
+ break;
279
+ }
280
+ }
281
+
282
+ return true;
283
+ },
284
+
285
+ type: function(v) {
286
+ try {
287
+ /* Returns type, e.g. "string", "number", "array" etc.
288
+ Note, this is only used for precise typing. */
289
+ if (v === null) {
290
+ return 'null';
291
+ }
292
+ if (v === undefined) {
293
+ return 'undefined';
294
+ }
295
+ var oType = Object.prototype.toString.call(v).match(/\s(.+?)\]/)[1].toLowerCase();
296
+ if (v.nodeType) {
297
+ if (v.nodeType === 1) {
298
+ return 'domelement';
299
+ }
300
+ return 'domnode';
301
+ }
302
+ if (/^(string|number|array|regexp|function|date|boolean)$/.test(oType)) {
303
+ return oType;
304
+ }
305
+ if (typeof v === 'object') {
306
+ return v.jquery && typeof v.jquery === 'string' ? 'jquery' : 'object';
307
+ }
308
+ if (v === window || v === document) {
309
+ return 'object';
310
+ }
311
+ return 'default';
312
+ } catch (e) {
313
+ return 'default';
314
+ }
315
+ },
316
+
317
+ within: function(ref) {
318
+ /* Check existence of a val within an object
319
+ RETURNS KEY */
320
+ return {
321
+ is: function(o) {
322
+ for (var i in ref) {
323
+ if (ref[i] === o) {
324
+ return i;
325
+ }
326
+ }
327
+ return '';
328
+ }
329
+ };
330
+ },
331
+
332
+ common: {
333
+ circRef: function(obj, key, settings) {
334
+ return util.expander(
335
+ '[POINTS BACK TO <strong>' + (key) + '</strong>]',
336
+ 'Click to show this item anyway',
337
+ function() {
338
+ this.parentNode.appendChild(prettyPrintThis(obj, {maxDepth: 1}));
339
+ }
340
+ );
341
+ },
342
+ depthReached: function(obj, settings) {
343
+ return util.expander(
344
+ '[DEPTH REACHED]',
345
+ 'Click to show this item anyway',
346
+ function() {
347
+ try {
348
+ this.parentNode.appendChild(prettyPrintThis(obj, {maxDepth: 1}));
349
+ } catch (e) {
350
+ this.parentNode.appendChild(
351
+ util.table(['ERROR OCCURED DURING OBJECT RETRIEVAL'], 'error').addRow([e.message]).node
352
+ );
353
+ }
354
+ }
355
+ );
356
+ }
357
+ },
358
+
359
+ getStyles: function(el, type) {
360
+ type = prettyPrintThis.settings.styles[type] || {};
361
+ return util.merge(
362
+ {}, prettyPrintThis.settings.styles['default'][el], type[el]
363
+ );
364
+ },
365
+
366
+ expander: function(text, title, clickFn) {
367
+ return util.el('a', {
368
+ innerHTML: util.shorten(text) + ' <b style="visibility:hidden;">[+]</b>',
369
+ title: title,
370
+ onmouseover: function() {
371
+ this.getElementsByTagName('b')[0].style.visibility = 'visible';
372
+ },
373
+ onmouseout: function() {
374
+ this.getElementsByTagName('b')[0].style.visibility = 'hidden';
375
+ },
376
+ onclick: function() {
377
+ this.style.display = 'none';
378
+ clickFn.call(this);
379
+ return false;
380
+ },
381
+ style: {
382
+ cursor: 'pointer'
383
+ }
384
+ });
385
+ },
386
+
387
+ stringify: function(obj) {
388
+
389
+ /* Bit of an ugly duckling!
390
+ - This fn returns an ATTEMPT at converting an object/array/anyType
391
+ into a string, kinda like a JSON-deParser
392
+ - This is used for when |settings.expanded === false| */
393
+
394
+ var type = util.type(obj),
395
+ str, first = true;
396
+ if (type === 'array') {
397
+ str = '[';
398
+ util.forEach(obj, function(item, i) {
399
+ str += (i === 0 ? '' : ', ') + util.stringify(item);
400
+ });
401
+ return str + ']';
402
+ }
403
+ if (typeof obj === 'object') {
404
+ str = '{';
405
+ for (var i in obj) {
406
+ if (obj.hasOwnProperty(i)) {
407
+ str += (first ? '' : ', ') + i + ':' + util.stringify(obj[i]);
408
+ first = false;
409
+ }
410
+ }
411
+ return str + '}';
412
+ }
413
+ if (type === 'regexp') {
414
+ return '/' + obj.source + '/';
415
+ }
416
+ if (type === 'string') {
417
+ return '"' + obj.replace(/"/g, '\\"') + '"';
418
+ }
419
+ return obj.toString();
420
+ },
421
+
422
+ headerGradient: (function() {
423
+
424
+ var canvas = document.createElement('canvas');
425
+ if (!canvas.getContext) {
426
+ return '';
427
+ }
428
+ var cx = canvas.getContext('2d');
429
+ canvas.height = 30;
430
+ canvas.width = 1;
431
+
432
+ var linearGrad = cx.createLinearGradient(0, 0, 0, 30);
433
+ linearGrad.addColorStop(0, 'rgba(0,0,0,0)');
434
+ linearGrad.addColorStop(1, 'rgba(0,0,0,0.25)');
435
+
436
+ cx.fillStyle = linearGrad;
437
+ cx.fillRect(0, 0, 1, 30);
438
+
439
+ var dataURL = canvas.toDataURL && canvas.toDataURL();
440
+ return 'url(' + (dataURL || '') + ')';
441
+
442
+ })()
443
+
444
+ };
445
+
446
+ // Main..
447
+ var prettyPrintThis = function(obj, options) {
448
+
449
+ /*
450
+ * obj :: Object to be printed
451
+ * options :: Options (merged with config)
452
+ */
453
+
454
+ options = options || {};
455
+
456
+ var settings = util.merge({}, prettyPrintThis.config, options),
457
+ container = util.el('div'),
458
+ config = prettyPrintThis.config,
459
+ currentDepth = 0,
460
+ stack = {},
461
+ hasRunOnce = false;
462
+
463
+ var last_object_depth = 0;
464
+ var obj_stack = new Array()
465
+
466
+ /* Expose per-call settings.
467
+ Note: "config" is overwritten (where necessary) by options/"settings"
468
+ So, if you need to access/change *DEFAULT* settings then go via ".config" */
469
+ prettyPrintThis.settings = settings;
470
+
471
+ var typeDealer = {
472
+ string: function(item) {
473
+ return util.txt('"' + util.shorten(item.replace(/"/g, '\\"')) + '"');
474
+ },
475
+ number: function(item) {
476
+ return util.txt(item);
477
+ },
478
+ regexp: function(item) {
479
+
480
+ var miniTable = util.table(['RegExp', null], 'regexp');
481
+ var flags = util.table();
482
+ var span = util.expander(
483
+ '/' + item.source + '/',
484
+ 'Click to show more',
485
+ function() {
486
+ this.parentNode.appendChild(miniTable.node);
487
+ }
488
+ );
489
+
490
+ flags
491
+ .addRow(['g', item.global])
492
+ .addRow(['i', item.ignoreCase])
493
+ .addRow(['m', item.multiline]);
494
+
495
+ miniTable
496
+ .addRow(['source', '/' + item.source + '/'])
497
+ .addRow(['flags', flags.node])
498
+ .addRow(['lastIndex', item.lastIndex]);
499
+
500
+ return settings.expanded ? miniTable.node : span;
501
+ },
502
+ domelement: function(element, depth) {
503
+
504
+ var miniTable = util.table(['DOMElement', null], 'domelement'),
505
+ props = ['id', 'className', 'innerHTML', 'src', 'href'], elname = element.nodeName || '';
506
+
507
+ miniTable.addRow(['tag', '&lt;' + elname.toLowerCase() + '&gt;']);
508
+
509
+ util.forEach(props, function(prop) {
510
+ if (element[prop]) {
511
+ miniTable.addRow([prop, util.htmlentities(element[prop])]);
512
+ }
513
+ });
514
+
515
+ return settings.expanded ? miniTable.node : util.expander(
516
+ 'DOMElement (' + elname.toLowerCase() + ')',
517
+ 'Click to show more',
518
+ function() {
519
+ this.parentNode.appendChild(miniTable.node);
520
+ }
521
+ );
522
+ },
523
+ domnode: function(node) {
524
+
525
+ /* Deals with all DOMNodes that aren't elements (nodeType !== 1) */
526
+ var miniTable = util.table(['DOMNode', null], 'domelement'),
527
+ data = util.htmlentities((node.data || 'UNDEFINED').replace(/\n/g, '\\n'));
528
+ miniTable
529
+ .addRow(['nodeType', node.nodeType + ' (' + node.nodeName + ')'])
530
+ .addRow(['data', data]);
531
+
532
+ return settings.expanded ? miniTable.node : util.expander(
533
+ 'DOMNode',
534
+ 'Click to show more',
535
+ function() {
536
+ this.parentNode.appendChild(miniTable.node);
537
+ }
538
+ );
539
+ },
540
+ jquery: function(obj, depth, key) {
541
+ return typeDealer['array'](obj, depth, key, true);
542
+ },
543
+ object: function(obj, depth, key) {
544
+ obj_stack.push(key);
545
+ console.log("object push " + key)
546
+
547
+ var get_stack_ref = function() {
548
+ return obj_stack.filter(function(obj){ return typeof obj != 'undefined'}).join('.') + ".*";
549
+ }
550
+
551
+ /* Checking depth + circular refs */
552
+ /* Note, check for circular refs before depth; just makes more sense */
553
+ var stackKey = util.within(stack).is(obj);
554
+ if (stackKey) {
555
+ return util.common.circRef(obj, stackKey, settings);
556
+ }
557
+ stack[key || 'TOP'] = obj;
558
+ if (depth === settings.maxDepth) {
559
+ return util.common.depthReached(obj, settings);
560
+ }
561
+
562
+ var table = util.table(['Object', null], 'object'),
563
+ isEmpty = true;
564
+
565
+ for (var i in obj) {
566
+ if (!obj.hasOwnProperty || obj.hasOwnProperty(i)) {
567
+ var item = obj[i],
568
+ type = util.type(item);
569
+ isEmpty = false;
570
+ try {
571
+ table.addRow([i, typeDealer[type](item, depth + 1, i)], type);
572
+ } catch (e) {
573
+ /* Security errors are thrown on certain Window/DOM properties */
574
+ if (window.console && window.console.log) {
575
+ console.log(e.message);
576
+ }
577
+ }
578
+ }
579
+ }
580
+
581
+ if (isEmpty) {
582
+ var curr_stack = get_stack_ref();
583
+ console.log(curr_stack);
584
+ //table.addRow(['<small>[.. more ' + tmp_stack + ']</small>']);
585
+ table.addRow([
586
+ util.el('a', {
587
+ innerHTML: "more ..",
588
+ title: curr_stack,
589
+ onclick: function() {
590
+ return prettyPrintThis.settings.more_callback(curr_stack);
591
+ },
592
+ style: {
593
+ cursor: 'pointer'
594
+ }
595
+ })
596
+ ])
597
+
598
+ } else {
599
+ table.thead.appendChild(
600
+ util.hRow(['key', 'value'], 'colHeader')
601
+ );
602
+ }
603
+
604
+ var ret = (settings.expanded || hasRunOnce) ? table.node : util.expander(
605
+ util.stringify(obj),
606
+ 'Click to show more',
607
+ function() {
608
+ this.parentNode.appendChild(table.node);
609
+ }
610
+ );
611
+
612
+ hasRunOnce = true;
613
+
614
+ obj_stack.pop();
615
+ console.log("object pop " + key)
616
+
617
+ return ret;
618
+
619
+ },
620
+ array: function(arr, depth, key, jquery) {
621
+ obj_stack.push(key)
622
+ console.log("array push " + key)
623
+
624
+ /* Checking depth + circular refs */
625
+ /* Note, check for circular refs before depth; just makes more sense */
626
+ var stackKey = util.within(stack).is(arr);
627
+ if (stackKey) {
628
+ return util.common.circRef(arr, stackKey);
629
+ }
630
+ stack[key || 'TOP'] = arr;
631
+ if (depth === settings.maxDepth) {
632
+ return util.common.depthReached(arr);
633
+ }
634
+
635
+ /* Accepts a table and modifies it */
636
+ var me = jquery ? 'jQuery' : 'Array', table = util.table([me + '(' + arr.length + ')', null], jquery ? 'jquery' : me.toLowerCase()),
637
+ isEmpty = true,
638
+ count = 0;
639
+
640
+ if (jquery) {
641
+ table.addRow(['selector', arr.selector]);
642
+ }
643
+
644
+ util.forEach(arr, function(item, i) {
645
+ //obj_stack.push(i)
646
+ //console.log("index push " + i)
647
+
648
+ if (settings.maxArray >= 0 && ++count > settings.maxArray) {
649
+ table.addRow([
650
+ i + '..' + (arr.length - 1),
651
+ typeDealer[util.type(item)]('...', depth + 1, i)
652
+ ]);
653
+ return false;
654
+ }
655
+ isEmpty = false;
656
+ table.addRow([i, typeDealer[util.type(item)](item, depth + 1, i)]);
657
+ //obj_stack.pop();
658
+ //console.log("index pop " + i)
659
+ });
660
+
661
+ if (!jquery) {
662
+ if (isEmpty) {
663
+ table.addRow(['<small>[empty]</small>']);
664
+ } else {
665
+ table.thead.appendChild(util.hRow(['index', 'value'], 'colHeader'));
666
+ }
667
+ }
668
+ obj_stack.pop();
669
+ console.log("array pop " + key)
670
+ return settings.expanded ? table.node : util.expander(
671
+ util.stringify(arr),
672
+ 'Click to show more',
673
+ function() {
674
+ this.parentNode.appendChild(table.node);
675
+ }
676
+ );
677
+
678
+ },
679
+ 'function': function(fn, depth, key) {
680
+
681
+ /* Checking JUST circular refs */
682
+ var stackKey = util.within(stack).is(fn);
683
+ if (stackKey) {
684
+ return util.common.circRef(fn, stackKey);
685
+ }
686
+ stack[key || 'TOP'] = fn;
687
+
688
+ var miniTable = util.table(['Function', null], 'function'),
689
+ argsTable = util.table(['Arguments']),
690
+ args = fn.toString().match(/\((.+?)\)/),
691
+ body = fn.toString().match(/\(.*?\)\s+?\{?([\S\s]+)/)[1].replace(/\}?$/, '');
692
+
693
+ miniTable
694
+ .addRow(['arguments', args ? args[1].replace(/[^\w_,\s]/g, '') : '<small>[none/native]</small>'])
695
+ .addRow(['body', body]);
696
+
697
+ return settings.expanded ? miniTable.node : util.expander(
698
+ 'function(){...}',
699
+ 'Click to see more about this function.',
700
+ function() {
701
+ this.parentNode.appendChild(miniTable.node);
702
+ }
703
+ );
704
+ },
705
+ 'date': function(date) {
706
+
707
+ var miniTable = util.table(['Date', null], 'date'),
708
+ sDate = date.toString().split(/\s/);
709
+
710
+ /* TODO: Make this work well in IE! */
711
+ miniTable
712
+ .addRow(['Time', sDate[4]])
713
+ .addRow(['Date', sDate.slice(0, 4).join('-')]);
714
+
715
+ return settings.expanded ? miniTable.node : util.expander(
716
+ 'Date (timestamp): ' + (+date),
717
+ 'Click to see a little more info about this date',
718
+ function() {
719
+ this.parentNode.appendChild(miniTable.node);
720
+ }
721
+ );
722
+
723
+ },
724
+ 'boolean': function(bool) {
725
+ return util.txt(bool.toString().toUpperCase());
726
+ },
727
+ 'undefined': function() {
728
+ return util.txt('UNDEFINED');
729
+ },
730
+ 'null': function() {
731
+ return util.txt('NULL');
732
+ },
733
+ 'default': function() {
734
+ /* When a type cannot be found */
735
+ return util.txt('prettyPrint: TypeNotFound Error');
736
+ }
737
+ };
738
+
739
+ container.appendChild(typeDealer[(settings.forceObject) ? 'object' : util.type(obj)](obj, currentDepth));
740
+
741
+ return container;
742
+
743
+ };
744
+
745
+ /* Configuration */
746
+
747
+ /* All items can be overwridden by passing an
748
+ "options" object when calling prettyPrint */
749
+ prettyPrintThis.config = {
750
+
751
+ /* Try setting this to false to save space */
752
+ expanded: true,
753
+
754
+ forceObject: false,
755
+ maxDepth: 3,
756
+ maxArray: -1, // default is unlimited
757
+ styles: {
758
+ array: {
759
+ th: {
760
+ backgroundColor: '#6DBD2A',
761
+ color: 'white'
762
+ }
763
+ },
764
+ 'function': {
765
+ th: {
766
+ backgroundColor: '#D82525'
767
+ }
768
+ },
769
+ regexp: {
770
+ th: {
771
+ backgroundColor: '#E2F3FB',
772
+ color: '#000'
773
+ }
774
+ },
775
+ object: {
776
+ th: {
777
+ backgroundColor: '#1F96CF'
778
+ }
779
+ },
780
+ jquery: {
781
+ th: {
782
+ backgroundColor: '#FBF315'
783
+ }
784
+ },
785
+ error: {
786
+ th: {
787
+ backgroundColor: 'red',
788
+ color: 'yellow'
789
+ }
790
+ },
791
+ domelement: {
792
+ th: {
793
+ backgroundColor: '#F3801E'
794
+ }
795
+ },
796
+ date: {
797
+ th: {
798
+ backgroundColor: '#A725D8'
799
+ }
800
+ },
801
+ colHeader: {
802
+ th: {
803
+ backgroundColor: '#EEE',
804
+ color: '#000',
805
+ textTransform: 'uppercase'
806
+ }
807
+ },
808
+ more_callback: function(stack) {
809
+
810
+ },
811
+ 'default': {
812
+ table: {
813
+ borderCollapse: 'collapse',
814
+ width: '100%'
815
+ },
816
+ td: {
817
+ padding: '5px',
818
+ fontSize: '12px',
819
+ backgroundColor: '#FFF',
820
+ color: '#222',
821
+ border: '1px solid #000',
822
+ verticalAlign: 'top',
823
+ fontFamily: '"Consolas","Lucida Console",Courier,mono',
824
+ whiteSpace: 'nowrap'
825
+ },
826
+ td_hover: {
827
+ /* Styles defined here will apply to all tr:hover > td,
828
+ - Be aware that "inheritable" properties (e.g. fontWeight) WILL BE INHERITED */
829
+ },
830
+ th: {
831
+ padding: '5px',
832
+ fontSize: '12px',
833
+ backgroundColor: '#222',
834
+ color: '#EEE',
835
+ textAlign: 'left',
836
+ border: '1px solid #000',
837
+ verticalAlign: 'top',
838
+ fontFamily: '"Consolas","Lucida Console",Courier,mono',
839
+ backgroundImage: util.headerGradient,
840
+ backgroundRepeat: 'repeat-x'
841
+ }
842
+ }
843
+ }
844
+ };
845
+
846
+ return prettyPrintThis;
847
+
848
+ })();
849
+ </script>
850
+
851
+ <script>
852
+
853
+ var path = window.location.pathname
854
+ var base_debug_path = path + '?debug='
855
+ var entry_debug_path = base_debug_path + "*.*"
856
+
857
+ $(function() {
858
+ request_data(entry_debug_path);
859
+ })
860
+
861
+ var data = {}
862
+ request_data = function(path) {
863
+ $.ajax(path, dataType = 'json')
864
+ .done(function(data) {
865
+ update_data(data);
866
+ })
867
+ }
868
+ update_data = function(new_data) {
869
+ jQuery.extend(true, data, new_data);
870
+ var html = prettyPrint(data, {
871
+ maxDepth: -1,
872
+ more_callback: function(stack) {
873
+ request_data(base_debug_path + stack)
874
+ }
875
+ })
876
+ $("#content").html(html)
877
+ }
878
+
879
+ </script>
880
+
881
+ </html>