jeffreyhunter77-R2Doc 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +20 -0
  3. data/Manifest +50 -0
  4. data/R2Doc.gemspec +33 -0
  5. data/README +103 -0
  6. data/README.rdoc +103 -0
  7. data/Rakefile +9 -0
  8. data/bin/r2doc +157 -0
  9. data/lib/r2doc.rb +7 -0
  10. data/lib/r2doc/context_extensions.rb +237 -0
  11. data/lib/r2doc/erb_template_engine.rb +11 -0
  12. data/lib/r2doc/generator.rb +123 -0
  13. data/lib/r2doc/rdoc_v2_generator.rb +112 -0
  14. data/lib/r2doc/template.rb +95 -0
  15. data/lib/r2doc/template/r2doc/_aliases.html.erb +22 -0
  16. data/lib/r2doc/template/r2doc/_attributes.html.erb +24 -0
  17. data/lib/r2doc/template/r2doc/_classes_and_modules.html.erb +13 -0
  18. data/lib/r2doc/template/r2doc/_constants.html.erb +22 -0
  19. data/lib/r2doc/template/r2doc/_method_detail.html.erb +10 -0
  20. data/lib/r2doc/template/r2doc/_method_details.html.erb +17 -0
  21. data/lib/r2doc/template/r2doc/_method_listing.html.erb +37 -0
  22. data/lib/r2doc/template/r2doc/_method_listing_row.html.erb +4 -0
  23. data/lib/r2doc/template/r2doc/_nav.html.erb +40 -0
  24. data/lib/r2doc/template/r2doc/_nav_item.html.erb +1 -0
  25. data/lib/r2doc/template/r2doc/class.html.erb +71 -0
  26. data/lib/r2doc/template/r2doc/file.html.erb +52 -0
  27. data/lib/r2doc/template/r2doc/images/blue-arrow-right.png +0 -0
  28. data/lib/r2doc/template/r2doc/images/blue-arrow-up.png +0 -0
  29. data/lib/r2doc/template/r2doc/images/blue-box.png +0 -0
  30. data/lib/r2doc/template/r2doc/images/blue-plus.png +0 -0
  31. data/lib/r2doc/template/r2doc/images/close-button.png +0 -0
  32. data/lib/r2doc/template/r2doc/images/green-arrow-right.png +0 -0
  33. data/lib/r2doc/template/r2doc/images/green-arrow-up.png +0 -0
  34. data/lib/r2doc/template/r2doc/images/nav-back.png +0 -0
  35. data/lib/r2doc/template/r2doc/images/nav-bottom.png +0 -0
  36. data/lib/r2doc/template/r2doc/images/nav-top.png +0 -0
  37. data/lib/r2doc/template/r2doc/images/orange-hash.png +0 -0
  38. data/lib/r2doc/template/r2doc/images/red-dash.png +0 -0
  39. data/lib/r2doc/template/r2doc/images/search-back.png +0 -0
  40. data/lib/r2doc/template/r2doc/images/top-back.png +0 -0
  41. data/lib/r2doc/template/r2doc/images/top-left.png +0 -0
  42. data/lib/r2doc/template/r2doc/images/top-right.png +0 -0
  43. data/lib/r2doc/template/r2doc/index.html.erb +42 -0
  44. data/lib/r2doc/template/r2doc/jquery.js +19 -0
  45. data/lib/r2doc/template/r2doc/prototype.js +285 -0
  46. data/lib/r2doc/template/r2doc/r2doc.css +400 -0
  47. data/lib/r2doc/template/r2doc/rdoc-utils.js +510 -0
  48. data/lib/r2doc/template/r2doc/rdoc.js.erb +164 -0
  49. data/lib/r2doc/template_util.rb +82 -0
  50. data/lib/rdoc/discover.rb +4 -0
  51. data/lib/rdoc/generators/r2doc_generator.rb +105 -0
  52. metadata +155 -0
