hanna 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,102 @@
1
+ # Hanna — a better RDoc template
2
+
3
+ Hanna is an RDoc template that scales. It's implemented in Haml, making the sources clean
4
+ and readable. It's built with simplicity, beauty and ease of browsing in mind. (See more
5
+ in [the wiki][wiki].)
6
+
7
+ Hanna gem is available from [Gemcutter][]:
8
+
9
+ gem install hanna
10
+
11
+ The template was created by [Mislav][] and since then has seen contributions from:
12
+
13
+ 1. [Tony Strauss](http://github.com/DesigningPatterns), who participated from the early
14
+ start and made tons of fixes and enhancements to the template;
15
+ 2. [Hongli Lai](http://blog.phusion.nl/) with the search filter for methods.
16
+
17
+
18
+ ## Usage
19
+
20
+ There is a command-line tool installed with the Hanna gem:
21
+
22
+ hanna -h
23
+
24
+ This is a wrapper over `rdoc` and it forwards all the parameters to it. Manual usage
25
+ would require specifying Hanna as a template when invoking RDoc on the command-line:
26
+
27
+ rdoc -o doc --inline-source --format=html -T hanna lib/*.rb
28
+
29
+ Hanna requires the `--inline-source` (or `-S`) flag.
30
+
31
+ An alternative is to set the `RDOCOPT` environment variable:
32
+
33
+ RDOCOPT="-S -f html -T hanna"
34
+
35
+ This will make RDoc always use Hanna unless it is explicitly overridden.
36
+
37
+ Another neat trick is to put the following line in your .gemrc:
38
+
39
+ rdoc: --inline-source --line-numbers --format=html --template=hanna
40
+
41
+ This will make RubyGems use Hanna when generating documentation for installed gems.
42
+
43
+ ### Rake task
44
+
45
+ For repeated generation of API docs, it's better to set up a Rake task. If you already
46
+ have an `RDocTask` set up in your Rakefile, the only thing you need to change is this:
47
+
48
+ # replace this:
49
+ require 'rake/rdoctask'
50
+ # with this:
51
+ require 'hanna/rdoctask'
52
+
53
+ Tip: you can do this in the Rakefile of your Rails project before running `rake doc:rails`.
54
+
55
+ Here is an example of a task for the [will_paginate library][wp]:
56
+
57
+ # instead of 'rake/rdoctask':
58
+ require 'hanna/rdoctask'
59
+
60
+ desc 'Generate RDoc documentation for the will_paginate plugin.'
61
+ Rake::RDocTask.new(:rdoc) do |rdoc|
62
+ rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'CHANGELOG').
63
+ include('lib/**/*.rb').
64
+ exclude('lib/will_paginate/named_scope*').
65
+ exclude('lib/will_paginate/array.rb').
66
+ exclude('lib/will_paginate/version.rb')
67
+
68
+ rdoc.main = "README.rdoc" # page to start on
69
+ rdoc.title = "will_paginate documentation"
70
+
71
+ rdoc.rdoc_dir = 'doc' # rdoc output folder
72
+ rdoc.options << '--webcvs=http://github.com/mislav/will_paginate/tree/master/'
73
+ end
74
+
75
+ ### Generating documentation for installed gems
76
+
77
+ You can generate documentation for installed gems, which might be more convenient than the
78
+ `gem rdoc` command with the +RDOCOPT+ environment variable set as described. For instance,
79
+ to generate docs for "actionpack" and "activerecord" type:
80
+
81
+ [sudo] hanna --gems actionpack activerecord
82
+
83
+
84
+ ## You can help
85
+
86
+ Don't like something? Think you can design better? (You probably can.)
87
+
88
+ I think of Hanna as the first RDoc template that's actually _maintainable_. First thing I
89
+ have done is converted the original HTML template to Haml and Sass, cleaning up and
90
+ removing the (ridiculous amount of) duplication. Also, the template fragments are now in
91
+ _separate files_.
92
+
93
+ Ultimately, I'd like to lose the frameset. Currently that is far from possible because the
94
+ whole RDoc HTML Generator is built for frames. Still, that is my goal.
95
+
96
+ This is git. Fork it, hack away, tell me about it!
97
+
98
+
99
+ [wiki]: http://github.com/mislav/hanna/wikis/home "Hanna wiki"
100
+ [gemcutter]: http://gemcutter.org/ "Gemcutter gem server"
101
+ [wp]: http://github.com/mislav/will_paginate/tree/master/Rakefile
102
+ [Mislav]: http://mislav.caboo.se/ "Mislav Marohnić"
@@ -0,0 +1,4 @@
1
+ desc "builds the gem"
2
+ task :gem do
3
+ system %(gem build hanna.gemspec)
4
+ end
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/ruby
2
+ if ARGV.size == 1 and ARGV.first == '-h'
3
+ puts <<-HELP
4
+ Hanna -- a better RDoc template
5
+ Synopsis:
6
+ hanna [options] [file names...]
7
+ [sudo] hanna --gems [gem names...]
8
+
9
+ Example usage:
10
+
11
+ hanna lib/**/*.rb
12
+
13
+ Hanna passes all arguments to RDoc. To find more about RDoc options, see
14
+ "rdoc -h". Default options are:
15
+
16
+ -o doc --inline-source --charset=UTF-8
17
+
18
+ The second form, with the "--gems" argument, serves the same purpose as
19
+ the "gem rdoc" command: it generates documentation for installed gems.
20
+ When no gem names are given, "hanna --gems" will install docs for EACH of
21
+ the gems, which can, uh, take a little while.
22
+
23
+ HELP
24
+ exit 0
25
+ end
26
+
27
+ unless RUBY_PLATFORM =~ /(:?mswin|mingw)/
28
+ require 'pathname'
29
+ hanna_dir = Pathname.new(__FILE__).realpath.dirname + '../lib'
30
+ else
31
+ # windows
32
+ hanna_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
33
+ end
34
+
35
+ $:.unshift(hanna_dir) unless $:.include?(hanna_dir)
36
+
37
+ require 'rubygems'
38
+ require 'hanna/version'
39
+ Hanna::require_rdoc
40
+ require 'rdoc/rdoc'
41
+
42
+ options = []
43
+
44
+ options << '-f' << 'html' << '-T' << 'hanna'
45
+ options << '--inline-source' << '--charset=UTF-8'
46
+
47
+ if ARGV.first == '--gems'
48
+ require 'rubygems/doc_manager'
49
+ Gem::DocManager.configured_args = options
50
+
51
+ gem_names = ARGV.dup
52
+ gem_names.shift
53
+
54
+ unless gem_names.empty?
55
+ specs = gem_names.inject([]) do |arr, name|
56
+ found = Gem::SourceIndex.from_installed_gems.find_name(name)
57
+ spec = found.sort_by {|s| s.version }.last
58
+ arr << spec if spec
59
+ arr
60
+ end
61
+ else
62
+ specs = Gem::SourceIndex.from_installed_gems.inject({}) do |all, pair|
63
+ full_name, spec = pair
64
+ if spec.has_rdoc? and (!all[spec.name] or spec.version > all[spec.name].version)
65
+ all[spec.name] = spec
66
+ end
67
+ all
68
+ end
69
+ specs = specs.values
70
+ puts "Hanna is installing documentation for #{specs.size} gem#{specs.size > 1 ? 's' : ''} ..."
71
+ end
72
+
73
+ specs.each do |spec|
74
+ Gem::DocManager.new(spec).generate_rdoc
75
+ end
76
+ else
77
+ options << '-o' << 'doc' unless ARGV.include?('-o') or ARGV.include?('--op')
78
+ options.concat ARGV
79
+
80
+ RDoc::RDoc.new.document(options)
81
+ end
@@ -0,0 +1 @@
1
+ require 'hanna/hanna'
@@ -0,0 +1,48 @@
1
+ # = A better RDoc HTML template
2
+ #
3
+ # Authors: Mislav Marohnić <mislav.marohnic@gmail.com>
4
+ # Tony Strauss (http://github.com/DesigningPatterns)
5
+ # Michael Granger <ged@FaerieMUD.org>, who had maintained the original RDoc template
6
+
7
+ require 'haml'
8
+ require 'sass'
9
+ require 'rdoc/generator/html'
10
+ require 'hanna/template_page_patch'
11
+
12
+ module RDoc::Generator::HTML::HANNA
13
+ class << self
14
+ def dir
15
+ @dir ||= File.join File.dirname(__FILE__), 'template_files'
16
+ end
17
+
18
+ def read(*names)
19
+ content = names.inject('') { |all, name| all << File.read(File.join(dir, name)) }
20
+ extension = names.first =~ /\.(\w+)$/ && $1
21
+
22
+ Hanna::TemplateHelpers.silence_warnings do
23
+ case extension
24
+ when 'sass'
25
+ Sass::Engine.new(content)
26
+ when 'haml'
27
+ Haml::Engine.new(content, :format => :html4, :filename => names.join(','))
28
+ else
29
+ content
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ STYLE = read('styles.sass')
36
+
37
+ CLASS_PAGE = read('page.haml')
38
+ FILE_PAGE = CLASS_PAGE
39
+ METHOD_LIST = read('method_list.haml', 'sections.haml')
40
+
41
+ FR_INDEX_BODY = BODY = read('layout.haml')
42
+
43
+ FILE_INDEX = read('file_index.haml')
44
+ CLASS_INDEX = read('class_index.haml')
45
+ METHOD_INDEX = read('method_index.haml')
46
+
47
+ INDEX = read('index.haml')
48
+ end
@@ -0,0 +1,42 @@
1
+ require 'hanna/version'
2
+ require 'rake'
3
+ require 'rake/rdoctask'
4
+
5
+ Rake::RDocTask.class_eval do
6
+ # don't allow it
7
+ undef :external=, :template=
8
+
9
+ # Create the tasks defined by this task lib.
10
+ def define
11
+ @template = 'hanna'
12
+ options << '--format=html'
13
+
14
+ # inline source and UTF-8 are defaults:
15
+ options << '--inline-source' unless options.include? '--inline-source' or options.include? '-S'
16
+ options << '--charset=UTF-8' if options.grep(/^(--charset\b|-c\b)/).empty?
17
+
18
+ desc "Build the HTML documentation"
19
+ task name
20
+
21
+ desc "Force a rebuild of the RDOC files"
22
+ task paste("re", name) => [paste("clobber_", name), name]
23
+
24
+ desc "Remove rdoc products"
25
+ task paste("clobber_", name) do
26
+ rm_r rdoc_dir rescue nil
27
+ end
28
+
29
+ task :clobber => [paste("clobber_", name)]
30
+
31
+ directory @rdoc_dir
32
+ task name => [rdoc_target]
33
+ file rdoc_target => @rdoc_files + [Rake.application.rakefile] do
34
+ rm_r @rdoc_dir rescue nil
35
+ Hanna::require_rdoc
36
+ require 'rdoc/rdoc'
37
+
38
+ RDoc::RDoc.new.document(option_list + @rdoc_files)
39
+ end
40
+ return self
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ %h1= values[:list_title]
2
+ %ol#index-entries.classes
3
+ = render_class_tree make_class_tree(values[:entries])
@@ -0,0 +1,12 @@
1
+ %h1= values[:list_title]
2
+ - any_hidden = false
3
+
4
+ %ol#index-entries{ :class => 'files' }
5
+ - for entry in values[:entries]
6
+ - hide = entry[:name] =~ /\.rb$/
7
+ - any_hidden = true if hide
8
+ %li{ :class => hide ? 'other' : nil }= link_to entry[:name], entry[:href]
9
+
10
+ - if any_hidden
11
+ %li
12
+ %a.show{ :href => '#', :onclick => 'this.parentNode.parentNode.className += " expanded"; this.parentNode.removeChild(this); return false' } show all
@@ -0,0 +1,11 @@
1
+ !!! Frameset
2
+ %html{ "xml:lang" => "en", :lang => "en", :xmlns => "http://www.w3.org/1999/xhtml" }
3
+ %head
4
+ %title= values[:title]
5
+ %meta{ :content => "text/html; charset=#{values[:charset]}", "http-equiv" => "Content-Type" }
6
+ %frameset{ :cols => "20%, *", :border => "1", :frameborder => "1", :bordercolor => "gray" }
7
+ %frameset{ :rows => "15%, 35%, 50%" }
8
+ %frame{ :name => "Files", :title => "Files", :src => "fr_file_index.html" }
9
+ %frame{ :name => "Classes", :src => "fr_class_index.html" }
10
+ %frame{ :name => "Methods", :src => "fr_method_index.html" }
11
+ %frame{ :name => "docwin", :src => values[:initial_page] }=""
@@ -0,0 +1,34 @@
1
+ !!! strict
2
+ - index = values[:list_title]
3
+ %html{ :lang => "en" }
4
+ %head
5
+ %title= values[:title]
6
+ %meta{ 'http-equiv' => "Content-Type", :content => "text/html; charset=#{values[:charset]}" }
7
+ %link{ :rel => "stylesheet", :href => values[:style_url], :type => "text/css", :media => "screen" }
8
+ - unless index
9
+ :javascript
10
+ function popupCode(url) {
11
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
12
+ }
13
+
14
+ function toggleCode(id) {
15
+ var code = document.getElementById(id)
16
+
17
+ code.style.display = code.style.display != 'block' ? 'block' : 'none'
18
+ return true
19
+ }
20
+
21
+ // Make codeblocks hidden by default
22
+ document.writeln('<' + 'style type="text/css">.method .source pre { display: none }<\/style>')
23
+ - else
24
+ %base{ :target => 'docwin' }/
25
+
26
+ %body{ :class => index ? 'list' : 'page' }
27
+ - if index
28
+ #index= yield
29
+ - else
30
+ #wrapper{ :class => values[:classmod] ? 'class' : 'file' }
31
+ = yield
32
+ #footer-push
33
+ #footer
34
+ = link_to '<strong>Hanna</strong> RDoc template', 'http://github.com/mislav/hanna/tree/master'
@@ -0,0 +1,13 @@
1
+ %h1= values[:list_title]
2
+
3
+ %script{:type => 'text/javascript'}
4
+ = read("prototype-1.6.0.3.js")
5
+ = build_javascript_search_index(values[:entries])
6
+ = read("method_search.js")
7
+ %form{:onsubmit => 'return performSearch()'}
8
+ %input{:type => 'text', :id => 'search', :class => 'untouched', :value => 'Enter search terms...'}
9
+ %ol#search-results{ :class => 'methods', :style => 'display: none' }
10
+
11
+ %ol#index-entries{ :class => 'methods' }
12
+ - for entry in values[:entries]
13
+ %li= link_to_method entry[:name], entry[:href]
@@ -0,0 +1,37 @@
1
+ - methods = methods_from_sections values[:sections]
2
+ - unless methods.empty?
3
+ #method-list
4
+ %h2 Methods
5
+ - for type in ['public class', 'protected class', 'public instance', 'protected instance']
6
+ - unless (list = methods[type]).empty?
7
+ %h3= type
8
+ %ol
9
+ - for method in list
10
+ - if method[:name].to_s.empty? && method[:callseq]
11
+ %li= link_to method[:callseq].gsub(/<br\s*\/?>/, "").split(/[\r\n]+/).map{ |s| s.split(/([({]+|\[\{|\s+(#?=>|&rarr;)\s+)/).first.sub(/^[A-Za-z0-9_:]+\./, "").sub(/\s+=\s+.*/, "=").strip }.uniq.join("<br />\n"), '#' + method[:aref]
12
+ - else
13
+ %li= link_to method[:name], '#' + method[:aref]
14
+
15
+ - if values[:requires] or values[:toc] or values[:includes]
16
+ #context
17
+ - if values[:requires]
18
+ #requires
19
+ %h2 Required files
20
+ %ol
21
+ - for req in values[:requires]
22
+ %li= link_to req[:name], req[:aref]
23
+
24
+ - if values[:toc]
25
+ #contents
26
+ %h2 Contents
27
+ %ol
28
+ - for item in values[:toc]
29
+ %li= link_to values[:secname], values[:href]
30
+
31
+ - if values[:includes]
32
+ #includes
33
+ %h2 Included modules
34
+ %ol
35
+ - for inc in values[:includes]
36
+ %li= link_to inc[:name], inc[:aref]
37
+
@@ -0,0 +1,63 @@
1
+ $(document).observe('dom:loaded', function() {
2
+ // Setup search-during-typing.
3
+ new Form.Element.Observer('search', 0.3, function(element, value) {
4
+ performSearch();
5
+ });
6
+
7
+ // Remove the default search box value when the user puts the focus on
8
+ // the search box for the first time.
9
+ var search_box = $('search');
10
+ if ($F('search') == 'Enter search terms...') {
11
+ search_box.observe('focus', function() {
12
+ if (search_box.hasClassName('untouched')) {
13
+ search_box.removeClassName('untouched');
14
+ search_box.value = '';
15
+ }
16
+ });
17
+ } else {
18
+ search_box.removeClassName('untouched');
19
+ }
20
+
21
+ search_box.insert({
22
+ after: new Element('span', { 'class': 'clear_button' }).update('x').observe('click', function(e) {
23
+ e.stopPropagation()
24
+ search_box.setValue('')
25
+ search_box.focus()
26
+ })
27
+ })
28
+ });
29
+
30
+ function searchInIndex(query) {
31
+ var i;
32
+ var results = [];
33
+ query = query.toLowerCase();
34
+ for (i = 0; i < search_index.length; i++) {
35
+ if (search_index[i].method.indexOf(query) != -1) {
36
+ results.push(search_index[i]);
37
+ }
38
+ }
39
+ return results;
40
+ }
41
+
42
+ function buildHtmlForResults(results) {
43
+ var html = "";
44
+ var i;
45
+ for (i = 0; i < results.length; i++) {
46
+ html += '<li>' + results[i].html + '</li>';
47
+ }
48
+ return html;
49
+ }
50
+
51
+ function performSearch() {
52
+ var query = $F('search');
53
+ if (query == '') {
54
+ $('index-entries').show();
55
+ $('search-results').hide();
56
+ } else {
57
+ var results = searchInIndex(query);
58
+ $('search-results').update(buildHtmlForResults(results));
59
+ $('index-entries').hide();
60
+ $('search-results').show();
61
+ }
62
+ return false;
63
+ }