rocco 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +23 -0
- data/Rakefile +63 -7
- data/bin/rocco +5 -0
- data/lib/rocco.rb +54 -36
- data/lib/rocco/layout.mustache +7 -1
- data/lib/rocco/tasks.rb +110 -0
- data/rocco.gemspec +4 -3
- metadata +5 -4
- data/README.md +0 -8
data/README
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
___ ___ ___ ___ ___
|
4
|
+
/\ \ /\ \ /\ \ /\ \ /\ \
|
5
|
+
/::\ \ /::\ \ /::\ \ /::\ \ /::\ \
|
6
|
+
/::\:\__\ /:/\:\__\ /:/\:\__\ /:/\:\__\ /:/\:\__\
|
7
|
+
\;:::/ / \:\/:/ / \:\ \/__/ \:\ \/__/ \:\/:/ /
|
8
|
+
|:\/__/ \::/ / \:\__\ \:\__\ \::/ /
|
9
|
+
\|__| \/__/ \/__/ \/__/ \/__/
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
Rocco is a quick-and-dirty, literate-programming-style documentation
|
14
|
+
generator for Ruby. See the Rocco generated docs for more information:
|
15
|
+
|
16
|
+
<http://rtomayko.github.com/rocco/>
|
17
|
+
|
18
|
+
|
19
|
+
Rocco is a port of, and borrows heavily from, Docco -- the original
|
20
|
+
quick-and-dirty, hundred-line-long, literate-programming-style
|
21
|
+
documentation generator in CoffeeScript:
|
22
|
+
|
23
|
+
<http://jashkenas.github.com/docco/>
|
data/Rakefile
CHANGED
@@ -1,5 +1,18 @@
|
|
1
|
+
$LOAD_PATH.unshift 'lib'
|
2
|
+
|
1
3
|
require 'rake/testtask'
|
2
|
-
|
4
|
+
require 'rake/clean'
|
5
|
+
|
6
|
+
task :default => [:sup, :docs]
|
7
|
+
|
8
|
+
desc 'Holla'
|
9
|
+
task :sup do
|
10
|
+
verbose do
|
11
|
+
lines = File.read('README').split("\n")[0,12]
|
12
|
+
lines.map! { |line| line[15..-1] }
|
13
|
+
puts lines.join("\n")
|
14
|
+
end
|
15
|
+
end
|
3
16
|
|
4
17
|
desc 'Run tests (default)'
|
5
18
|
Rake::TestTask.new(:test) do |t|
|
@@ -7,6 +20,52 @@ Rake::TestTask.new(:test) do |t|
|
|
7
20
|
t.ruby_opts = ['-rubygems'] if defined? Gem
|
8
21
|
end
|
9
22
|
|
23
|
+
# Bring in Rocco tasks
|
24
|
+
require 'rocco/tasks'
|
25
|
+
Rocco::make 'docs/'
|
26
|
+
|
27
|
+
desc 'Build rocco docs'
|
28
|
+
task :docs => :rocco
|
29
|
+
directory 'docs/'
|
30
|
+
|
31
|
+
desc 'Build docs and open in browser for the reading'
|
32
|
+
task :read => :docs do
|
33
|
+
sh 'open docs/rocco.html'
|
34
|
+
end
|
35
|
+
|
36
|
+
# Make index.html a copy of rocco.html
|
37
|
+
file 'docs/index.html' => 'docs/rocco.html' do |f|
|
38
|
+
cp 'docs/rocco.html', 'docs/index.html', :preserve => true
|
39
|
+
end
|
40
|
+
task :docs => 'docs/index.html'
|
41
|
+
CLEAN.include 'docs/index.html'
|
42
|
+
|
43
|
+
# Alias for docs task
|
44
|
+
task :doc => :docs
|
45
|
+
|
46
|
+
# GITHUB PAGES ===============================================================
|
47
|
+
|
48
|
+
desc 'Update gh-pages branch'
|
49
|
+
task :pages => ['docs/.git', :docs] do
|
50
|
+
rev = `git rev-parse --short HEAD`.strip
|
51
|
+
Dir.chdir 'docs' do
|
52
|
+
sh "git add *.html"
|
53
|
+
sh "git commit -m 'rebuild pages from #{rev}'" do |ok,res|
|
54
|
+
if ok
|
55
|
+
verbose { puts "gh-pages updated" }
|
56
|
+
sh "git push -q o HEAD:gh-pages"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Update the pages/ directory clone
|
63
|
+
file 'docs/.git' => ['docs/', '.git/refs/heads/gh-pages'] do |f|
|
64
|
+
sh "cd docs && git init -q && git remote add o ../.git" if !File.exist?(f.name)
|
65
|
+
sh "cd docs && git fetch -q o && git reset -q --hard o/gh-pages && touch ."
|
66
|
+
end
|
67
|
+
CLOBBER.include 'docs/.git'
|
68
|
+
|
10
69
|
# PACKAGING =================================================================
|
11
70
|
|
12
71
|
if defined?(Gem)
|
@@ -39,21 +98,18 @@ end
|
|
39
98
|
# GEMSPEC ===================================================================
|
40
99
|
|
41
100
|
file 'rocco.gemspec' => FileList['{lib,test,bin}/**','Rakefile'] do |f|
|
42
|
-
# read version from tilt.rb
|
43
101
|
version = File.read('lib/rocco.rb')[/VERSION = '(.*)'/] && $1
|
44
|
-
|
102
|
+
date = Time.now.strftime("%Y-%m-%d")
|
45
103
|
spec = File.
|
46
104
|
read(f.name).
|
47
105
|
sub(/s\.version\s*=\s*'.*'/, "s.version = '#{version}'")
|
48
106
|
parts = spec.split(" # = MANIFEST =\n")
|
49
|
-
# determine file list from git ls-files
|
50
107
|
files = `git ls-files`.
|
51
108
|
split("\n").sort.reject{ |file| file =~ /^\./ }.
|
52
109
|
map{ |file| " #{file}" }.join("\n")
|
53
|
-
# piece file back together and write...
|
54
110
|
parts[1] = " s.files = %w[\n#{files}\n ]\n"
|
55
111
|
spec = parts.join(" # = MANIFEST =\n")
|
56
|
-
spec.sub!(/s.date = '.*'/, "s.date = '#{
|
112
|
+
spec.sub!(/s.date = '.*'/, "s.date = '#{date}'")
|
57
113
|
File.open(f.name, 'w') { |io| io.write(spec) }
|
58
|
-
puts "
|
114
|
+
puts "#{f.name} #{version} (#{date})"
|
59
115
|
end
|
data/bin/rocco
CHANGED
data/lib/rocco.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Rocco reads Ruby source files and produces annotated source documentation
|
5
5
|
# in HTML format. Comments are formatted with [Markdown][md] and presented
|
6
6
|
# alongside syntax highlighted code so as to give an annotation effect.
|
7
|
-
# This page is the result of running Rocco against its own source file.
|
7
|
+
# This page is the result of running Rocco against [its own source file][so].
|
8
8
|
#
|
9
9
|
# Most of this was written while waiting for [node.js][no] to build (so I
|
10
10
|
# could use Docco!). Docco's gorgeous HTML and CSS are taken verbatim.
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# [CoffeeScript][co] and may be a bit easier to obtain and install in
|
13
13
|
# existing Ruby environments or where node doesn't run yet.
|
14
14
|
#
|
15
|
-
# Rocco
|
15
|
+
# Install Rocco with Rubygems:
|
16
16
|
#
|
17
17
|
# gem install rocco
|
18
18
|
#
|
@@ -27,19 +27,29 @@
|
|
27
27
|
# [do]: http://jashkenas.github.com/docco/
|
28
28
|
# [co]: http://coffeescript.org/
|
29
29
|
# [md]: http://daringfireball.net/projects/markdown/
|
30
|
+
# [so]: http://github.com/rtomayko/rocco/blob/master/lib/rocco.rb#commit
|
30
31
|
|
31
32
|
#### Prerequisites
|
32
33
|
|
33
|
-
#
|
34
|
-
#
|
35
|
-
|
34
|
+
# We'll need a Markdown library. [RDiscount][rd], if we're lucky. Otherwise,
|
35
|
+
# issue a warning and fall back on using BlueCloth.
|
36
|
+
#
|
37
|
+
# [rd]: http://github.com/rtomayko/rdiscount
|
38
|
+
begin
|
39
|
+
require 'rdiscount'
|
40
|
+
rescue LoadError => boom
|
41
|
+
warn "warn: #{boom}. trying bluecloth"
|
42
|
+
require 'bluecloth'
|
43
|
+
Markdown = BlueCloth
|
44
|
+
end
|
36
45
|
|
37
46
|
# We use [{{ mustache }}](http://defunkt.github.com/mustache/) for
|
38
|
-
# templating.
|
47
|
+
# HTML templating.
|
39
48
|
require 'mustache'
|
40
49
|
|
41
50
|
# Code is run through [Pygments](http://pygments.org/) for syntax
|
42
|
-
# highlighting. Fail fast if we can't find the `pygmentize`
|
51
|
+
# highlighting. Fail fast right here if we can't find the `pygmentize`
|
52
|
+
# program on PATH.
|
43
53
|
if ! ENV['PATH'].split(':').any? { |dir| File.exist?("#{dir}/pygmentize") }
|
44
54
|
fail "Pygments is required for syntax highlighting"
|
45
55
|
end
|
@@ -51,7 +61,7 @@ end
|
|
51
61
|
# whatever means necessary and return it as a string. With no `block`, the
|
52
62
|
# file is read to retrieve data.
|
53
63
|
class Rocco
|
54
|
-
VERSION = '0.
|
64
|
+
VERSION = '0.2'
|
55
65
|
|
56
66
|
def initialize(filename, &block)
|
57
67
|
@file = filename
|
@@ -61,8 +71,7 @@ class Rocco
|
|
61
71
|
else
|
62
72
|
File.read(filename)
|
63
73
|
end
|
64
|
-
|
65
|
-
@sections = highlight(parse(@data))
|
74
|
+
@sections = highlight(split(parse(@data)))
|
66
75
|
end
|
67
76
|
|
68
77
|
# The filename as given to `Rocco.new`.
|
@@ -82,7 +91,9 @@ class Rocco
|
|
82
91
|
|
83
92
|
#### Internal Parsing and Highlighting
|
84
93
|
|
85
|
-
# Parse the raw file data into a list of two-tuples.
|
94
|
+
# Parse the raw file data into a list of two-tuples. Each tuple has the
|
95
|
+
# form `[docs, code]` where both elements are arrays containing the
|
96
|
+
# raw lines parsed from the input file.
|
86
97
|
def parse(data)
|
87
98
|
sections = []
|
88
99
|
docs, code = [], []
|
@@ -94,8 +105,6 @@ class Rocco
|
|
94
105
|
docs, code = [], []
|
95
106
|
end
|
96
107
|
docs << line
|
97
|
-
when /^\s*$/
|
98
|
-
code << line
|
99
108
|
else
|
100
109
|
code << line
|
101
110
|
end
|
@@ -104,50 +113,59 @@ class Rocco
|
|
104
113
|
sections
|
105
114
|
end
|
106
115
|
|
107
|
-
# Take the
|
108
|
-
#
|
109
|
-
|
110
|
-
|
116
|
+
# Take the list of paired *sections* two-tuples and split into two
|
117
|
+
# separate lists: one holding the comments with leaders removed and
|
118
|
+
# one with the code blocks.
|
119
|
+
def split(sections)
|
111
120
|
docs_blocks, code_blocks = [], []
|
112
121
|
sections.each do |docs,code|
|
113
122
|
docs_blocks << docs.map { |line| line.sub(/^\s*#\s?/, '') }.join("\n")
|
114
123
|
code_blocks << code.join("\n")
|
115
124
|
end
|
125
|
+
[docs_blocks, code_blocks]
|
126
|
+
end
|
116
127
|
|
117
|
-
|
118
|
-
|
119
|
-
|
128
|
+
# Take the result of `split` and apply Markdown formatting to comments and
|
129
|
+
# syntax highlighting to source code.
|
130
|
+
def highlight(blocks)
|
131
|
+
docs_blocks, code_blocks = blocks
|
132
|
+
|
133
|
+
# Combine all docs blocks into a single big markdown document with section
|
134
|
+
# dividers and run through the Markdown processor. Then split it back out
|
135
|
+
# into separate sections.
|
136
|
+
markdown = docs_blocks.join("\n\n##### DIVIDER\n\n")
|
120
137
|
docs_html = Markdown.new(markdown, :smart).
|
121
138
|
to_html.
|
122
|
-
split(
|
139
|
+
split(/\n*<h5>DIVIDER<\/h5>\n*/m)
|
123
140
|
|
124
141
|
# Combine all code blocks into a single big stream and run through
|
125
|
-
#
|
126
|
-
#
|
142
|
+
# Pygments. We `popen` a read/write pygmentize process in the parent and
|
143
|
+
# then fork off a child process to write the input.
|
127
144
|
code_html = nil
|
128
145
|
open("|pygmentize -l ruby -f html", 'r+') do |fd|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
146
|
+
pid =
|
147
|
+
fork {
|
148
|
+
fd.close_read
|
149
|
+
fd.write code_blocks.join("\n\n# DIVIDER\n\n")
|
150
|
+
fd.close_write
|
151
|
+
exit!
|
152
|
+
}
|
136
153
|
fd.close_write
|
137
154
|
code_html = fd.read
|
138
155
|
fd.close_read
|
156
|
+
Process.wait(pid)
|
139
157
|
end
|
140
158
|
|
141
|
-
# Do some post-processing on the pygments output to
|
142
|
-
# partial `<pre>` blocks.
|
143
|
-
# document.
|
159
|
+
# Do some post-processing on the pygments output to split things back
|
160
|
+
# into sections and remove partial `<pre>` blocks.
|
144
161
|
code_html = code_html.
|
145
|
-
split(/\n
|
162
|
+
split(/\n*<span class="c1"># DIVIDER<\/span>\n*/m).
|
146
163
|
map { |code| code.sub(/\n?<div class="highlight"><pre>/m, '') }.
|
147
164
|
map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
|
148
165
|
|
149
|
-
#
|
150
|
-
# started with.
|
166
|
+
# Lastly, combine the docs and code lists back into a list of two-tuples.
|
151
167
|
docs_html.zip(code_html)
|
152
168
|
end
|
153
169
|
end
|
170
|
+
|
171
|
+
# And that's it.
|
data/lib/rocco/layout.mustache
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
</head>
|
8
8
|
<body>
|
9
9
|
<div id='container'>
|
10
|
+
<div id="background"></div>
|
10
11
|
<table cellspacing=0 cellpadding=0>
|
11
12
|
<thead>
|
12
13
|
<tr>
|
@@ -17,7 +18,12 @@
|
|
17
18
|
<tbody>
|
18
19
|
{{#sections}}
|
19
20
|
<tr id='section-{{ num }}'>
|
20
|
-
<td class=docs>
|
21
|
+
<td class=docs>
|
22
|
+
<div class="octowrap">
|
23
|
+
<a class="octothorpe" href="#section-{{ num }}">#</a>
|
24
|
+
</div>
|
25
|
+
{{{ docs }}}
|
26
|
+
</td>
|
21
27
|
<td class=code>
|
22
28
|
<div class='highlight'><pre>{{{ code }}}</pre></div>
|
23
29
|
</td>
|
data/lib/rocco/tasks.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
#### Rocco Rake Tasks
|
2
|
+
#
|
3
|
+
# To use the Rocco Rake tasks, require `rocco/tasks` in your `Rakefile`
|
4
|
+
# and define a Rake task with `rocco_task`. In its simplest form, `rocco_task`
|
5
|
+
# takes the path to a destination directory where HTML docs should be built:
|
6
|
+
#
|
7
|
+
# require 'rocco/tasks'
|
8
|
+
#
|
9
|
+
# desc "Build Rocco Docs"
|
10
|
+
# Rocco::make 'docs/'
|
11
|
+
#
|
12
|
+
# This creates a `:rocco` rake task, which can then be run with:
|
13
|
+
#
|
14
|
+
# rake rocco
|
15
|
+
#
|
16
|
+
# It's a good idea to guard against Rocco not being available, since your
|
17
|
+
# Rakefile will fail to load otherwise. Consider doing something like this,
|
18
|
+
# so that your Rakefile will still work
|
19
|
+
#
|
20
|
+
# begin
|
21
|
+
# require 'rocco/tasks'
|
22
|
+
# Rocco::make 'docs/'
|
23
|
+
# rescue LoadError
|
24
|
+
# warn "#$! -- rocco tasks not loaded."
|
25
|
+
# task :rocco
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# It's also possible to pass a glob pattern:
|
29
|
+
#
|
30
|
+
# Rocco::make 'html/', 'lib/thing/**/*.rb'
|
31
|
+
#
|
32
|
+
# Or a list of glob patterns:
|
33
|
+
#
|
34
|
+
# Rocco::make 'html/', ['lib/thing.rb', 'lib/thing/*.rb']
|
35
|
+
#
|
36
|
+
|
37
|
+
# Might be nice to defer this until we actually need to build docs but this
|
38
|
+
# will have to do for now.
|
39
|
+
require 'rocco'
|
40
|
+
|
41
|
+
# Reopen the Rocco class and add a `make` class method. This is a simple bit
|
42
|
+
# of sugar over `Rocco::Task.new`. If you want your Rake task to be named
|
43
|
+
# something other than `:rocco`, you can use `Rocco::Task` directly.
|
44
|
+
class Rocco
|
45
|
+
def self.make(dest='docs/', source_files='lib/**/*.rb')
|
46
|
+
Task.new(:rocco, dest, source_files)
|
47
|
+
end
|
48
|
+
|
49
|
+
# `Rocco::Task.new` takes a task name, the destination directory docs
|
50
|
+
# should be built under, and a source file pattern or file list.
|
51
|
+
class Task
|
52
|
+
def initialize(task_name, dest='docs/', sources='lib/**/*.rb')
|
53
|
+
@name = task_name
|
54
|
+
@dest = dest[-1] == ?/ ? dest : "#{dest}/"
|
55
|
+
@sources = FileList[sources]
|
56
|
+
|
57
|
+
# Make sure there's a `directory` task defined for our destination.
|
58
|
+
define_directory_task @dest
|
59
|
+
|
60
|
+
# Run over the source file list, constructing destination filenames
|
61
|
+
# and defining file tasks.
|
62
|
+
@sources.each do |source_file|
|
63
|
+
dest_file = File.basename(source_file, '.rb') + '.html'
|
64
|
+
define_file_task source_file, "#{@dest}#{dest_file}"
|
65
|
+
|
66
|
+
# If `rake/clean` was required, add the generated files to the list.
|
67
|
+
# That way all Rocco generated are removed when running `rake clean`.
|
68
|
+
CLEAN.include "#{@dest}#{dest_file}" if defined? CLEAN
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Define the destination directory task and make the `:rocco` task depend
|
73
|
+
# on it. This causes the destination directory to be created if it doesn't
|
74
|
+
# already exist.
|
75
|
+
def define_directory_task(path)
|
76
|
+
directory path
|
77
|
+
task @name => path
|
78
|
+
end
|
79
|
+
|
80
|
+
# Setup a `file` task for a single Rocco output file (`dest_file`). It
|
81
|
+
# depends on the source file, the destination directory, and all of Rocco's
|
82
|
+
# internal source code, so that the destination file is rebuilt when any of
|
83
|
+
# those changes.
|
84
|
+
#
|
85
|
+
# You can run these tasks directly with Rake:
|
86
|
+
#
|
87
|
+
# rake docs/foo.html docs/bar.html
|
88
|
+
#
|
89
|
+
# ... would generate the `foo.html` and `bar.html` files but only if they
|
90
|
+
# don't already exist or one of their dependencies was changed.
|
91
|
+
def define_file_task(source_file, dest_file)
|
92
|
+
prerequisites = [@dest, source_file] + rocco_source_files
|
93
|
+
file dest_file => prerequisites do |f|
|
94
|
+
verbose { puts "rocco: #{source_file} -> #{dest_file}" }
|
95
|
+
rocco = Rocco.new(source_file)
|
96
|
+
File.open(dest_file, 'wb') { |fd| fd.write(rocco.to_html) }
|
97
|
+
end
|
98
|
+
task @name => dest_file
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return a `FileList` that includes all of Roccos source files. This causes
|
102
|
+
# output files to be regenerated properly when someone upgrades the Rocco
|
103
|
+
# library.
|
104
|
+
def rocco_source_files
|
105
|
+
libdir = File.expand_path('../..', __FILE__)
|
106
|
+
FileList["#{libdir}/rocco.rb", "#{libdir}/rocco/**"]
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
data/rocco.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'rocco'
|
6
|
-
s.version = '0.
|
7
|
-
s.date = '2010-03-
|
6
|
+
s.version = '0.2'
|
7
|
+
s.date = '2010-03-11'
|
8
8
|
|
9
9
|
s.description = "Docco in Ruby"
|
10
10
|
s.summary = s.description
|
@@ -15,12 +15,13 @@ Gem::Specification.new do |s|
|
|
15
15
|
# = MANIFEST =
|
16
16
|
s.files = %w[
|
17
17
|
COPYING
|
18
|
-
README
|
18
|
+
README
|
19
19
|
Rakefile
|
20
20
|
bin/rocco
|
21
21
|
lib/rocco.rb
|
22
22
|
lib/rocco/layout.mustache
|
23
23
|
lib/rocco/layout.rb
|
24
|
+
lib/rocco/tasks.rb
|
24
25
|
rocco.gemspec
|
25
26
|
]
|
26
27
|
# = MANIFEST =
|
metadata
CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
7
|
+
- 2
|
8
|
+
version: "0.2"
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Ryan Tomayko
|
@@ -13,7 +13,7 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2010-03-
|
16
|
+
date: 2010-03-11 00:00:00 -08:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
@@ -50,12 +50,13 @@ extra_rdoc_files: []
|
|
50
50
|
|
51
51
|
files:
|
52
52
|
- COPYING
|
53
|
-
- README
|
53
|
+
- README
|
54
54
|
- Rakefile
|
55
55
|
- bin/rocco
|
56
56
|
- lib/rocco.rb
|
57
57
|
- lib/rocco/layout.mustache
|
58
58
|
- lib/rocco/layout.rb
|
59
|
+
- lib/rocco/tasks.rb
|
59
60
|
- rocco.gemspec
|
60
61
|
has_rdoc: true
|
61
62
|
homepage: http://rtomayko.github.com/rocco/
|
data/README.md
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
# rocco
|
2
|
-
|
3
|
-
This is a Ruby port of [Docco](http://jashkenas.github.com/docco/), a
|
4
|
-
_quick-and-dirty, hundred-line-long, literate-programming-style
|
5
|
-
documentation generator_.
|
6
|
-
|
7
|
-
See the [Rocco generated documentation](http://rtomayko.github.com/rocco/)
|
8
|
-
for more information.
|