@@ -0,0 +1,510 @@
1
+ /* R2Doc
2
+ * Copyright (c) 2009 Jeffrey Hunter and Mission Critical Labs, Inc.
3
+ *
4
+ * Distributable under an MIT-style license. See LICENSE file for details.
5
+ */
6
+
7
+
8
+ /**
9
+ * 'Namespace' for rdoc-related stuff
10
+ */
11
+ var rdoc = {};
12
+
13
+ /**
14
+ * Utility function for generating the URL from one page to another.
15
+ */
16
+ rdoc.genUrl = function(fromUrl, toUrl) {
17
+ var fromItems = fromUrl.split(/\\+|\/+/);
18
+ var toItems = toUrl.split(/\\+|\/+/);
19
+
20
+ fromItems.pop();
21
+ var toFile = toItems.pop();
22
+
23
+ while (fromItems.length > 0 && toItems.length > 0 && fromItems[0] == toItems[0]) {
24
+ fromItems.shift();
25
+ toItems.shift();
26
+ }
27
+
28
+ var url = [];
29
+ for (var i = 0; i < fromItems.length; i++) { url.push('..'); }
30
+
31
+ url = url.concat(toItems);
32
+ url.push(toFile);
33
+ return url.join('/');
34
+ }
35
+
36
+ /**
37
+ * Base class for custom autocompleters.
38
+ *
39
+ * This class is an abstract class intended for creating your own
40
+ * autocompletion widget. Derived classes must define the methods
41
+ * delayedUpdate(), determineIds(), setIds(result). The methods are
42
+ * described in greater detail below. This class does not provide an
43
+ * initialize method of its own. It defines a method named
44
+ * baseInitialize which is intended to be called from the derived class's
45
+ * initialize function.
46
+ *
47
+ * The delayedUpdate() method is responsible for retrieving the list of
48
+ * possible autocompletion options. It typically passes this back by
49
+ * calling newSelections(). newSelections() expects an array of objects
50
+ * representing each possible selection. At a minimum, each object must
51
+ * provide two properties: display_name and description. Note that
52
+ * display_name is the value that will be evaluated to see if it matches
53
+ * what the user has typed.
54
+ *
55
+ * The determineIds() method is called when the control loses focus
56
+ * without a selection being chosen through any of the autocompletion
57
+ * means (e.g. by clicking an item, hitting tab, or hitting return).
58
+ * This is an opportunity for the control to perform any cleanup needed
59
+ * for a typed in response (for example, lookup an id based on the typed
60
+ * in text).
61
+ *
62
+ * The setIds() method is called when a specific item from the list of
63
+ * autocompletion options is chosen. The item chose is passed to the
64
+ * funtion. If the delayedUpdate() method passes a list of objects to
65
+ * newSelections(), the object passed to setIds() will be the selected
66
+ * object from the list.
67
+ */
68
+ rdoc.CustomAutoCompleter = Class.create();
69
+ rdoc.CustomAutoCompleter.prototype = {
70
+ /**
71
+ * Constructor
72
+ *
73
+ * @param elem The element or id to preform autocompletion for
74
+ * @param chooser The element or id of the window that diplays the choices
75
+ */
76
+ baseInitialize: function(elem, chooser) {
77
+ this.element = $(elem);
78
+ this.chooser = $(chooser);
79
+ this.visible = false;
80
+ this.selectedIndex = null;
81
+ this.selectedElem = null;
82
+ this.options = null;
83
+ this.selectionSet = false;
84
+ this.listClickCallback = this.onListClick.bind(this);
85
+ this.updateTimer = null;
86
+
87
+ // prep the chooser
88
+ this.chooser.style.display = 'none';
89
+
90
+ // prep the element
91
+ this.element.setAttribute('autocomplete','off');
92
+ Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
93
+ Event.observe(this.element, "keydown", this.onKeyPress.bindAsEventListener(this));
94
+ },
95
+
96
+ /**
97
+ * Called when a key is pressed for the autocompleting element
98
+ */
99
+ onKeyPress: function(event) {
100
+ switch(event.keyCode) {
101
+ case Event.KEY_TAB:
102
+ case Event.KEY_RETURN:
103
+ if (this.selectedIndex != null) {
104
+ this.useSelection();
105
+ Event.stop(event);
106
+ }
107
+ return;
108
+
109
+ case Event.KEY_ESC:
110
+ this.hide();
111
+ Event.stop(event);
112
+ return;
113
+
114
+ case Event.KEY_LEFT:
115
+ case Event.KEY_RIGHT:
116
+ return;
117
+
118
+ case Event.KEY_UP:
119
+ this.selectionSet = false;
120
+ this.selectionUp();
121
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
122
+ return;
123
+
124
+ case Event.KEY_DOWN:
125
+ if (!this.visible) {
126
+ this.updateSelectionsNow();
127
+ } else {
128
+ this.selectionSet = false;
129
+ this.selectionDown();
130
+ }
131
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
132
+ return;
133
+ }
134
+
135
+ this.selectionSet = false;
136
+ this.updateSelections();
137
+ },
138
+
139
+ /**
140
+ * Called when the autocompleting element loses focus
141
+ */
142
+ onBlur: function(event) {
143
+ // to make sure click events work on the list
144
+ setTimeout(this.afterBlur.bind(this), 250);
145
+ },
146
+
147
+ /**
148
+ * Called after focus has already been lost
149
+ */
150
+ afterBlur: function() {
151
+ if (!this.selectionSet) this.determineIds();
152
+ this.hide();
153
+ },
154
+
155
+ /**
156
+ * Makes the selected item the new element value
157
+ */
158
+ useSelection: function() {
159
+ if (this.selectedIndex == null) return;
160
+
161
+ var selected = this.options[this.selectedIndex];
162
+ this.setIds(selected);
163
+ this.hide();
164
+ },
165
+
166
+ /**
167
+ * Turn off the selection window
168
+ */
169
+ hide: function() {
170
+ this.visible = false;
171
+ this.selectedIndex = null;
172
+ this.selectedElem = null;
173
+ this.chooser.style.display = 'none';
174
+ },
175
+
176
+ /**
177
+ * Move the selection up one item in the list
178
+ */
179
+ selectionUp: function() {
180
+ if (!this.selectedElem) return;
181
+ if (!this.selectedElem.previousSibling) return;
182
+
183
+ this.selectedElem.className = '';
184
+ this.selectedElem = this.selectedElem.previousSibling;
185
+ this.selectedIndex = this.selectedElem.optionIndex;
186
+ this.selectedElem.className = 'selected';
187
+ this.scrollIntoView(this.selectedElem);
188
+ },
189
+
190
+ /**
191
+ * Move the selection down one item in the list
192
+ */
193
+ selectionDown: function() {
194
+ if (!this.selectedElem) {
195
+ this.selectFirst();
196
+ return;
197
+ }
198
+
199
+ if (!this.selectedElem.nextSibling) return;
200
+
201
+ this.selectedElem.className = '';
202
+ this.selectedElem = this.selectedElem.nextSibling;
203
+ this.selectedIndex = this.selectedElem.optionIndex;
204
+ this.selectedElem.className = 'selected';
205
+ this.scrollIntoView(this.selectedElem);
206
+ },
207
+
208
+ /**
209
+ * Select the first element
210
+ */
211
+ selectFirst: function() {
212
+ if (this.options.length > 0) {
213
+ this.selectedIndex = 0;
214
+ this.selectedElem = this.chooser.down('li');
215
+ if (this.selectedElem) {
216
+ this.selectedElem.className = 'selected';
217
+ this.scrollIntoView(this.selectedElem);
218
+ return true;
219
+ } else {
220
+ return false;
221
+ }
222
+ }
223
+
224
+ return false;
225
+ },
226
+
227
+ /**
228
+ * Scroll the list of selections, if necessary, so that the given item is
229
+ * visible
230
+ */
231
+ scrollIntoView: function(elem) {
232
+ var topY = elem.offsetTop - this.chooser.scrollTop;
233
+ var bottomY = topY + elem.offsetHeight;
234
+
235
+ // if the top is too high, scroll down
236
+ if (topY < 0) {
237
+ this.chooser.scrollTop = elem.offsetTop;
238
+ // otherwise, if the bottom is too low, scroll up
239
+ } else if (bottomY > this.chooser.clientHeight) {
240
+ this.chooser.scrollTop = elem.offsetTop - this.chooser.clientHeight + elem.offsetHeight;
241
+ }
242
+ },
243
+
244
+ /**
245
+ * Click event handler for list items
246
+ */
247
+ onListClick: function(event) {
248
+ var li = Event.findElement(event, 'LI');
249
+ if (!li) return;
250
+
251
+ if (this.selectedElem) this.selectedElem.className = '';
252
+
253
+ this.selectedElem = li;
254
+ this.selectedIndex = li.optionIndex;
255
+ li.className = 'selected';
256
+ this.useSelection();
257
+ },
258
+
259
+ /**
260
+ * Update the list of selections
261
+ */
262
+ updateSelections: function() {
263
+ this.visible = true;
264
+ if (this.updateTimer != null) clearTimeout(this.updateTimer);
265
+ this.updateTimer = setTimeout(this.delayedUpdate.bind(this), 250);
266
+ },
267
+
268
+ /**
269
+ * Perform an immediate update the list of selections
270
+ */
271
+ updateSelectionsNow: function() {
272
+ this.visible = true;
273
+ if (this.updateTimer != null) clearTimeout(this.updateTimer);
274
+ this.updateTimer = setTimeout(this.delayedUpdate.bind(this), 1);
275
+ },
276
+
277
+ /**
278
+ * Called when new selections are retrieved
279
+ */
280
+ newSelections: function(allOptions, preserveSelectedIndex) {
281
+ if (!this.visible) return;
282
+
283
+ var txt = this.element.value.toUpperCase();
284
+
285
+ // examine all possibilities and show only those beginning with the currently entered text
286
+ this.options = [];
287
+ var i;
288
+ for (i = 0; i < allOptions.length; i++) {
289
+ if (allOptions[i].display_name.substring(0, txt.length).toUpperCase() == txt)
290
+ this.options.push(allOptions[i]);
291
+ }
292
+
293
+ if (!preserveSelectedIndex)
294
+ this.selectedIndex = 0;
295
+ this.updateDisplay();
296
+ },
297
+
298
+ /**
299
+ * Update the selection box with a new set of options
300
+ */
301
+ updateDisplay: function() {
302
+ // just hide the display if nothing matches
303
+ if (this.options.length == 0) {
304
+ this.hide();
305
+ return;
306
+ }
307
+
308
+ // create the list
309
+ var ul = document.createElement('UL');
310
+ var idx = 0;
311
+
312
+ while (idx < this.options.length) {
313
+ var li = document.createElement('LI');
314
+ li.innerHTML = this.options[idx].display_name.escapeHTML() + ' <span class="description">' + this.options[idx].description.escapeHTML() + '</span>';
315
+ li.optionIndex = idx;
316
+ Event.observe(li, 'click', this.listClickCallback);
317
+ if (this.selectedIndex == idx) {
318
+ li.className = 'selected';
319
+ this.selectedElem = li;
320
+ }
321
+ ul.appendChild(li);
322
+ idx++;
323
+ }
324
+
325
+ // populate the display
326
+ while (this.chooser.hasChildNodes()) { this.chooser.removeChild(this.chooser.childNodes[0]); }
327
+ this.chooser.appendChild(ul);
328
+
329
+ if (this.chooser.style.display != 'block') {
330
+ this.chooser.style.zIndex = 1;
331
+ this.chooser.style.position = 'absolute';
332
+ this.positionChooser();
333
+ this.displayChooser();
334
+ }
335
+ },
336
+
337
+ /**
338
+ * Set the position for the chooser window
339
+ */
340
+ positionChooser: function() {
341
+ Position.clone(this.element, this.chooser, {setHeight: false, offsetTop: this.element.offsetHeight});
342
+ },
343
+
344
+ /**
345
+ * Effect for displaying the chooser. Can be overridden.
346
+ */
347
+ displayChooser: function() {
348
+ jQuery(this.chooser).slideDown('fast');
349
+ }
350
+ };
351
+
352
+ /**
353
+ * Base class for custom modal dialogs
354
+ *
355
+ * Supported options:
356
+ * maskOpacity - Opacity (0.0 to 1.0) of the background behind the dialog
357
+ * maskColor - Color of the background behind the dialog
358
+ * maskZIndex - Z-index of the background behind the dialog
359
+ * container - Id or element to contain the dialog (defaults to body element)
360
+ */
361
+ rdoc.CustomDialog = Class.create();
362
+ rdoc.CustomDialog.prototype = {
363
+ /**
364
+ * Constructor
365
+ */
366
+ baseInitialize: function(options) {
367
+ this.options = {maskOpacity: 0.6, maskColor: '#000', maskZIndex: 1000};
368
+ if (options) this.options = Object.extend(this.options, options);
369
+
370
+ this.background = this.initBack();
371
+ this.dialog = this.initDialog();
372
+ },
373
+
374
+ /**
375
+ * Display the dialog
376
+ */
377
+ open: function(id) {
378
+ var size = this.pageDimensions();
379
+
380
+ this.background.style.top = '0px';
381
+ this.background.style.left = '0px';
382
+ this.background.style.width = size.width + 'px';
383
+ this.background.style.height = size.height + 'px';
384
+ if (this.options.maskOpacity) this.background.setOpacity(this.options.maskOpacity);
385
+ jQuery(this.background).fadeIn('normal');
386
+
387
+ this.centerDialog(size);
388
+ jQuery(this.dialog).fadeIn('normal');
389
+ },
390
+
391
+ /**
392
+ * Close/hide the dialog
393
+ */
394
+ close: function() {
395
+ jQuery(this.background).fadeOut();
396
+ jQuery(this.dialog).fadeOut();
397
+ },
398
+
399
+ /**
400
+ * Center the dialog
401
+ */
402
+ centerDialog: function(size) {
403
+ var scrollY = (window.scrollY ? window.scrollY : (document.body.scrollY ? document.body.scrollY : (document.documentElement.scrollTop ? document.documentElement.scrollTop : 0)));
404
+
405
+ this.dialog.style.top = (scrollY + 40) + 'px';
406
+ this.dialog.style.left = Math.floor((size.width - this.dialogWidth()) / 2) + 'px';
407
+ },
408
+
409
+ /**
410
+ * Return the width of the dialog in pixels
411
+ */
412
+ dialogWidth: function() {
413
+ return this.dialog.clientWidth;
414
+ },
415
+
416
+ /**
417
+ * Create the background element
418
+ */
419
+ initBack: function() {
420
+ var div = document.createElement('div');
421
+ div.style.position = 'absolute';
422
+ div.style.display = 'none';
423
+ if (this.options.maskColor) div.style.backgroundColor = this.options.maskColor;
424
+ if (this.options.maskZIndex) div.style.zIndex = this.options.maskZIndex;
425
+ var container = this.options.container ? $(this.options.container) : $$('body').first();
426
+ container.appendChild(div);
427
+ return $(div);
428
+ },
429
+
430
+ /**
431
+ * Create the dialog element
432
+ */
433
+ initDialog: function() {
434
+ var div = document.createElement('div');
435
+ div.style.position = 'absolute';
436
+ div.style.display = 'none';
437
+ if (this.options.maskZIndex) div.style.zIndex = this.options.maskZIndex + 1;
438
+ var container = this.options.container ? $(this.options.container) : $$('body').first();
439
+ container.appendChild(div);
440
+ return $(div);
441
+ },
442
+
443
+ /**
444
+ * Current scrollable size
445
+ */
446
+ scrollableDimensions: function() {
447
+ var size = {};
448
+
449
+ if (window.innerHeight && window.scrollMaxY) {
450
+ var baseWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : window.innerWidth;
451
+ size.width = baseWidth + window.scrollMaxX;
452
+ size.height = window.innerHeight + window.scrollMaxY;
453
+ } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
454
+ size.width = document.body.scrollWidth;
455
+ size.height = document.body.scrollHeight;
456
+ } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
457
+ size.width = document.body.offsetWidth;
458
+ if (document.documentElement && document.documentElement.scrollHeight > document.body.offsetHeight)
459
+ size.height = document.documentElement.scrollHeight;
460
+ else
461
+ size.height = document.body.offsetHeight;
462
+ }
463
+
464
+ return size;
465
+ },
466
+
467
+ /**
468
+ * Current document size
469
+ */
470
+ documentDimensions: function() {
471
+ var size = {};
472
+
473
+ if (self.innerHeight) { // all except Explorer
474
+ size.width = document.documentElement.clientWidth ?
475
+ document.documentElement.clientWidth : self.innerWidth;
476
+ size.height = self.innerHeight;
477
+ } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
478
+ if (document.body && document.body.clientWidth > document.documentElement.clientWidth)
479
+ size.width = document.body.clientWidth;
480
+ else
481
+ size.width = document.documentElement.clientWidth;
482
+ if (document.body && document.body.clientHeight > document.documentElement.clientHeight)
483
+ size.height = document.body.clientHeight;
484
+ else
485
+ size.height = document.documentElement.clientHeight;
486
+ } else if (document.body) { // other Explorers
487
+ size.width = document.body.clientWidth;
488
+ size.height = document.body.clientHeight;
489
+ }
490
+
491
+ return size;
492
+ },
493
+
494
+ /**
495
+ * Determine the current page size
496
+ */
497
+ pageDimensions: function () {
498
+ var scrollSize = this.scrollableDimensions();
499
+ var winSize = this.documentDimensions();
500
+ var pageSize = {};
501
+
502
+ // for small pages with total height less then height of the viewport
503
+ pageSize.height = (scrollSize.height < winSize.height) ? winSize.height : scrollSize.height;
504
+ // for small pages with total width less then width of the viewport
505
+ pageSize.width = (scrollSize.width < winSize.width) ? winSize.width : scrollSize.width;
506
+
507
+ return pageSize;
508
+ }
509
+
510
+ };