erlapi 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +15 -0
  5. data/Rakefile +56 -0
  6. data/VERSION +1 -0
  7. data/bin/erlapi +26 -0
  8. data/erlapi.gemspec +140 -0
  9. data/lib/erlapi.rb +38 -0
  10. data/lib/erlapi/generator.rb +194 -0
  11. data/lib/erlapi/generator/shtml.rb +353 -0
  12. data/lib/erlapi/generator/template/direct/_context.rhtml +172 -0
  13. data/lib/erlapi/generator/template/direct/class.rhtml +40 -0
  14. data/lib/erlapi/generator/template/direct/file.rhtml +30 -0
  15. data/lib/erlapi/generator/template/direct/index.rhtml +14 -0
  16. data/lib/erlapi/generator/template/direct/resources/apple-touch-icon.png +0 -0
  17. data/lib/erlapi/generator/template/direct/resources/css/main.css +263 -0
  18. data/lib/erlapi/generator/template/direct/resources/css/panel.css +383 -0
  19. data/lib/erlapi/generator/template/direct/resources/css/reset.css +53 -0
  20. data/lib/erlapi/generator/template/direct/resources/favicon.ico +0 -0
  21. data/lib/erlapi/generator/template/direct/resources/i/arrows.png +0 -0
  22. data/lib/erlapi/generator/template/direct/resources/i/results_bg.png +0 -0
  23. data/lib/erlapi/generator/template/direct/resources/i/tree_bg.png +0 -0
  24. data/lib/erlapi/generator/template/direct/resources/js/jquery-1.3.2.min.js +19 -0
  25. data/lib/erlapi/generator/template/direct/resources/js/jquery-effect.js +593 -0
  26. data/lib/erlapi/generator/template/direct/resources/js/main.js +22 -0
  27. data/lib/erlapi/generator/template/direct/resources/js/searchdoc.js +628 -0
  28. data/lib/erlapi/generator/template/direct/resources/panel/index.html +71 -0
  29. data/lib/erlapi/generator/template/merge/index.rhtml +14 -0
  30. data/lib/erlapi/generator/template/shtml/_context.rhtml +164 -0
  31. data/lib/erlapi/generator/template/shtml/class.rhtml +46 -0
  32. data/lib/erlapi/generator/template/shtml/file.rhtml +37 -0
  33. data/lib/erlapi/generator/template/shtml/index.rhtml +14 -0
  34. data/lib/erlapi/generator/template/shtml/resources/apple-touch-icon.png +0 -0
  35. data/lib/erlapi/generator/template/shtml/resources/css/main.css +191 -0
  36. data/lib/erlapi/generator/template/shtml/resources/css/panel.css +383 -0
  37. data/lib/erlapi/generator/template/shtml/resources/css/reset.css +53 -0
  38. data/lib/erlapi/generator/template/shtml/resources/favicon.ico +0 -0
  39. data/lib/erlapi/generator/template/shtml/resources/i/arrows.png +0 -0
  40. data/lib/erlapi/generator/template/shtml/resources/i/results_bg.png +0 -0
  41. data/lib/erlapi/generator/template/shtml/resources/i/tree_bg.png +0 -0
  42. data/lib/erlapi/generator/template/shtml/resources/js/jquery-1.3.2.min.js +19 -0
  43. data/lib/erlapi/generator/template/shtml/resources/js/main.js +34 -0
  44. data/lib/erlapi/generator/template/shtml/resources/js/searchdoc.js +628 -0
  45. data/lib/erlapi/generator/template/shtml/resources/panel/index.html +71 -0
  46. data/lib/erlapi/helpers.rb +26 -0
  47. data/lib/erlapi/merge.rb +217 -0
  48. data/lib/erlapi/parser.rb +134 -0
  49. data/lib/erlapi/shtml.rb +351 -0
  50. data/lib/erlapi/templatable.rb +51 -0
  51. data/lib/erlapi/templates/html/direct/_context.rhtml +172 -0
  52. data/lib/erlapi/templates/html/direct/class.rhtml +40 -0
  53. data/lib/erlapi/templates/html/direct/file.rhtml +30 -0
  54. data/lib/erlapi/templates/html/direct/index.rhtml +14 -0
  55. data/lib/erlapi/templates/html/direct/resources/apple-touch-icon.png +0 -0
  56. data/lib/erlapi/templates/html/direct/resources/css/main.css +263 -0
  57. data/lib/erlapi/templates/html/direct/resources/css/panel.css +383 -0
  58. data/lib/erlapi/templates/html/direct/resources/css/reset.css +53 -0
  59. data/lib/erlapi/templates/html/direct/resources/favicon.ico +0 -0
  60. data/lib/erlapi/templates/html/direct/resources/i/arrows.png +0 -0
  61. data/lib/erlapi/templates/html/direct/resources/i/results_bg.png +0 -0
  62. data/lib/erlapi/templates/html/direct/resources/i/tree_bg.png +0 -0
  63. data/lib/erlapi/templates/html/direct/resources/js/jquery-1.3.2.min.js +19 -0
  64. data/lib/erlapi/templates/html/direct/resources/js/jquery-effect.js +593 -0
  65. data/lib/erlapi/templates/html/direct/resources/js/main.js +22 -0
  66. data/lib/erlapi/templates/html/direct/resources/js/searchdoc.js +628 -0
  67. data/lib/erlapi/templates/html/direct/resources/panel/index.html +71 -0
  68. data/lib/erlapi/templates/html/merge/index.rhtml +14 -0
  69. data/lib/erlapi/templates/html/shtml/_context.rhtml +68 -0
  70. data/lib/erlapi/templates/html/shtml/class.rhtml +25 -0
  71. data/lib/erlapi/templates/html/shtml/file.rhtml +37 -0
  72. data/lib/erlapi/templates/html/shtml/index.rhtml +14 -0
  73. data/lib/erlapi/templates/html/shtml/resources copy/apple-touch-icon.png +0 -0
  74. data/lib/erlapi/templates/html/shtml/resources copy/css/main.css +195 -0
  75. data/lib/erlapi/templates/html/shtml/resources copy/css/panel.css +383 -0
  76. data/lib/erlapi/templates/html/shtml/resources copy/css/reset.css +53 -0
  77. data/lib/erlapi/templates/html/shtml/resources copy/favicon.ico +0 -0
  78. data/lib/erlapi/templates/html/shtml/resources copy/i/arrows.png +0 -0
  79. data/lib/erlapi/templates/html/shtml/resources copy/i/results_bg.png +0 -0
  80. data/lib/erlapi/templates/html/shtml/resources copy/i/tree_bg.png +0 -0
  81. data/lib/erlapi/templates/html/shtml/resources copy/js/jquery-1.3.2.min.js +19 -0
  82. data/lib/erlapi/templates/html/shtml/resources copy/js/main.js +34 -0
  83. data/lib/erlapi/templates/html/shtml/resources copy/js/searchdoc.js +628 -0
  84. data/lib/erlapi/templates/html/shtml/resources copy/panel/index.html +71 -0
  85. data/lib/erlapi/templates/html/shtml/resources/apple-touch-icon.png +0 -0
  86. data/lib/erlapi/templates/html/shtml/resources/css/main.css +263 -0
  87. data/lib/erlapi/templates/html/shtml/resources/css/panel.css +383 -0
  88. data/lib/erlapi/templates/html/shtml/resources/css/reset.css +53 -0
  89. data/lib/erlapi/templates/html/shtml/resources/favicon.ico +0 -0
  90. data/lib/erlapi/templates/html/shtml/resources/i/arrows.png +0 -0
  91. data/lib/erlapi/templates/html/shtml/resources/i/results_bg.png +0 -0
  92. data/lib/erlapi/templates/html/shtml/resources/i/tree_bg.png +0 -0
  93. data/lib/erlapi/templates/html/shtml/resources/js/jquery-1.3.2.min.js +19 -0
  94. data/lib/erlapi/templates/html/shtml/resources/js/jquery-effect.js +593 -0
  95. data/lib/erlapi/templates/html/shtml/resources/js/main.js +22 -0
  96. data/lib/erlapi/templates/html/shtml/resources/js/searchdoc.js +620 -0
  97. data/lib/erlapi/templates/html/shtml/resources/panel/index.html +71 -0
  98. data/test/erlapi_test.rb +7 -0
  99. data/test/test_helper.rb +10 -0
  100. metadata +155 -0
