DesigningPatterns-hanna 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +85 -0
- data/Rakefile +25 -0
- data/bin/hanna +79 -0
- data/lib/hanna.rb +1 -0
- data/lib/hanna/hanna.rb +55 -0
- data/lib/hanna/rdoctask.rb +45 -0
- data/lib/hanna/template_files/class_index.haml +3 -0
- data/lib/hanna/template_files/file_index.haml +13 -0
- data/lib/hanna/template_files/index.haml +11 -0
- data/lib/hanna/template_files/layout.haml +37 -0
- data/lib/hanna/template_files/method_list.haml +34 -0
- data/lib/hanna/template_files/page.haml +50 -0
- data/lib/hanna/template_files/sections.haml +97 -0
- data/lib/hanna/template_files/styles.sass +334 -0
- data/lib/hanna/template_helpers.rb +66 -0
- data/lib/hanna/template_page_patch.rb +35 -0
- metadata +89 -0
data/README.markdown
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Hanna -- a better RDoc template
|
2
|
+
|
3
|
+
Hanna is an RDoc template that scales. It's implemented in Haml, making the
|
4
|
+
sources clean and readable. It's built with simplicity, beauty and ease of
|
5
|
+
browsing in mind. (See more in [the wiki][wiki].)
|
6
|
+
|
7
|
+
Hanna was made by [Mislav][] and is available from [GitHub][]:
|
8
|
+
|
9
|
+
gem install mislav-hanna
|
10
|
+
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
After installing, you have three options. You can use the command-line tool:
|
15
|
+
|
16
|
+
hanna -h
|
17
|
+
|
18
|
+
For repeated generation of API docs, it's better to set up a Rake task. If you
|
19
|
+
already have an `RDocTask` set up, the only thing you need to change is this:
|
20
|
+
|
21
|
+
# replace this:
|
22
|
+
require 'rake/rdoctask'
|
23
|
+
# with this:
|
24
|
+
require 'hanna/rdoctask'
|
25
|
+
|
26
|
+
Tip: you can do this in the Rakefile of your Rails project before running `rake
|
27
|
+
doc:rails`.
|
28
|
+
|
29
|
+
Here is an example of a task for the [will_paginate library][wp]:
|
30
|
+
|
31
|
+
# instead of 'rake/rdoctask':
|
32
|
+
require 'hanna/rdoctask'
|
33
|
+
|
34
|
+
desc 'Generate RDoc documentation for the will_paginate plugin.'
|
35
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
36
|
+
rdoc.rdoc_files.include('README.rdoc', 'LICENSE', 'CHANGELOG').
|
37
|
+
include('lib/**/*.rb').
|
38
|
+
exclude('lib/will_paginate/named_scope*').
|
39
|
+
exclude('lib/will_paginate/array.rb').
|
40
|
+
exclude('lib/will_paginate/version.rb')
|
41
|
+
|
42
|
+
rdoc.main = "README.rdoc" # page to start on
|
43
|
+
rdoc.title = "will_paginate documentation"
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
46
|
+
rdoc.options << '--webcvs=http://github.com/mislav/will_paginate/tree/master/'
|
47
|
+
end
|
48
|
+
|
49
|
+
Either way, it's the same as using RDoc.
|
50
|
+
|
51
|
+
The last thing you can do with Hanna is generate documentation for installed
|
52
|
+
gems. This is a replacement for the "gem rdoc" command.
|
53
|
+
|
54
|
+
[sudo] hanna --gems haml will_paginate
|
55
|
+
|
56
|
+
Hanna also can be used with standard rdoc options:
|
57
|
+
--inline-source -T hanna
|
58
|
+
|
59
|
+
## A work in progress
|
60
|
+
|
61
|
+
Hanna is far from done, but it is the first RDoc template that's actually
|
62
|
+
_maintainable_. First thing I have done is converted the original HTML
|
63
|
+
template to Haml and Sass, cleaning up and removing the (ridiculous amount of)
|
64
|
+
duplication.
|
65
|
+
|
66
|
+
Also, the template fragments are now in _separate files_. You would have
|
67
|
+
fainted if you seen how it was before. (It's really no wonder why there are no
|
68
|
+
other RDoc templates around ... save one: [Allison][].)
|
69
|
+
|
70
|
+
Ultimately, I'd like to lose the frameset. Currently that is far from possible
|
71
|
+
because the whole RDoc HTML Generator is built for frames. Still, that is my
|
72
|
+
goal.
|
73
|
+
|
74
|
+
## You can help
|
75
|
+
|
76
|
+
Don't like something? Think you can design better? (You probably can.)
|
77
|
+
|
78
|
+
This is git. I welcome all submissions towards my goal.
|
79
|
+
|
80
|
+
|
81
|
+
[wiki]: http://github.com/mislav/hanna/wikis/home "Hanna wiki"
|
82
|
+
[GitHub]: http://gems.github.com/ "GitHub gem source"
|
83
|
+
[wp]: http://github.com/mislav/will_paginate
|
84
|
+
[Mislav]: http://mislav.caboo.se/ "Mislav Marohnić"
|
85
|
+
[Allison]: http://blog.evanweaver.com/files/doc/fauna/allison/ "A modern, pretty RDoc template"
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
desc %{Update ".manifest" with the latest list of project filenames. Respect .gitignore by excluding everything that git ignores. Update `files` and `test_files` arrays in "*.gemspec" file if it's present.}
|
2
|
+
task :manifest do
|
3
|
+
list = Dir['**/*'].sort
|
4
|
+
spec_file = Dir['*.gemspec'].first
|
5
|
+
list -= [spec_file] if spec_file
|
6
|
+
|
7
|
+
File.read('.gitignore').each_line do |glob|
|
8
|
+
glob = glob.chomp.sub(/^\//, '')
|
9
|
+
list -= Dir[glob]
|
10
|
+
list -= Dir["#{glob}/**/*"] if File.directory?(glob) and !File.symlink?(glob)
|
11
|
+
puts "excluding #{glob}"
|
12
|
+
end if File.exists?('.gitignore')
|
13
|
+
|
14
|
+
if spec_file
|
15
|
+
spec = File.read spec_file
|
16
|
+
spec.gsub! /^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx do
|
17
|
+
assignment = $1
|
18
|
+
bunch = $2 ? list.grep(/^test\//) : list
|
19
|
+
'%s%%w(%s)' % [assignment, bunch.join(' ')]
|
20
|
+
end
|
21
|
+
|
22
|
+
File.open(spec_file, 'w') {|f| f << spec }
|
23
|
+
end
|
24
|
+
File.open('.manifest', 'w') {|f| f << list.join("\n") }
|
25
|
+
end
|
data/bin/hanna
ADDED
@@ -0,0 +1,79 @@
|
|
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
|
+
require 'rubygems'
|
28
|
+
begin
|
29
|
+
gem 'rdoc', '~> 2.0.0'
|
30
|
+
rescue Gem::LoadError
|
31
|
+
$stderr.puts "Hanna requires the RDoc 2.0 gem."
|
32
|
+
exit 1
|
33
|
+
else
|
34
|
+
require 'rdoc/rdoc'
|
35
|
+
end
|
36
|
+
|
37
|
+
hanna_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
38
|
+
$:.unshift(hanna_dir) unless $:.include?(hanna_dir)
|
39
|
+
|
40
|
+
options = []
|
41
|
+
|
42
|
+
options << '-T' << 'hanna/hanna.rb'
|
43
|
+
options << '--inline-source' << '--charset=UTF-8'
|
44
|
+
|
45
|
+
if ARGV.first == '--gems'
|
46
|
+
require 'rubygems/doc_manager'
|
47
|
+
Gem::DocManager.configured_args = options
|
48
|
+
|
49
|
+
gem_names = ARGV.dup
|
50
|
+
gem_names.shift
|
51
|
+
|
52
|
+
unless gem_names.empty?
|
53
|
+
specs = gem_names.inject([]) do |arr, name|
|
54
|
+
found = Gem::SourceIndex.from_installed_gems.search(name)
|
55
|
+
spec = found.sort_by {|s| s.version }.last
|
56
|
+
arr << spec if spec
|
57
|
+
arr
|
58
|
+
end
|
59
|
+
else
|
60
|
+
specs = Gem::SourceIndex.from_installed_gems.inject({}) do |all, pair|
|
61
|
+
full_name, spec = pair
|
62
|
+
if spec.has_rdoc? and (!all[spec.name] or spec.version > all[spec.name].version)
|
63
|
+
all[spec.name] = spec
|
64
|
+
end
|
65
|
+
all
|
66
|
+
end
|
67
|
+
specs = specs.values
|
68
|
+
puts "Hanna is installing documentation for #{specs.size} gem#{specs.size > 1 ? 's' : ''} ..."
|
69
|
+
end
|
70
|
+
|
71
|
+
specs.each do |spec|
|
72
|
+
Gem::DocManager.new(spec).generate_rdoc
|
73
|
+
end
|
74
|
+
else
|
75
|
+
options << '-o' << 'doc' unless ARGV.include?('-o') or ARGV.include?('--op')
|
76
|
+
options.concat ARGV
|
77
|
+
|
78
|
+
RDoc::RDoc.new.document(options)
|
79
|
+
end
|
data/lib/hanna.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'hanna/hanna'
|
data/lib/hanna/hanna.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'haml'
|
2
|
+
require 'sass'
|
3
|
+
require 'rdoc/generator/html'
|
4
|
+
require 'hanna/template_page_patch'
|
5
|
+
|
6
|
+
# = A better RDoc HTML template
|
7
|
+
#
|
8
|
+
# Many different kinds of awesome.
|
9
|
+
#
|
10
|
+
# Author: Mislav Marohnić <mislav.marohnic@gmail.com>
|
11
|
+
# Based on the work of Michael Granger <ged@FaerieMUD.org>
|
12
|
+
|
13
|
+
module RDoc::Generator::HTML::HANNA
|
14
|
+
class << self
|
15
|
+
def dir
|
16
|
+
@dir ||= File.join File.dirname(__FILE__), 'template_files'
|
17
|
+
end
|
18
|
+
|
19
|
+
def read(*names)
|
20
|
+
extension = nil
|
21
|
+
|
22
|
+
content = names.map { |name|
|
23
|
+
if extension
|
24
|
+
name += '.' + extension
|
25
|
+
else
|
26
|
+
extension = name =~ /\.(\w+)$/ && $1
|
27
|
+
end
|
28
|
+
File.read File.join(dir, name)
|
29
|
+
}.join('')
|
30
|
+
|
31
|
+
case extension
|
32
|
+
when 'sass'
|
33
|
+
Sass::Engine.new(content)
|
34
|
+
when 'haml'
|
35
|
+
Haml::Engine.new(content)
|
36
|
+
else
|
37
|
+
content
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
STYLE = read('styles.sass')
|
43
|
+
|
44
|
+
CLASS_PAGE = read('page.haml')
|
45
|
+
FILE_PAGE = CLASS_PAGE
|
46
|
+
METHOD_LIST = read('method_list.haml', 'sections')
|
47
|
+
|
48
|
+
FR_INDEX_BODY = BODY = read('layout.haml')
|
49
|
+
|
50
|
+
FILE_INDEX = read('file_index.haml')
|
51
|
+
CLASS_INDEX = read('class_index.haml')
|
52
|
+
METHOD_INDEX = FILE_INDEX
|
53
|
+
|
54
|
+
INDEX = read('index.haml')
|
55
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
|
4
|
+
Rake::RDocTask.class_eval do
|
5
|
+
# don't allow it
|
6
|
+
undef :external=
|
7
|
+
|
8
|
+
# Create the tasks defined by this task lib.
|
9
|
+
def define
|
10
|
+
unless @template and @template != 'html'
|
11
|
+
@template = File.dirname(__FILE__) + '/hanna'
|
12
|
+
end
|
13
|
+
options << '--inline-source' unless options.include? '--inline-source' or options.include? '-S'
|
14
|
+
options << '--charset=UTF-8' if options.grep(/^(--charset$|-c\b)/).empty?
|
15
|
+
|
16
|
+
desc "Build the HTML documentation"
|
17
|
+
task name
|
18
|
+
|
19
|
+
desc "Force a rebuild of the RDOC files"
|
20
|
+
task paste("re", name) => [paste("clobber_", name), name]
|
21
|
+
|
22
|
+
desc "Remove rdoc products"
|
23
|
+
task paste("clobber_", name) do
|
24
|
+
rm_r rdoc_dir rescue nil
|
25
|
+
end
|
26
|
+
|
27
|
+
task :clobber => [paste("clobber_", name)]
|
28
|
+
|
29
|
+
directory @rdoc_dir
|
30
|
+
task name => [rdoc_target]
|
31
|
+
file rdoc_target => @rdoc_files + [$rakefile] do
|
32
|
+
rm_r @rdoc_dir rescue nil
|
33
|
+
|
34
|
+
begin
|
35
|
+
gem 'rdoc', '~> 2.0.0'
|
36
|
+
rescue Gem::LoadError
|
37
|
+
$stderr.puts "Couldn't load RDoc 2.0 gem"
|
38
|
+
end
|
39
|
+
require 'rdoc/rdoc'
|
40
|
+
|
41
|
+
RDoc::RDoc.new.document(option_list + @rdoc_files)
|
42
|
+
end
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%h1= values["list_title"]
|
2
|
+
- type = values["list_title"].downcase
|
3
|
+
- any_hidden = false
|
4
|
+
|
5
|
+
%ol#index-entries{ :class => type }
|
6
|
+
- for entry in values["entries"]
|
7
|
+
- hide = type == 'files' && entry['name'] =~ /\.rb$/
|
8
|
+
- any_hidden = true if hide
|
9
|
+
%li{ :class => hide ? 'other' : nil }= link_to entry['name'], entry['href']
|
10
|
+
|
11
|
+
- if any_hidden
|
12
|
+
%li
|
13
|
+
%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%, *" }
|
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,37 @@
|
|
1
|
+
!!! strict
|
2
|
+
- index = values['list_title']
|
3
|
+
%html{ :xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => "en", :lang => "en" }
|
4
|
+
%head
|
5
|
+
%title= index || 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
|
+
%script{ :type => "text/javascript" }
|
10
|
+
:plain
|
11
|
+
function popupCode(url) {
|
12
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
13
|
+
}
|
14
|
+
|
15
|
+
function toggleCode(id) {
|
16
|
+
var code = document.getElementById(id)
|
17
|
+
|
18
|
+
code.style.display = code.style.display != 'block' ? 'block' : 'none'
|
19
|
+
return true
|
20
|
+
}
|
21
|
+
|
22
|
+
// Make codeblocks hidden by default
|
23
|
+
document.writeln('<' + 'style type="text/css">.method .source pre { display: none }<\/style>')
|
24
|
+
- else
|
25
|
+
%base{ :target => 'docwin' }/
|
26
|
+
|
27
|
+
%body{ :class => index ? 'list' : 'page' }
|
28
|
+
- if index
|
29
|
+
#index= yield
|
30
|
+
- else
|
31
|
+
#wrapper{ :class => values["classmod"] ? 'class' : 'file' }
|
32
|
+
= yield
|
33
|
+
#footer-push
|
34
|
+
#footer
|
35
|
+
= link_to '<strong>Hanna</strong> RDoc template', 'http://github.com/mislav/hanna'
|
36
|
+
hand-crafted by
|
37
|
+
%strong= link_to 'Mislav', 'http://mislav.caboo.se/'
|
@@ -0,0 +1,34 @@
|
|
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
|
+
%li= link_to method["name"], '#' + method["aref"]
|
11
|
+
|
12
|
+
- if values["requires"] or values["toc"] or values["includes"]
|
13
|
+
#context
|
14
|
+
- if values["requires"]
|
15
|
+
#requires
|
16
|
+
%h2 Required files
|
17
|
+
%ol
|
18
|
+
- for req in values["requires"]
|
19
|
+
%li= link_to req["name"], req["aref"]
|
20
|
+
|
21
|
+
- if values["toc"]
|
22
|
+
#contents
|
23
|
+
%h2 Contents
|
24
|
+
%ol
|
25
|
+
- for item in values["toc"]
|
26
|
+
%li= link_to values["secname"], values["href"]
|
27
|
+
|
28
|
+
- if values["includes"]
|
29
|
+
#includes
|
30
|
+
%h2 Included modules
|
31
|
+
%ol
|
32
|
+
- for inc in values["includes"]
|
33
|
+
%li= link_to inc["name"], inc["aref"]
|
34
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
- file_page = !values["classmod"]
|
2
|
+
- title_in_description = values["description"] && values["description"] =~ /^\s*<h1>/m
|
3
|
+
|
4
|
+
.header
|
5
|
+
- title = capture_haml do
|
6
|
+
- if file_page
|
7
|
+
= values["short_name"]
|
8
|
+
- else
|
9
|
+
%span.type= values["classmod"]
|
10
|
+
= values["full_name"]
|
11
|
+
- if title_in_description
|
12
|
+
.name= title
|
13
|
+
- else
|
14
|
+
%h1.name= title
|
15
|
+
|
16
|
+
- if file_page
|
17
|
+
.paths
|
18
|
+
= values["full_path"]
|
19
|
+
- if values["cvsurl"]
|
20
|
+
== (#{link_to 'view online', values["cvsurl"]})
|
21
|
+
- else
|
22
|
+
%ol.paths
|
23
|
+
- values["infiles"].each_with_index do |file, index|
|
24
|
+
%li{ :class => index > 0 ? 'other' : nil }
|
25
|
+
= link_to file["full_path"], file["full_path_url"]
|
26
|
+
- if file["cvsurl"]
|
27
|
+
== (#{link_to 'view online', file["cvsurl"]})
|
28
|
+
- if values["infiles"].size > 1
|
29
|
+
%li
|
30
|
+
%a.show{ :href => '#', :onclick => 'this.parentNode.parentNode.className += " expanded"; this.parentNode.removeChild(this); return false' } show all
|
31
|
+
|
32
|
+
- if values["parent"] then
|
33
|
+
.parent
|
34
|
+
Parent:
|
35
|
+
%strong= link_to values["parent"], values["par_url"]
|
36
|
+
|
37
|
+
- if values["dtm_modified"]
|
38
|
+
.last-update
|
39
|
+
Last Update:
|
40
|
+
%span.datetime= values["dtm_modified"]
|
41
|
+
|
42
|
+
#content
|
43
|
+
- if values["diagram"]
|
44
|
+
#diagram= values["diagram"]
|
45
|
+
|
46
|
+
#text
|
47
|
+
- if values["description"]
|
48
|
+
#description~ values["description"]
|
49
|
+
|
50
|
+
= yield
|
@@ -0,0 +1,97 @@
|
|
1
|
+
- for section in values["sections"]
|
2
|
+
#section
|
3
|
+
- if section["sectitle"]
|
4
|
+
%h2= link_to section["sectitle"], section["secsequence"]
|
5
|
+
- if section["seccomment"]
|
6
|
+
.section-comment= section["seccomment"]
|
7
|
+
- if section["classlist"]
|
8
|
+
#class-list
|
9
|
+
%h3 Classes and Modules
|
10
|
+
= section["classlist"]
|
11
|
+
|
12
|
+
- if section["constants"]
|
13
|
+
#constants-list
|
14
|
+
%h3.section-bar Constants
|
15
|
+
.name-list
|
16
|
+
%table{ :summary => "Constants" }
|
17
|
+
- for const in section["constants"]
|
18
|
+
%tr.top-aligned-row.context-row
|
19
|
+
%td.context-item-name
|
20
|
+
= const["name"]
|
21
|
+
%td
|
22
|
+
\=
|
23
|
+
%td.context-item-value
|
24
|
+
= const["value"]
|
25
|
+
- if const["desc"] then
|
26
|
+
%td{ :width => "3em" }
|
27
|
+
|
28
|
+
%td.context-item-desc
|
29
|
+
= const["desc"]
|
30
|
+
|
31
|
+
- if section["aliases"]
|
32
|
+
#aliases-list
|
33
|
+
%h3.section-bar External Aliases
|
34
|
+
.name-list
|
35
|
+
%table{ :summary => "aliases" }
|
36
|
+
- for alia in section["aliases"]
|
37
|
+
%tr.top-aligned-row.context-row
|
38
|
+
%td.context-item-name
|
39
|
+
= alia["old_name"]
|
40
|
+
%td
|
41
|
+
\->
|
42
|
+
%td.context-item-value
|
43
|
+
= alia["new_name"]
|
44
|
+
- if alia["desc"] then
|
45
|
+
%tr.top-aligned-row.context-row
|
46
|
+
%td
|
47
|
+
|
48
|
+
%td.context-item-desc{ :colspan => "2" }
|
49
|
+
= alia["desc"]
|
50
|
+
|
51
|
+
- if section["attributes"]
|
52
|
+
#attribute-list
|
53
|
+
%h3.section-bar Attributes
|
54
|
+
.name-list
|
55
|
+
%table
|
56
|
+
- for attr in section["attributes"]
|
57
|
+
%tr.top-aligned-row.context-row
|
58
|
+
%td.context-item-name
|
59
|
+
= attr["name"]
|
60
|
+
- if attr["rw"] then
|
61
|
+
%td.context-item-value
|
62
|
+
= "[#{attr['rw']}]"
|
63
|
+
- else
|
64
|
+
%td.context-item-value
|
65
|
+
%td.context-item-desc
|
66
|
+
= attr["a_desc"]
|
67
|
+
|
68
|
+
- if section["method_list"]
|
69
|
+
#methods
|
70
|
+
- for list in section["method_list"]
|
71
|
+
- if list["methods"] then
|
72
|
+
%h3== #{list["type"]} #{list["category"].downcase} methods
|
73
|
+
|
74
|
+
- for method in list["methods"]
|
75
|
+
.method{ :id => "method-#{method['aref']}", :class => "#{list['type']}-#{list['category']}".downcase }
|
76
|
+
%a{ :name => method["aref"] }
|
77
|
+
.synopsis
|
78
|
+
- method_html = capture_haml do
|
79
|
+
- if method["callseq"]
|
80
|
+
%span.name= method["callseq"]
|
81
|
+
- else
|
82
|
+
%span.name= method["name"]
|
83
|
+
%span.arguments= method["params"]
|
84
|
+
- if method["codeurl"]
|
85
|
+
%a.method-signature{ :href => method["codeurl"], :onclick => "popupCode(this.href); return false", :target => "Code" }
|
86
|
+
= method_html
|
87
|
+
- else
|
88
|
+
= method_html
|
89
|
+
- if method["m_desc"]
|
90
|
+
.description
|
91
|
+
~ method["m_desc"]
|
92
|
+
- if method["sourcecode"]
|
93
|
+
.source
|
94
|
+
- name = "#{method['aref']}-source"
|
95
|
+
%a.source-toggle{ :href => "#", :onclick => "toggleCode('#{name}'); return false" }
|
96
|
+
[show source]
|
97
|
+
~ "<pre id='#{name}'>#{method["sourcecode"]}</pre>"
|
@@ -0,0 +1,334 @@
|
|
1
|
+
!title_font = Georgia, serif
|
2
|
+
!code_font_family = Monaco, "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace
|
3
|
+
!code_font_size = 14px
|
4
|
+
!code_font = !code_font_size !code_font_family
|
5
|
+
|
6
|
+
!light_link = #369
|
7
|
+
!link = !light_link - 40
|
8
|
+
!light_text = #666
|
9
|
+
!dark_blue_text = #0E3062
|
10
|
+
|
11
|
+
html, body
|
12
|
+
:height 100%
|
13
|
+
body
|
14
|
+
:font-family Verdana, Arial, Helvetica, sans-serif
|
15
|
+
:font-size 90%
|
16
|
+
:margin 0
|
17
|
+
:padding 0
|
18
|
+
:background white
|
19
|
+
|
20
|
+
#wrapper
|
21
|
+
:min-height 100%
|
22
|
+
:height auto !important
|
23
|
+
:height 100%
|
24
|
+
:margin 0 auto -43px
|
25
|
+
#footer-push
|
26
|
+
:height 43px
|
27
|
+
div.header, #footer
|
28
|
+
:background #eee
|
29
|
+
#footer
|
30
|
+
:border-top 1px solid silver
|
31
|
+
:margin-top 12px
|
32
|
+
:padding 0 2em
|
33
|
+
:line-height 30px
|
34
|
+
:text-align center
|
35
|
+
:font-variant small-caps
|
36
|
+
:font-size 95%
|
37
|
+
|
38
|
+
// self-clearing
|
39
|
+
.clearing
|
40
|
+
&:after
|
41
|
+
:content "."
|
42
|
+
:visibility hidden
|
43
|
+
:height 0
|
44
|
+
:display block
|
45
|
+
:clear both
|
46
|
+
* html &
|
47
|
+
:height 1px
|
48
|
+
*:first-child + html
|
49
|
+
:overflow hidden
|
50
|
+
|
51
|
+
h1, h2, h3, h4, h5, h6
|
52
|
+
:margin 0
|
53
|
+
:font-weight normal
|
54
|
+
|
55
|
+
a
|
56
|
+
:color = !link
|
57
|
+
&:hover
|
58
|
+
:background = !light_link
|
59
|
+
:text-decoration none
|
60
|
+
:color #eef
|
61
|
+
#description, .method .description, .header
|
62
|
+
a
|
63
|
+
:color = !light_link
|
64
|
+
&:hover
|
65
|
+
:color #eee
|
66
|
+
h1, h2, h3, h4, h5, h6
|
67
|
+
a
|
68
|
+
:color = !link
|
69
|
+
|
70
|
+
ol
|
71
|
+
:margin 0
|
72
|
+
:padding 0
|
73
|
+
:list-style none
|
74
|
+
li
|
75
|
+
:margin-left 0
|
76
|
+
:white-space nowrap
|
77
|
+
&.other
|
78
|
+
:display none
|
79
|
+
ol.expanded li.other
|
80
|
+
:display list-item
|
81
|
+
|
82
|
+
table
|
83
|
+
:margin-bottom 1em
|
84
|
+
:font-size 1em
|
85
|
+
:border-collapse collapse
|
86
|
+
td, th
|
87
|
+
:padding .4em .8em
|
88
|
+
thead
|
89
|
+
:background-color #e8e8e8
|
90
|
+
th
|
91
|
+
:font-variant small-caps
|
92
|
+
:color = !light_text
|
93
|
+
tr
|
94
|
+
:border-bottom 1px solid silver
|
95
|
+
|
96
|
+
#index, div.header
|
97
|
+
a.show
|
98
|
+
:text-decoration underline
|
99
|
+
:font-style italic
|
100
|
+
:color = !light_text
|
101
|
+
&:after
|
102
|
+
:content " ..."
|
103
|
+
&:hover
|
104
|
+
:color black
|
105
|
+
:background #ffe
|
106
|
+
|
107
|
+
#index
|
108
|
+
:font 85%/1.2 Arial, Helvetica, sans-serif
|
109
|
+
a
|
110
|
+
:text-decoration none
|
111
|
+
h1
|
112
|
+
:padding .2em .5em .1em
|
113
|
+
:background #ccc
|
114
|
+
:font = "small-caps 1.2em" !title_font
|
115
|
+
:color #333
|
116
|
+
:border-bottom 1px solid gray
|
117
|
+
ol
|
118
|
+
:padding .4em .5em
|
119
|
+
li
|
120
|
+
:white-space nowrap
|
121
|
+
#index-entries.classes
|
122
|
+
:font-size 1.1em
|
123
|
+
ol
|
124
|
+
:padding 0
|
125
|
+
span.nodoc
|
126
|
+
:display none
|
127
|
+
span.nodoc, a
|
128
|
+
:font-weight bold
|
129
|
+
.parent
|
130
|
+
:font-weight normal
|
131
|
+
|
132
|
+
div.header
|
133
|
+
:font-size 80%
|
134
|
+
:padding .5em 2%
|
135
|
+
:font-family Arial, Helvetica, sans-serif
|
136
|
+
:border-bottom 1px solid silver
|
137
|
+
.name
|
138
|
+
:font-size 1.6em
|
139
|
+
:font-family = !title_font
|
140
|
+
.type
|
141
|
+
:color = !light_text
|
142
|
+
:font-size 80%
|
143
|
+
:font-variant small-caps
|
144
|
+
h1.name
|
145
|
+
:font-size 2.2em
|
146
|
+
.paths, .last-update, .parent
|
147
|
+
:color = !light_text
|
148
|
+
.last-update .datetime
|
149
|
+
:color = !light_text - 30
|
150
|
+
.parent
|
151
|
+
:margin-top .3em
|
152
|
+
strong
|
153
|
+
:font-weight normal
|
154
|
+
:color = !light_text - 30
|
155
|
+
|
156
|
+
#content
|
157
|
+
:padding 12px 2%
|
158
|
+
div.class &
|
159
|
+
:position relative
|
160
|
+
:width 72%
|
161
|
+
|
162
|
+
pre, .method .synopsis
|
163
|
+
:font = !code_font
|
164
|
+
pre
|
165
|
+
:color black
|
166
|
+
:background #eee
|
167
|
+
:border 1px solid silver
|
168
|
+
:padding 0 .5em .8em .5em
|
169
|
+
:overflow auto
|
170
|
+
p, li, dd
|
171
|
+
code, tt
|
172
|
+
:font = !code_font
|
173
|
+
:background #ffffe3
|
174
|
+
:padding 2px 3px
|
175
|
+
h1, h2, h3, h4, h5, h6
|
176
|
+
code, tt
|
177
|
+
:font-size 1.1em
|
178
|
+
|
179
|
+
#text
|
180
|
+
:position relative
|
181
|
+
|
182
|
+
#description
|
183
|
+
// :max-width 60em
|
184
|
+
p
|
185
|
+
:margin-top .5em
|
186
|
+
h1, h2, h3, h4, h5, h6
|
187
|
+
:font-family = !title_font
|
188
|
+
h1
|
189
|
+
:font-size 2.2em
|
190
|
+
:margin-bottom .2em
|
191
|
+
:border-bottom 3px double #d8d8d8
|
192
|
+
:padding-bottom .1em
|
193
|
+
h2
|
194
|
+
:font-size 1.8em
|
195
|
+
:color = !dark_blue_text
|
196
|
+
:margin .8em 0 .3em 0
|
197
|
+
h3
|
198
|
+
:font-size 1.6em
|
199
|
+
:margin .8em 0 .3em 0
|
200
|
+
:color = !light_text
|
201
|
+
h4
|
202
|
+
:font-size 1.4em
|
203
|
+
:margin .8em 0 .3em 0
|
204
|
+
h5
|
205
|
+
:font-size 1.2em
|
206
|
+
:margin .8em 0 .3em 0
|
207
|
+
:color = !dark_blue_text
|
208
|
+
h6
|
209
|
+
:font-size 1.0em
|
210
|
+
:margin .8em 0 .3em 0
|
211
|
+
:color = !light_text
|
212
|
+
|
213
|
+
#description, .method .description
|
214
|
+
ul
|
215
|
+
:margin .8em 0
|
216
|
+
:padding-left 1.5em
|
217
|
+
|
218
|
+
#method-list
|
219
|
+
:position absolute
|
220
|
+
:top 0px
|
221
|
+
:right -33%
|
222
|
+
:width 28%
|
223
|
+
:background #eee
|
224
|
+
:border 1px solid silver
|
225
|
+
:padding .4em 1%
|
226
|
+
:overflow hidden
|
227
|
+
h2
|
228
|
+
:font-size 1.3em
|
229
|
+
h3
|
230
|
+
:font-variant small-caps
|
231
|
+
:text-transform capitalize
|
232
|
+
:font-family = !title_font
|
233
|
+
:color #666
|
234
|
+
:font-size 1.1em
|
235
|
+
ol
|
236
|
+
:padding 0 0 .5em .5em
|
237
|
+
|
238
|
+
#context
|
239
|
+
:font-size 85%
|
240
|
+
:padding-left 1.5em
|
241
|
+
:border-top 1px dashed silver
|
242
|
+
:margin-top 1em
|
243
|
+
h2
|
244
|
+
:color #333
|
245
|
+
:font = "bold small-caps 1.3em" !title_font
|
246
|
+
:margin .5em 0 .1em 0
|
247
|
+
|
248
|
+
#methods
|
249
|
+
h3
|
250
|
+
:font = "small-caps 1.2em" !title_font
|
251
|
+
:color #444
|
252
|
+
:margin 1em 0 .2em 0
|
253
|
+
h4
|
254
|
+
:font = "1.1em" !title_font
|
255
|
+
:color = !dark_blue_text
|
256
|
+
:margin 1em 0 .2em 0
|
257
|
+
|
258
|
+
.method
|
259
|
+
:border 1px solid silver
|
260
|
+
:margin-top .5em
|
261
|
+
:background #eee
|
262
|
+
.synopsis
|
263
|
+
:color black
|
264
|
+
:background silver
|
265
|
+
:padding .2em 1em
|
266
|
+
.name
|
267
|
+
:font-weight bold
|
268
|
+
a
|
269
|
+
:text-decoration none
|
270
|
+
.description
|
271
|
+
:padding 0 1em
|
272
|
+
pre
|
273
|
+
:background #f8f8f8
|
274
|
+
.source
|
275
|
+
:margin .5em 0
|
276
|
+
.source-toggle
|
277
|
+
:font-size 85%
|
278
|
+
:margin-left 1em
|
279
|
+
.public-class
|
280
|
+
:background #ffffe4
|
281
|
+
.public-instance .synopsis
|
282
|
+
:color #eee
|
283
|
+
:background = !light_link
|
284
|
+
|
285
|
+
#content .method .source pre
|
286
|
+
:background #262626
|
287
|
+
:color #ffdead
|
288
|
+
:margin 1em
|
289
|
+
:padding 0.5em
|
290
|
+
:border 1px dashed #999
|
291
|
+
:overflow hidden
|
292
|
+
|
293
|
+
.standalone-code
|
294
|
+
:background #221111
|
295
|
+
:color #ffdead
|
296
|
+
:overflow hidden
|
297
|
+
|
298
|
+
.ruby-constant
|
299
|
+
:color #7fffd4
|
300
|
+
:background transparent
|
301
|
+
|
302
|
+
.ruby-keyword
|
303
|
+
:color #00ffff
|
304
|
+
:background transparent
|
305
|
+
|
306
|
+
.ruby-ivar
|
307
|
+
:color #eedd82
|
308
|
+
:background transparent
|
309
|
+
|
310
|
+
.ruby-operator
|
311
|
+
:color #00ffee
|
312
|
+
:background transparent
|
313
|
+
|
314
|
+
.ruby-identifier
|
315
|
+
:color #ffdead
|
316
|
+
:background transparent
|
317
|
+
|
318
|
+
.ruby-node
|
319
|
+
:color #ffa07a
|
320
|
+
:background transparent
|
321
|
+
|
322
|
+
.ruby-comment
|
323
|
+
:color #b22222
|
324
|
+
:font-weight bold
|
325
|
+
:background transparent
|
326
|
+
|
327
|
+
.ruby-regexp
|
328
|
+
:color #ffa07a
|
329
|
+
:background transparent
|
330
|
+
|
331
|
+
.ruby-value
|
332
|
+
:color #7fffd4
|
333
|
+
:background transparent
|
334
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Hanna
|
5
|
+
module TemplateHelpers
|
6
|
+
protected
|
7
|
+
|
8
|
+
def link_to(text, url = nil, classname = nil)
|
9
|
+
class_attr = classname ? %[ class="#{classname}"] : ''
|
10
|
+
|
11
|
+
if url
|
12
|
+
%[<a href="#{url}"#{class_attr}>#{text}</a>]
|
13
|
+
elsif classname
|
14
|
+
%[<span#{class_attr}>#{text}</span>]
|
15
|
+
else
|
16
|
+
text
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def debug(text)
|
21
|
+
"<pre>#{h YAML::dump(text)}</pre>"
|
22
|
+
end
|
23
|
+
|
24
|
+
def h(html)
|
25
|
+
CGI::escapeHTML html
|
26
|
+
end
|
27
|
+
|
28
|
+
def methods_from_sections(sections)
|
29
|
+
sections.inject(Hash.new {|h, k| h[k] = []}) do |methods, section|
|
30
|
+
section['method_list'].each do |ml|
|
31
|
+
methods["#{ml['type']} #{ml['category']}".downcase].concat ml['methods']
|
32
|
+
end if section['method_list']
|
33
|
+
methods
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def make_class_tree(entries)
|
38
|
+
entries.inject({}) do |tree, entry|
|
39
|
+
if entry['href']
|
40
|
+
leaf = entry['name'].split('::').inject(tree) do |branch, klass|
|
41
|
+
branch[klass] ||= {}
|
42
|
+
end
|
43
|
+
leaf['_href'] = entry['href']
|
44
|
+
end
|
45
|
+
tree
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def render_class_tree(tree, parent = nil)
|
50
|
+
parent = parent + '::' if parent
|
51
|
+
tree.keys.sort.inject('') do |out, name|
|
52
|
+
unless name == '_href'
|
53
|
+
subtree = tree[name]
|
54
|
+
text = parent ? %[<span class="parent">#{parent}</span>#{name}] : name
|
55
|
+
out << '<li>'
|
56
|
+
out << (subtree['_href'] ? link_to(text, subtree['_href']) : %[<span class="nodoc">#{text}</span>])
|
57
|
+
if subtree.keys.size > 1
|
58
|
+
out << "\n<ol>" << render_class_tree(subtree, parent.to_s + name) << "\n</ol>"
|
59
|
+
end
|
60
|
+
out << '</li>'
|
61
|
+
end
|
62
|
+
out
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'hanna/template_helpers'
|
2
|
+
|
3
|
+
RDoc::TemplatePage.class_eval do
|
4
|
+
|
5
|
+
include Hanna::TemplateHelpers
|
6
|
+
|
7
|
+
# overwrite the original method
|
8
|
+
def write_html_on(io, values)
|
9
|
+
result = @templates.reverse.inject(nil) do |previous, template|
|
10
|
+
case template
|
11
|
+
when Haml::Engine
|
12
|
+
template.to_html(get_binding, :values => values) { previous }
|
13
|
+
when Sass::Engine
|
14
|
+
template.to_css
|
15
|
+
when String
|
16
|
+
ERB.new(template).result(get_binding(values){ previous })
|
17
|
+
when nil
|
18
|
+
previous
|
19
|
+
else
|
20
|
+
raise "don't know how to handle a template of class '#{template.class.name}'"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
io.write result
|
25
|
+
rescue
|
26
|
+
$stderr.puts "error while writing to #{io.inspect}"
|
27
|
+
raise
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def get_binding(values = nil)
|
33
|
+
binding
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: DesigningPatterns-hanna
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Mislav Marohni\xC4\x87"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-05-03 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rdoc
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.1.0
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: haml
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 1.8.2
|
32
|
+
version:
|
33
|
+
description: Hanna is an RDoc template that scales. It's implemented in Haml, making its source clean and maintainable. It's built with simplicity, beauty and ease of browsing in mind.
|
34
|
+
email: mislav.marohnic@gmail.com
|
35
|
+
executables:
|
36
|
+
- hanna
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
files:
|
42
|
+
- README.markdown
|
43
|
+
- Rakefile
|
44
|
+
- bin
|
45
|
+
- bin/hanna
|
46
|
+
- lib
|
47
|
+
- lib/hanna.rb
|
48
|
+
- lib/hanna
|
49
|
+
- lib/hanna/hanna.rb
|
50
|
+
- lib/hanna/rdoctask.rb
|
51
|
+
- lib/hanna/template_files
|
52
|
+
- lib/hanna/template_files/class_index.haml
|
53
|
+
- lib/hanna/template_files/file_index.haml
|
54
|
+
- lib/hanna/template_files/index.haml
|
55
|
+
- lib/hanna/template_files/layout.haml
|
56
|
+
- lib/hanna/template_files/method_list.haml
|
57
|
+
- lib/hanna/template_files/page.haml
|
58
|
+
- lib/hanna/template_files/sections.haml
|
59
|
+
- lib/hanna/template_files/styles.sass
|
60
|
+
- lib/hanna/template_helpers.rb
|
61
|
+
- lib/hanna/template_page_patch.rb
|
62
|
+
has_rdoc: false
|
63
|
+
homepage: http://github.com/mislav/hanna
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 1.2.0
|
85
|
+
signing_key:
|
86
|
+
specification_version: 2
|
87
|
+
summary: An RDoc template that rocks
|
88
|
+
test_files: []
|
89
|
+
|