jeffreyhunter77-R2Doc 0.1

Sign up to get free protection for your applications and to get access to all the features.
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,7 @@
1
+ # This file is intentionally blank.
2
+ #
3
+ # It exists as an easy mechanism to set up the document generator for use
4
+ # under RDoc v1.0.1 (e.g. +require 'r2doc'+). The only work that
5
+ # actually needs to be done is to include this directory in +$:+. That's
6
+ # done automatically by gem when this file is required. The remaining
7
+ # code is loaded by rdoc itself when it's run.
@@ -0,0 +1,237 @@
1
+ # Various extensions to the context classes made available to templates
2
+
3
+ module R2Doc
4
+
5
+ # Extensions for the RDoc::Generator::Context / Generators::ContextUser
6
+ # class
7
+ module ContextExtensions
8
+ # Numeric value associated with visibility values for sorting
9
+ VISIBILITY_VALUE = { :public=>0, :protected=>1, :private=>2 }
10
+
11
+ # Return the parent ContextUser of this object
12
+ def parent
13
+ p = (@context.parent.nil? || (@context == @context.parent)) ? nil : R2Doc.all_references[parent_name]
14
+ # guard against pollution of all_references with methods having conflicting names
15
+ (p.respond_to?(:is_method_context?) && p.is_method_context?) ? nil : p
16
+ end
17
+
18
+ # Return an array representing the navigational path to this class in
19
+ # the namespace hierarchy. The first item in the array is the
20
+ # outermost class or module. The class itself is not included in the
21
+ # array, nor is the root of the namespace. So, for a class
22
+ # A::B::C::D, the returned array will contain the A module, the B
23
+ # module, and the C module, in that order. All items in the array are
24
+ # instances of ContextUser
25
+ def name_path_to_parent
26
+ path = []
27
+ p = parent
28
+ while p do
29
+ path.unshift p
30
+ p = p.parent
31
+ end
32
+ path
33
+ end
34
+
35
+ # Return the description markup for this context
36
+ def description(temporaryPath = nil)
37
+ oldPath = self.path if (self.respond_to?(:path) && (!temporaryPath.nil?))
38
+ self.format_path = temporaryPath unless temporaryPath.nil?
39
+ d = markup(@context.comment)
40
+ self.format_path = oldPath if (self.respond_to?(:path) && (!temporaryPath.nil?))
41
+ d
42
+ end
43
+
44
+ # Return a list of Hashes for all constants containing the following keys:
45
+ # [<tt>:name</tt>] The constant name
46
+ # [<tt>:value</tt>] The value of the constant
47
+ # [<tt>:description</tt>] Constant description markup
48
+ def constants
49
+ @context.constants.sort{|a,b| a.name<=>b.name}.collect{|c| {:name=>c.name, :value=>c.value, :description=>markup(c.comment, true)}}
50
+ end
51
+
52
+ # Returns true if the context contains contants
53
+ def has_constants?
54
+ @context.constants.length > 0
55
+ end
56
+
57
+ # Return a list of Hashes for all aliases containing the following keys:
58
+ # [<tt>:old_name</tt>] The old name
59
+ # [<tt>:new_name</tt>] The new name
60
+ # [<tt>:description</tt>] Alias description markup
61
+ def aliases
62
+ @context.aliases.sort{|a,b| a.old_name<=>b.old_name}.collect{|al| {:old_name=>al.old_name, :new_name=>al.new_name, :description=>markup(al.comment, true)}}
63
+ end
64
+
65
+ # Return true if this context contains aliases
66
+ def has_aliases?
67
+ @context.aliases.length > 0
68
+ end
69
+
70
+ # Return a list of Hashes for all documentable attributes containing the following keys:
71
+ # [<tt>:name</tt>] The attribute name
72
+ # [<tt>:visibility</tt>] <tt>:public</tt>, <tt>:protected</tt>, or <tt>:private</tt>
73
+ # [<tt>:rw</tt>] <tt>'r'</tt> or <tt>'rw'</tt>
74
+ # [<tt>:description</tt>] Attribute description markup
75
+ def attributes
76
+ attrs = sort_members(@context.attributes).find_all{|a| @options.show_all || a.visibility == :public || a.visibility == :protected}
77
+ attrs.collect{|a| {:name=>a.name, :visibility=>a.visibility, :rw=>a.rw, :description=>markup(a.comment, true)}}
78
+ end
79
+
80
+ # Return true if this context contains attributes
81
+ def has_attributes?
82
+ a = @context.attributes.find{|a| @options.show_all || a.visibility == :public || a.visibility == :protected}
83
+ a ? true : false
84
+ end
85
+
86
+ # Returns a collection of HtmlMethod objects for all methods in this context
87
+ def all_methods
88
+ collect_methods unless @methods
89
+ @all_methods = sort_members(@methods) unless @all_methods
90
+ @all_methods
91
+ end
92
+
93
+ # Return a list of Hashes for all documentable class methods containing the following keys:
94
+ # [<tt>:name</tt>] The method name
95
+ # [<tt>:visibility</tt>] <tt>:public:</tt>, <tt>:protected</tt>, or <tt>:private</tt>
96
+ # [<tt>:params</tt>] Method call signature markup (does not include method name)
97
+ # [<tt>:callseq</tt>] Markup documenting alternative ways to call the method (should take precedence over name and params when present)
98
+ # [<tt>:url</tt>] The relative URL to the method from the documentation root (e.g. <tt>'classes/Foo.html#bar'</tt>)
99
+ # [<tt>:anchor</tt>] The name of the anchor for this method (e.g. <tt>'bar'</tt>)
100
+ # [<tt>:description</tt>] Method description markup
101
+ def class_methods
102
+ all_methods().find_all{|m| m.singleton && (@options.show_all || m.visibility == :public || m.visibility == :protected)}.collect{|m| method_hash(m)}
103
+ end
104
+
105
+ # Returns true if the context contains class (singleton) methods
106
+ def has_class_methods?
107
+ m = all_methods().find{|m| m.singleton && (@options.show_all || m.visibility == :public || m.visibility == :protected)}
108
+ m ? true : false
109
+ end
110
+
111
+ # Return a list of Hashes for all documentable instance methods. See class_methods for Hash key information.
112
+ def instance_methods
113
+ all_methods().find_all{|m| (!m.singleton) && (@options.show_all || m.visibility == :public || m.visibility == :protected)}.collect{|m| method_hash(m)}
114
+ end
115
+
116
+ # Returns true if the context contains instance (non-singleton) methods
117
+ def has_instance_methods?
118
+ m = all_methods().find{|m| (!m.singleton) && (@options.show_all || m.visibility == :public || m.visibility == :protected)}
119
+ m ? true : false
120
+ end
121
+
122
+ # The collection of modules contained within this context
123
+ def modules
124
+ return @modules if @modules
125
+ @modules = @context.modules.sort.find_all{|m| m.document_self}.collect{|m| R2Doc.all_references[m.full_name]}
126
+ end
127
+
128
+ # The collection of classes contained within this context
129
+ def classes
130
+ return @classes if @classes
131
+ @classes = @context.classes.sort.find_all{|c| c.document_self}.collect{|c| R2Doc.all_references[c.full_name]}
132
+ end
133
+
134
+ # Returns true if this context contains classes
135
+ def has_classes?
136
+ c = @context.classes.find{|c| c.document_self}
137
+ c ? true : false
138
+ end
139
+
140
+ # Returns true if this context contains modules
141
+ def has_modules?
142
+ m = @context.modules.find{|m| m.document_self}
143
+ m ? true : false
144
+ end
145
+
146
+ # Returns true if this context contains classes or modules
147
+ def has_classes_or_modules?
148
+ has_classes? || has_modules?
149
+ end
150
+
151
+ # Returns true if this context has included modules
152
+ def has_includes?
153
+ @context.includes.length > 0
154
+ end
155
+
156
+ # The collection of included modules. This returns a hash with the folliwing keys for each module:
157
+ # [<tt>:name</tt>] The module name
158
+ # [<tt>:url</tt>] The relative URL to the module from the documentation root
159
+ def includes
160
+ return @includes if @includes
161
+ @includes = []
162
+ @context.includes.each do |i|
163
+ ref = R2Doc.all_references[i.name]
164
+ ref = @context.find_symbol(i.name)
165
+ ref = ref.viewer if ref
166
+ if ref and ref.document_self
167
+ @includes << {:name=>i.name, :url=>ref.path}
168
+ else
169
+ @includes << {:name=>i.name}
170
+ end
171
+ end
172
+ @includes
173
+ end
174
+
175
+ # Returns true if this object is a method context
176
+ def is_method_context?
177
+ false
178
+ end
179
+
180
+ protected
181
+
182
+ # Sort members by visibility, then name
183
+ def sort_members(members)
184
+ members.sort do |a,b|
185
+ avis = VISIBILITY_VALUE[a.visibility]
186
+ bvis = VISIBILITY_VALUE[b.visibility]
187
+ (avis == bvis) ? a.name <=> b.name : avis <=> bvis
188
+ end
189
+ end
190
+
191
+ # Assembles a Hash for an HTMLMethod, +m+. This is used by class_methods and instance_methods.
192
+ def method_hash(m)
193
+ hash = {:name=>m.name, :visibility=>m.visibility, :params=>m.params, :url=>"#{path}\##{m.aref}", :anchor=>m.aref, :description=>m.description.strip}
194
+ hash[:callseq] = m.call_seq.gsub(/->/, '&rarr;') if m.call_seq
195
+ hash
196
+ end
197
+ end
198
+
199
+
200
+ # Extensions for the RDoc::Generator::Class / Generators::HtmlClass
201
+ # class
202
+ module ClassExtensions
203
+ # Return the HtmlClass for the super class, or the class name if undocumented
204
+ def superclass
205
+ lookup = (parent_name) ? "#{parent_name}::#{context_superclass}" : context_superclass
206
+ s = R2Doc.all_references[lookup] || R2Doc.all_references[context_superclass] || context_superclass
207
+ # in some cases conflicting method names can pollute AllReferences
208
+ s = s.name if (s.respond_to?(:is_method_context?) && s.is_method_context?)
209
+ s == self ? nil : s
210
+ end
211
+
212
+ # Return the shorter, unqualified name of the class
213
+ def short_name
214
+ @context.name
215
+ end
216
+
217
+ protected
218
+
219
+ # Returns nil instead of an error if superclass is called for a module
220
+ def context_superclass
221
+ @context.is_module? ? nil : @context.superclass
222
+ end
223
+
224
+ end
225
+
226
+
227
+
228
+ # Extensions for the RDoc::Generator::Method / Generators::HtmlMethod
229
+ # class
230
+ module MethodExtensions
231
+ # Returns true if this object is a method context
232
+ def is_method_context?
233
+ true
234
+ end
235
+ end
236
+
237
+ end
@@ -0,0 +1,11 @@
1
+ module R2Doc
2
+ # R2Doc engine for ERB templates
3
+ class ERBTemplateEngine
4
+ # Load a template
5
+ def self.load(filename)
6
+ ERB.new(File.open(filename) {|f| f.read})
7
+ end
8
+ end
9
+ end
10
+
11
+ R2Doc::TemplateManager.register_engine('erb', R2Doc::ERBTemplateEngine)
@@ -0,0 +1,123 @@
1
+ module R2Doc
2
+ # Custom generator
3
+ module Generator
4
+ # generate the docs
5
+ def generate(toplevels)
6
+ @toplevels = toplevels
7
+ @files = []
8
+ @classes = []
9
+ @hyperlinks = {}
10
+ @topmodules = []
11
+ @topclasses = []
12
+
13
+ generate_prep # hook for version-specific initalization
14
+
15
+ build_indices
16
+ generate_html
17
+ copy_static_files
18
+ end
19
+
20
+ protected
21
+
22
+ # load the template files
23
+ def load_html_template
24
+ ['class', 'file', 'rdoc'].each do |name|
25
+ R2Doc::TemplateManager.load_template("#{template_name}/#{name}")
26
+ end
27
+ end
28
+
29
+ # build indices of our objects
30
+ def build_indices
31
+ @toplevels.each do |toplevel|
32
+ @files << create_file_context(toplevel, @options)
33
+ end
34
+
35
+ get_toplevels.all_classes_and_modules.each do |cls|
36
+ build_class_list(cls, @files[0])
37
+ end
38
+
39
+ @classes.each do |c|
40
+ if c.parent.nil?
41
+ if c.context.is_module?
42
+ @topmodules << c
43
+ else
44
+ @topclasses << c
45
+ end
46
+ end
47
+ end
48
+ @topmodules.sort!
49
+ @topclasses.sort!
50
+ end
51
+
52
+ # Build a class list from a top-level class
53
+ def build_class_list(from, html_file)
54
+ @classes << create_class_context(from, html_file, @options)
55
+ from.each_classmodule do |mod|
56
+ build_class_list(mod, html_file)
57
+ end
58
+ end
59
+
60
+ # Outputs the html
61
+ def generate_html
62
+ @classes.each {|klass| render klass.path, :class, binding }
63
+ @files.each {|file| render file.path, :file, binding }
64
+ render 'rdoc.js', :rdoc
65
+ generate_index
66
+ end
67
+
68
+ # Generate an index file
69
+ def generate_index
70
+ # determine what to put in the index
71
+ ref = (@options.main_page && R2Doc.all_references[@options.main_page]) ?
72
+ R2Doc.all_references[@options.main_page] : nil
73
+ ref = ref.nil? ? @files.find{|f| f.document_self} : ref
74
+
75
+ # create the index
76
+ file = ref
77
+ render 'index.html', :index, binding
78
+ end
79
+
80
+ # Run a template and output the contents
81
+ def render(filename, template, b = nil)
82
+ @current_path = filename
83
+ File.makedirs(File.dirname(filename))
84
+ t = R2Doc::TemplateManager.load_template("#{template_name}/#{template.to_s}")
85
+ b = b.nil? ? binding : b
86
+
87
+ File.open(filename, 'w') {|f| f.write t.result(b)}
88
+ end
89
+
90
+
91
+ # build the static file list
92
+ def build_static_file_list
93
+ @static_files = {}
94
+ R2Doc::TemplateManager.template_directories.collect {|d|
95
+ "#{File.expand_path(d)}/#{template_name}"}.find_all{|d|
96
+ File.directory?(d)
97
+ }.each{|d| add_to_static_file_list d}
98
+ end
99
+
100
+ # recursively add a directory's contents to the static file list
101
+ def add_to_static_file_list(dir, relpath = '')
102
+ Dir.entries(File.join(dir, relpath)).each do |entry|
103
+ unless entry.match(/^\..?$/) || R2Doc::TemplateManager.is_registered_extension?(R2Doc::TemplateManager.file_extension(entry))
104
+ partial = relpath.empty? ? entry : File.join(relpath, entry)
105
+ full = File.join(dir, partial)
106
+ if File.directory?(full)
107
+ add_to_static_file_list dir, partial
108
+ else
109
+ @static_files[full] = partial
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ # copy any static files needed by the template
116
+ def copy_static_files
117
+ @static_files.each{|full,partial|
118
+ File.makedirs(File.dirname(partial))
119
+ File.copy(full, partial)
120
+ }
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,112 @@
1
+
2
+ require 'ftools'
3
+
4
+ require 'rdoc/rdoc'
5
+ require 'rdoc/generator/html'
6
+
7
+ require 'erb'
8
+
9
+ require 'r2doc/context_extensions'
10
+ require 'r2doc/template'
11
+ require 'r2doc/template_util'
12
+ require 'r2doc/generator'
13
+ require 'r2doc/erb_template_engine'
14
+
15
+ RDoc::Generator::Context.class_eval do
16
+ include R2Doc::ContextExtensions
17
+ end
18
+
19
+ RDoc::Generator::Class.class_eval do
20
+ include R2Doc::ClassExtensions
21
+ end
22
+
23
+ RDoc::Generator::Method.class_eval do
24
+ include R2Doc::MethodExtensions
25
+ end
26
+
27
+
28
+ module R2Doc
29
+ # Accessor for the AllReferences class
30
+ def self.all_references
31
+ RDoc::Generator::AllReferences
32
+ end
33
+ end
34
+
35
+ module RDoc
36
+
37
+ class ClassModule
38
+ # Retain support for old-style is_module? call
39
+ def is_module?
40
+ module?
41
+ end
42
+ end
43
+
44
+ module Generator
45
+
46
+ class Context #:nodoc:
47
+ protected
48
+ def format_path=(new_path)
49
+ @formatter = ::RDoc::Markup::ToHtmlCrossref.new(new_path, self, @options.show_hash)
50
+ end
51
+ end
52
+
53
+ class Method #:nodoc:
54
+ def create_source_code_file(code_body)
55
+ end
56
+ end
57
+
58
+ # R2Doc generator for RDoc v2
59
+ class R2DOC < HTML
60
+
61
+ RDoc.add_generator self
62
+
63
+ include ERB::Util
64
+ include R2Doc::TemplateUtil
65
+ include R2Doc::Generator
66
+
67
+ # Factory method
68
+ def R2DOC.for(options)
69
+ R2DOC.new(options)
70
+ end
71
+
72
+ # Constructor
73
+ def initialize(*args)
74
+ super
75
+ build_static_file_list
76
+ end
77
+
78
+ # Perform version-specific initialization
79
+ def generate_prep
80
+ @template_cache = Cache.instance
81
+ end
82
+
83
+ # Return the name of the template
84
+ def template_name
85
+ @options.template || 'r2doc'
86
+ end
87
+
88
+ # Return the list of top level objects for this RDoc version
89
+ def get_toplevels
90
+ TopLevel
91
+ end
92
+
93
+ # Create a new file object for this RDoc version
94
+ def create_file_context(context, options)
95
+ File.new(@template_cache, context, options, FILE_DIR)
96
+ end
97
+
98
+ # Create a new class object for this RDoc version
99
+ def create_class_context(context, file, options)
100
+ Class.new(@template_cache, context, file, CLASS_DIR, options)
101
+ end
102
+
103
+ # Return a list of all defined methods
104
+ def complete_method_list
105
+ Method.all_methods
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end