@@ -0,0 +1,351 @@
1
+ require 'rubygems'
2
+ gem "rdoc", ">= 2.4.2"
3
+ if Gem.available? "json"
4
+ gem "json", ">= 1.1.3"
5
+ else
6
+ gem "json_pure", ">= 1.1.3"
7
+ end
8
+
9
+ require 'iconv'
10
+ require 'json'
11
+ require 'pathname'
12
+ require 'fileutils'
13
+ require 'erb'
14
+
15
+ require 'sdoc/github'
16
+ require 'sdoc/templatable'
17
+ require 'sdoc/helpers'
18
+
19
+ class RDoc::ClassModule
20
+ def document_self_or_methods
21
+ document_self || method_list.any?{ |m| m.document_self }
22
+ end
23
+
24
+ def with_documentation?
25
+ document_self_or_methods || classes_and_modules.any?{ |c| c.with_documentation? }
26
+ end
27
+ end
28
+
29
+ class RDoc::Generator::SHtml
30
+ RDoc::RDoc.add_generator( self )
31
+ include ERB::Util
32
+ include SDoc::GitHub
33
+ include SDoc::Templatable
34
+ include SDoc::Helpers
35
+
36
+ GENERATOR_DIRS = [File.join('sdoc', 'generator'), File.join('rdoc', 'generator')]
37
+
38
+ # Used in js to reduce index sizes
39
+ TYPE_CLASS = 1
40
+ TYPE_METHOD = 2
41
+ TYPE_FILE = 3
42
+
43
+ TREE_FILE = File.join 'panel', 'tree.js'
44
+ SEARCH_INDEX_FILE = File.join 'panel', 'search_index.js'
45
+
46
+ FILE_DIR = 'files'
47
+ CLASS_DIR = 'classes'
48
+
49
+ RESOURCES_DIR = File.join('resources', '.')
50
+
51
+ attr_reader :basedir
52
+
53
+ def self.for(options)
54
+ self.new(options)
55
+ end
56
+
57
+ def self.template_dir template
58
+ $LOAD_PATH.map do |path|
59
+ GENERATOR_DIRS.map do |dir|
60
+ File.join path, dir, 'template', template
61
+ end
62
+ end.flatten.find do |dir|
63
+ File.directory? dir
64
+ end
65
+ end
66
+
67
+ def initialize(options)
68
+ @options = options
69
+ @options.diagram = false
70
+ @github_url_cache = {}
71
+
72
+ template = @options.template || 'direct'
73
+
74
+ templ_dir = self.class.template_dir template
75
+
76
+ raise RDoc::Error, "could not find template #{template.inspect}" unless
77
+ templ_dir
78
+
79
+ @template_dir = Pathname.new File.expand_path(templ_dir)
80
+ @basedir = Pathname.pwd.expand_path
81
+ end
82
+
83
+ def generate( top_levels )
84
+ @outputdir = Pathname.new( @options.op_dir ).expand_path( @basedir )
85
+ @files = top_levels.sort
86
+ @classes = RDoc::TopLevel.all_classes_and_modules.sort
87
+
88
+ # Now actually write the output
89
+ copy_resources
90
+ generate_class_tree
91
+ generate_search_index
92
+ generate_file_files
93
+ generate_class_files
94
+ generate_index_file
95
+ end
96
+
97
+ def class_dir
98
+ CLASS_DIR
99
+ end
100
+
101
+ def file_dir
102
+ FILE_DIR
103
+ end
104
+
105
+
106
+ protected
107
+ ### Output progress information if debugging is enabled
108
+ def debug_msg( *msg )
109
+ return unless $DEBUG_RDOC
110
+ $stderr.puts( *msg )
111
+ end
112
+
113
+ ### Create class tree structure and write it as json
114
+ def generate_class_tree
115
+ debug_msg "Generating class tree"
116
+ topclasses = @classes.select {|klass| !(RDoc::ClassModule === klass.parent) }
117
+ tree = generate_file_tree + generate_class_tree_level(topclasses)
118
+ debug_msg " writing class tree to %s" % TREE_FILE
119
+ File.open(TREE_FILE, "w", 0644) do |f|
120
+ f.write('var tree = '); f.write(tree.to_json)
121
+ end unless $dryrun
122
+ end
123
+
124
+ ### Recursivly build class tree structure
125
+ def generate_class_tree_level(classes)
126
+ tree = []
127
+ classes.select{|c| c.with_documentation? }.sort.each do |klass|
128
+ item = [
129
+ klass.name,
130
+ klass.document_self_or_methods ? klass.path : '',
131
+ klass.module? ? '' : (klass.superclass ? " < #{String === klass.superclass ? klass.superclass : klass.superclass.full_name}" : ''),
132
+ generate_class_tree_level(klass.classes_and_modules)
133
+ ]
134
+ tree << item
135
+ end
136
+ tree
137
+ end
138
+
139
+ ### Create search index for all classes, methods and files
140
+ ### Wite it as json
141
+ def generate_search_index
142
+ debug_msg "Generating search index"
143
+
144
+ index = {
145
+ :searchIndex => [],
146
+ :longSearchIndex => [],
147
+ :info => []
148
+ }
149
+
150
+ add_class_search_index(index)
151
+ add_method_search_index(index)
152
+ add_file_search_index(index)
153
+
154
+ debug_msg " writing search index to %s" % SEARCH_INDEX_FILE
155
+ data = {
156
+ :index => index
157
+ }
158
+ File.open(SEARCH_INDEX_FILE, "w", 0644) do |f|
159
+ f.write('var search_data = '); f.write(data.to_json)
160
+ end unless $dryrun
161
+ end
162
+
163
+ ### Add files to search +index+ array
164
+ def add_file_search_index(index)
165
+ debug_msg " generating file search index"
166
+
167
+ @files.select { |file|
168
+ file.document_self
169
+ }.sort.each do |file|
170
+ index[:searchIndex].push( search_string(file.name) )
171
+ index[:longSearchIndex].push( search_string(file.path) )
172
+ index[:info].push([
173
+ file.name,
174
+ file.path,
175
+ file.path,
176
+ '',
177
+ snippet(file.comment),
178
+ TYPE_FILE
179
+ ])
180
+ end
181
+ end
182
+
183
+ ### Add classes to search +index+ array
184
+ def add_class_search_index(index)
185
+ debug_msg " generating class search index"
186
+
187
+ @classes.select { |klass|
188
+ klass.document_self_or_methods
189
+ }.sort.each do |klass|
190
+ index[:searchIndex].push( search_string(klass.name) )
191
+ index[:longSearchIndex].push( search_string(klass.parent.name) )
192
+ index[:info].push([
193
+ klass.name,
194
+ klass.parent.full_name,
195
+ klass.path,
196
+ klass.module? ? '' : (klass.superclass ? " < #{String === klass.superclass ? klass.superclass : klass.superclass.full_name}" : ''),
197
+ snippet(klass.comment),
198
+ TYPE_CLASS
199
+ ])
200
+ end
201
+ end
202
+
203
+ ### Add methods to search +index+ array
204
+ def add_method_search_index(index)
205
+ debug_msg " generating method search index"
206
+
207
+ list = @classes.map { |klass|
208
+ klass.method_list
209
+ }.flatten.sort{ |a, b| a.name == b.name ? a.parent.full_name <=> b.parent.full_name : a.name <=> b.name }.select { |method|
210
+ method.document_self
211
+ }
212
+ unless @options.show_all
213
+ list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
214
+ end
215
+
216
+ list.each do |method|
217
+ index[:searchIndex].push( search_string(method.name) + '()' )
218
+ index[:longSearchIndex].push( search_string(method.parent.name) )
219
+ index[:info].push([
220
+ method.name,
221
+ method.parent.full_name,
222
+ method.path,
223
+ method.params,
224
+ snippet(method.comment),
225
+ TYPE_METHOD
226
+ ])
227
+ end
228
+ end
229
+
230
+ ### Generate a documentation file for each class
231
+ def generate_class_files
232
+ debug_msg "Generating class documentation in #@outputdir"
233
+ templatefile = @template_dir + 'class.rhtml'
234
+
235
+ @classes.each do |klass|
236
+ debug_msg " working on %s (%s)" % [ klass.full_name, klass.path ]
237
+ outfile = @outputdir + klass.path
238
+ rel_prefix = @outputdir.relative_path_from( outfile.dirname )
239
+
240
+ debug_msg " rendering #{outfile}"
241
+ self.render_template( templatefile, binding(), outfile )
242
+ end
243
+ end
244
+
245
+ ### Generate a documentation file for each file
246
+ def generate_file_files
247
+ debug_msg "Generating file documentation in #@outputdir"
248
+ templatefile = @template_dir + 'file.rhtml'
249
+
250
+ @files.each do |file|
251
+ outfile = @outputdir + file.path
252
+ debug_msg " working on %s (%s)" % [ file.full_name, outfile ]
253
+ rel_prefix = @outputdir.relative_path_from( outfile.dirname )
254
+
255
+ debug_msg " rendering #{outfile}"
256
+ self.render_template( templatefile, binding(), outfile )
257
+ end
258
+ end
259
+
260
+ def index_file
261
+ if @options.main_page && file = @files.find { |f| f.full_name == @options.main_page }
262
+ file
263
+ else
264
+ @files.first
265
+ end
266
+ end
267
+
268
+ ### Create index.html with frameset
269
+ def generate_index_file
270
+ debug_msg "Generating index file in #@outputdir"
271
+ templatefile = @template_dir + 'index.rhtml'
272
+ outfile = @outputdir + 'index.html'
273
+ index_path = index_file.path
274
+
275
+ self.render_template( templatefile, binding(), outfile )
276
+ end
277
+
278
+ ### Strip comments on a space after 100 chars
279
+ def snippet(str)
280
+ str ||= ''
281
+ if str =~ /^(?>\s*)[^\#]/
282
+ content = str
283
+ else
284
+ content = str.gsub(/^\s*(#+)\s*/, '')
285
+ end
286
+
287
+ content = content.sub(/^(.{100,}?)\s.*/m, "\\1").gsub(/\r?\n/m, ' ')
288
+
289
+ begin
290
+ content.to_json
291
+ rescue # might fail on non-unicode string
292
+ begin
293
+ content = Iconv.conv('latin1//ignore', "UTF8", content) # remove all non-unicode chars
294
+ content.to_json
295
+ rescue
296
+ content = '' # something hugely wrong happend
297
+ end
298
+ end
299
+ content
300
+ end
301
+
302
+ ### Build search index key
303
+ def search_string(string)
304
+ string ||= ''
305
+ string.downcase.gsub(/\s/,'')
306
+ end
307
+
308
+ ### Copy all the resource files to output dir
309
+ def copy_resources
310
+ resoureces_path = @template_dir + RESOURCES_DIR
311
+ debug_msg "Copying #{resoureces_path}/** to #{@outputdir}/**"
312
+ FileUtils.cp_r resoureces_path.to_s, @outputdir.to_s, :preserve => true unless $dryrun
313
+ end
314
+
315
+ class FilesTree
316
+ attr_reader :children
317
+ def add(path, url)
318
+ path = path.split(File::SEPARATOR) unless Array === path
319
+ @children ||= {}
320
+ if path.length == 1
321
+ @children[path.first] = url
322
+ else
323
+ @children[path.first] ||= FilesTree.new
324
+ @children[path.first].add(path[1, path.length], url)
325
+ end
326
+ end
327
+ end
328
+
329
+ def generate_file_tree
330
+ if @files.length > 1
331
+ @files_tree = FilesTree.new
332
+ @files.each do |file|
333
+ @files_tree.add(file.relative_name, file.path)
334
+ end
335
+ [['', '', 'files', generate_file_tree_level(@files_tree)]]
336
+ else
337
+ []
338
+ end
339
+ end
340
+
341
+ def generate_file_tree_level(tree)
342
+ tree.children.keys.sort.map do |name|
343
+ child = tree.children[name]
344
+ if String === child
345
+ [name, child, '', []]
346
+ else
347
+ ['', '', name, generate_file_tree_level(child)]
348
+ end
349
+ end
350
+ end
351
+ end
@@ -0,0 +1,51 @@
1
+ module Erlapi::Templatable
2
+ ### Load and render the erb template in the given +templatefile+ within the
3
+ ### specified +context+ (a Binding object) and return output
4
+ ### Both +templatefile+ and +outfile+ should be Pathname-like objects.
5
+ def eval_template(templatefile, context)
6
+ template_src = templatefile.read
7
+ template = ERB.new( template_src, nil, '<>' )
8
+ template.filename = templatefile.to_s
9
+
10
+ begin
11
+ template.result( context )
12
+ rescue NoMethodError => err
13
+ raise StandardError, "Error while evaluating %s: %s (at %p)" % [
14
+ templatefile.to_s,
15
+ err.message,
16
+ eval( "_erbout[-50,50]", context )
17
+ ], err.backtrace
18
+ end
19
+ end
20
+
21
+ ### Load and render the erb template with the given +template_name+ within
22
+ ### current context. Adds all +local_assigns+ to context
23
+ def include_template(template_name, local_assigns = {})
24
+ source = local_assigns.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join
25
+ eval("#{source};templatefile = Erlapi::Generator::TEMPLATE_DIR + template_name;eval_template(templatefile, binding)")
26
+ end
27
+
28
+ ### Load and render the erb template in the given +templatefile+ within the
29
+ ### specified +context+ (a Binding object) and write it out to +outfile+.
30
+ ### Both +templatefile+ and +outfile+ should be Pathname-like objects.
31
+ def render_template( templatefile, context, outfile )
32
+ output = eval_template(templatefile, context)
33
+
34
+ # TODO delete this dirty hack when documentation for example for GeneratorMethods will not be cutted off by <script> tag
35
+ begin
36
+ if output.respond_to? :force_encoding
37
+ encoding = output.encoding
38
+ output = output.force_encoding('ASCII-8BIT').gsub('<script>', '&lt;script;&gt;').force_encoding(encoding)
39
+ else
40
+ output = output.gsub('<script>', '&lt;script&gt;')
41
+ end
42
+ rescue Exception => e
43
+
44
+ end
45
+
46
+ outfile.dirname.mkpath
47
+ outfile.open( 'w', 0644 ) do |file|
48
+ file.print( output )
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,172 @@
1
+ <div id="content">
2
+ <% unless (desc = context.description).empty? %>
3
+ <div class="description">
4
+ <%= desc %>
5
+ </div>
6
+ <% end %>
7
+
8
+ <% unless context.requires.empty? %>
9
+ <div class="sectiontitle">Required Files</div>
10
+ <ul>
11
+ <% context.requires.each do |req| %>
12
+ <li><%= h req.name %></li>
13
+ <% end %>
14
+ </ul>
15
+ <% end %>
16
+
17
+ <% sections = context.sections.select { |section| section.title } %>
18
+ <% unless sections.empty? %>
19
+ <div class="sectiontitle">Contents</div>
20
+ <ul>
21
+ <% sections.each do |section| %>
22
+ <li><a href="#<%= section.sequence %>"><%= h section.title %></a></li>
23
+ <% end %>
24
+ </ul>
25
+ <% end %>
26
+
27
+ <%
28
+ list = context.method_list
29
+ unless @options.show_all
30
+ list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
31
+ end
32
+ %>
33
+ <% unless list.empty? %>
34
+ <div class="sectiontitle">Methods</div>
35
+ <dl class="methods">
36
+ <% each_letter_group(list) do |group| %>
37
+ <dt><%= group[:name] %></dt>
38
+ <dd>
39
+ <ul>
40
+ <% group[:methods].each_with_index do |method, i| %>
41
+ <li><a href="#<%= method.aref %>"><%= method.name %></a><%= ',' unless group[:methods].size == i+1 %></li>
42
+ <% end %>
43
+ </ul>
44
+ </dd>
45
+ <% end %>
46
+ </dl>
47
+ <% end %>
48
+
49
+ <% unless context.includes.empty? %>
50
+ <div class="sectiontitle">Included Modules</div>
51
+ <ul>
52
+ <% context.includes.each do |inc| %>
53
+ <li>
54
+ <% unless String === inc.module %>
55
+ <a href="<%= context.aref_to inc.module.path %>"><%= h inc.module.full_name %></a>
56
+ <% else %>
57
+ <span><%= h inc.name %></span>
58
+ <% end %>
59
+ START:includes
60
+ </li>
61
+ <% end %>
62
+ </ul>
63
+ <% end %>
64
+
65
+ <% sections.each do |section| %>
66
+ <div class="sectiontitle"><a name="<%= h section.sequence %>"><%= h section.title %></a></div>
67
+ <% unless (description = section.description).empty? %>
68
+ <div class="description">
69
+ <%= description %>
70
+ </div>
71
+ <% end %>
72
+ <% end %>
73
+
74
+ <% unless context.classes_and_modules.empty? %>
75
+ <div class="sectiontitle">Classes and Modules</div>
76
+ <ul>
77
+ <% (context.modules.sort + context.classes.sort).each do |mod| %>
78
+ <li><span class="type"><%= mod.type.upcase %></span> <a href="<%= context.aref_to mod.path %>"><%= mod.full_name %></a></li>
79
+ <% end %>
80
+ </ul>
81
+ <% end %>
82
+
83
+ <% unless context.constants.empty? %>
84
+ <div class="sectiontitle">Constants</div>
85
+ <table border='0' cellpadding='5'>
86
+ <% context.each_constant do |const| %>
87
+ <tr valign='top'>
88
+ <td class="attr-name"><%= h const.name %></td>
89
+ <td>=</td>
90
+ <td class="attr-value"><%= h const.value %></td>
91
+ </tr>
92
+ <% unless (description = const.description).empty? %>
93
+ <tr valign='top'>
94
+ <td>&nbsp;</td>
95
+ <td colspan="2" class="attr-desc"><%= description %></td>
96
+ </tr>
97
+ <% end %>
98
+ <% end %>
99
+ </table>
100
+ <% end %>
101
+
102
+ <% unless context.attributes.empty? %>
103
+ <div class="sectiontitle">Attributes</div>
104
+ <table border='0' cellpadding='5'>
105
+ <% context.each_attribute do |attrib| %>
106
+ <tr valign='top'>
107
+ <td class='attr-rw'>
108
+ [<%= attrib.rw %>]
109
+ </td>
110
+ <td class='attr-name'><%= h attrib.name %></td>
111
+ <td class='attr-desc'><%= attrib.description.strip %></td>
112
+ </tr>
113
+ <% end %>
114
+ </table>
115
+ <% end %>
116
+
117
+ <% context.methods_by_type.each do |type, visibilities|
118
+ next if visibilities.empty?
119
+ visibilities.each do |visibility, methods|
120
+ next if methods.empty?
121
+ next unless @options.show_all || visibility == :public || visibility == :protected || methods.any? {|m| m.force_documentation }
122
+ %>
123
+ <div class="sectiontitle"><%= type.capitalize %> <%= visibility.to_s.capitalize %> methods</div>
124
+ <% methods.each do |method| %>
125
+ <div class="method">
126
+ <div class="title" id="<%= method.aref %>">
127
+ <% if method.call_seq %>
128
+ <a name="<%= method.aref %>"></a><b><%= method.call_seq.gsub(/->/, '&rarr;') %></b>
129
+ <% else %>
130
+ <a name="<%= method.aref %>"></a><b><%= h method.name %></b><%= h method.params %>
131
+ <% end %>
132
+ </div>
133
+ <% unless (description = method.description).empty? %>
134
+ <div class="description">
135
+ <%= description %>
136
+ </div>
137
+ <% end %>
138
+ <% unless method.aliases.empty? %>
139
+ <div class="aka">
140
+ This method is also aliased as
141
+ <% method.aliases.each do |aka| %>
142
+ <a href="<%= context.aref_to aka.path %>"><%= h aka.name %></a>
143
+ <% end %>
144
+ </div>
145
+ <% end %>
146
+ <% if method.token_stream %>
147
+ <% markup = method.markup_code %>
148
+ <div class="sourcecode">
149
+ <p class="source-link">
150
+ Source: <a href="javascript:toggleSource('<%= method.aref %>_source')" id="l_<%= method.aref %>_source">show</a>
151
+ <%
152
+ if markup =~ /File\s(\S+), line (\d+)/
153
+ path = $1
154
+ line = $2.to_i
155
+ end
156
+ github = github_url(path)
157
+ if github
158
+ %>
159
+ | <a href="<%= "#{github}#L#{line}" %>" target="_blank" class="github_url">on GitHub</a>
160
+ <% end %>
161
+ </p>
162
+ <div id="<%= method.aref %>_source" class="dyn-source">
163
+ <pre><%= method.markup_code %></pre>
164
+ </div>
165
+ </div>
166
+ <% end %>
167
+ </div>
168
+ <% end
169
+ end
170
+ end
171
+ %>
172
+ </div>