DesigningPatterns-hanna 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|