rocco 0.1

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/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2010 Ryan Tomayko <http://tomayko.com/about>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,8 @@
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.
data/Rakefile ADDED
@@ -0,0 +1,59 @@
1
+ require 'rake/testtask'
2
+ task :default => :test
3
+
4
+ desc 'Run tests (default)'
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.ruby_opts = ['-rubygems'] if defined? Gem
8
+ end
9
+
10
+ # PACKAGING =================================================================
11
+
12
+ if defined?(Gem)
13
+ SPEC = eval(File.read('rocco.gemspec'))
14
+
15
+ def package(ext='')
16
+ "pkg/rocco-#{SPEC.version}" + ext
17
+ end
18
+
19
+ desc 'Build packages'
20
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
21
+
22
+ desc 'Build and install as local gem'
23
+ task :install => package('.gem') do
24
+ sh "gem install #{package('.gem')}"
25
+ end
26
+
27
+ directory 'pkg/'
28
+
29
+ file package('.gem') => %w[pkg/ rocco.gemspec] + SPEC.files do |f|
30
+ sh "gem build rocco.gemspec"
31
+ mv File.basename(f.name), f.name
32
+ end
33
+
34
+ file package('.tar.gz') => %w[pkg/] + SPEC.files do |f|
35
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
36
+ end
37
+ end
38
+
39
+ # GEMSPEC ===================================================================
40
+
41
+ file 'rocco.gemspec' => FileList['{lib,test,bin}/**','Rakefile'] do |f|
42
+ # read version from tilt.rb
43
+ version = File.read('lib/rocco.rb')[/VERSION = '(.*)'/] && $1
44
+ # read spec file and split out manifest section
45
+ spec = File.
46
+ read(f.name).
47
+ sub(/s\.version\s*=\s*'.*'/, "s.version = '#{version}'")
48
+ parts = spec.split(" # = MANIFEST =\n")
49
+ # determine file list from git ls-files
50
+ files = `git ls-files`.
51
+ split("\n").sort.reject{ |file| file =~ /^\./ }.
52
+ map{ |file| " #{file}" }.join("\n")
53
+ # piece file back together and write...
54
+ parts[1] = " s.files = %w[\n#{files}\n ]\n"
55
+ spec = parts.join(" # = MANIFEST =\n")
56
+ spec.sub!(/s.date = '.*'/, "s.date = '#{Time.now.strftime("%Y-%m-%d")}'")
57
+ File.open(f.name, 'w') { |io| io.write(spec) }
58
+ puts "updated #{f.name}"
59
+ end
data/bin/rocco ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ libdir = File.expand_path('../../lib', __FILE__).sub(/^#{Dir.pwd}\//, '')
3
+
4
+ begin
5
+ require 'rdiscount'
6
+ require 'rocco'
7
+ rescue LoadError
8
+ case $!.to_s
9
+ when /rdiscount/
10
+ if !defined?(Gem)
11
+ warn "warn: #$!. trying again with rubygems"
12
+ require 'rubygems'
13
+ retry
14
+ end
15
+ when /rocco/
16
+ if !$:.include?(libdir)
17
+ warn "warn: #$!. trying again with #{libdir} on load path"
18
+ $:.unshift(libdir)
19
+ retry
20
+ end
21
+ end
22
+ raise
23
+ end
24
+
25
+ ARGV.each do |filename|
26
+ rocco = Rocco.new(filename)
27
+ dest = File.basename(filename, '.rb') + '.html'
28
+ warn "rocco: #{filename} -> #{dest}"
29
+ File.open(dest, 'wb') { |fd| fd.write(rocco.to_html) }
30
+ end
data/lib/rocco.rb ADDED
@@ -0,0 +1,153 @@
1
+ # **Rocco** is a Ruby port of [Docco][do], the quick-and-dirty,
2
+ # hundred-line-long, literate-programming-style documentation generator.
3
+ #
4
+ # Rocco reads Ruby source files and produces annotated source documentation
5
+ # in HTML format. Comments are formatted with [Markdown][md] and presented
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.
8
+ #
9
+ # Most of this was written while waiting for [node.js][no] to build (so I
10
+ # could use Docco!). Docco's gorgeous HTML and CSS are taken verbatim.
11
+ # The main difference is that Rocco is written in Ruby instead of
12
+ # [CoffeeScript][co] and may be a bit easier to obtain and install in
13
+ # existing Ruby environments or where node doesn't run yet.
14
+ #
15
+ # Rocco can be installed with rubygems:
16
+ #
17
+ # gem install rocco
18
+ #
19
+ # Once installed, the `rocco` command can be used to generate documentation
20
+ # for a set of Ruby source files:
21
+ #
22
+ # rocco lib/*.rb
23
+ #
24
+ # The HTML files are written to the current working directory.
25
+ #
26
+ # [no]: http://nodejs.org/
27
+ # [do]: http://jashkenas.github.com/docco/
28
+ # [co]: http://coffeescript.org/
29
+ # [md]: http://daringfireball.net/projects/markdown/
30
+
31
+ #### Prerequisites
32
+
33
+ # The [rdiscount](http://github.com/rtomayko/rdiscount) library is
34
+ # required for Markdown processing.
35
+ require 'rdiscount'
36
+
37
+ # We use [{{ mustache }}](http://defunkt.github.com/mustache/) for
38
+ # templating.
39
+ require 'mustache'
40
+
41
+ # Code is run through [Pygments](http://pygments.org/) for syntax
42
+ # highlighting. Fail fast if we can't find the `pygmentize` program.
43
+ if ! ENV['PATH'].split(':').any? { |dir| File.exist?("#{dir}/pygmentize") }
44
+ fail "Pygments is required for syntax highlighting"
45
+ end
46
+
47
+ #### Public Interface
48
+
49
+ # `Rocco.new` takes a source `filename` and an optional `block`.
50
+ # When `block` is given, it must read the contents of the file using
51
+ # whatever means necessary and return it as a string. With no `block`, the
52
+ # file is read to retrieve data.
53
+ class Rocco
54
+ VERSION = '0.1'
55
+
56
+ def initialize(filename, &block)
57
+ @file = filename
58
+ @data =
59
+ if block_given?
60
+ yield
61
+ else
62
+ File.read(filename)
63
+ end
64
+ # Parsing and highlighting
65
+ @sections = highlight(parse(@data))
66
+ end
67
+
68
+ # The filename as given to `Rocco.new`.
69
+ attr_reader :file
70
+
71
+ # A list of two-tuples representing each *section* of the source file. Each
72
+ # item in the list has the form: `[docs_html, code_html]`, where both
73
+ # elements are strings containing the documentation and source code HTML,
74
+ # respectively.
75
+ attr_reader :sections
76
+
77
+ # Generate HTML output for the entire document.
78
+ require 'rocco/layout'
79
+ def to_html
80
+ Rocco::Layout.new(self).render
81
+ end
82
+
83
+ #### Internal Parsing and Highlighting
84
+
85
+ # Parse the raw file data into a list of two-tuples.
86
+ def parse(data)
87
+ sections = []
88
+ docs, code = [], []
89
+ data.split("\n").each do |line|
90
+ case line
91
+ when /^\s*#/
92
+ if code.any?
93
+ sections << [docs, code]
94
+ docs, code = [], []
95
+ end
96
+ docs << line
97
+ when /^\s*$/
98
+ code << line
99
+ else
100
+ code << line
101
+ end
102
+ end
103
+ sections << [docs, code] if docs.any? || code.any?
104
+ sections
105
+ end
106
+
107
+ # Take the raw section data and apply markdown formatting and syntax
108
+ # highlighting.
109
+ def highlight(sections)
110
+ # Start by splitting the docs and codes blocks into two separate lists.
111
+ docs_blocks, code_blocks = [], []
112
+ sections.each do |docs,code|
113
+ docs_blocks << docs.map { |line| line.sub(/^\s*#\s?/, '') }.join("\n")
114
+ code_blocks << code.join("\n")
115
+ end
116
+
117
+ # Combine all docs blocks into a single big markdown document and run
118
+ # through RDiscount. Then split it back out into separate sections.
119
+ markdown = docs_blocks.join("\n##### DIVIDER\n")
120
+ docs_html = Markdown.new(markdown, :smart).
121
+ to_html.
122
+ split("\n<h5>DIVIDER</h5>\n")
123
+
124
+ # Combine all code blocks into a single big stream and run through
125
+ # pygments. We `popen` a pygmentize process and then fork off a
126
+ # writer process.
127
+ code_html = nil
128
+ open("|pygmentize -l ruby -f html", 'r+') do |fd|
129
+ fork {
130
+ fd.close_read
131
+ fd.write code_blocks.join("\n# DIVIDER\n")
132
+ fd.close_write
133
+ exit!
134
+ }
135
+
136
+ fd.close_write
137
+ code_html = fd.read
138
+ fd.close_read
139
+ end
140
+
141
+ # Do some post-processing on the pygments output to remove
142
+ # partial `<pre>` blocks. We'll add these back when we build to main
143
+ # document.
144
+ code_html = code_html.
145
+ split(/\n?<span class="c1"># DIVIDER<\/span>\n?/m).
146
+ map { |code| code.sub(/\n?<div class="highlight"><pre>/m, '') }.
147
+ map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
148
+
149
+ # Combine the docs and code lists into the same sections style list we
150
+ # started with.
151
+ docs_html.zip(code_html)
152
+ end
153
+ end
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>{{ title }}</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <table cellspacing=0 cellpadding=0>
11
+ <thead>
12
+ <tr>
13
+ <th class=docs><h1>{{ title }}</h1></th>
14
+ <th class=code></th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ {{#sections}}
19
+ <tr id='section-{{ num }}'>
20
+ <td class=docs>{{{ docs }}}</td>
21
+ <td class=code>
22
+ <div class='highlight'><pre>{{{ code }}}</pre></div>
23
+ </td>
24
+ </tr>
25
+ {{/sections}}
26
+ </table>
27
+ </div>
28
+ </body>
@@ -0,0 +1,24 @@
1
+ require 'mustache'
2
+
3
+ class Rocco::Layout < Mustache
4
+ self.template_path = File.dirname(__FILE__)
5
+
6
+ def initialize(doc)
7
+ @doc = doc
8
+ end
9
+
10
+ def title
11
+ File.basename(@doc.file)
12
+ end
13
+
14
+ def sections
15
+ num = 0
16
+ @doc.sections.map do |docs,code|
17
+ {
18
+ :docs => docs,
19
+ :code => code,
20
+ :num => (num += 1)
21
+ }
22
+ end
23
+ end
24
+ end
data/rocco.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+
5
+ s.name = 'rocco'
6
+ s.version = '0.1'
7
+ s.date = '2010-03-08'
8
+
9
+ s.description = "Docco in Ruby"
10
+ s.summary = s.description
11
+
12
+ s.authors = ["Ryan Tomayko"]
13
+ s.email = "r@tomayko.com"
14
+
15
+ # = MANIFEST =
16
+ s.files = %w[
17
+ COPYING
18
+ README.md
19
+ Rakefile
20
+ bin/rocco
21
+ lib/rocco.rb
22
+ lib/rocco/layout.mustache
23
+ lib/rocco/layout.rb
24
+ rocco.gemspec
25
+ ]
26
+ # = MANIFEST =
27
+
28
+ s.executables = ["rocco"]
29
+
30
+ s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
31
+ s.add_dependency 'rdiscount'
32
+ s.add_dependency 'mustache'
33
+
34
+ s.has_rdoc = false
35
+ s.homepage = "http://rtomayko.github.com/rocco/"
36
+ s.require_paths = %w[lib]
37
+ s.rubygems_version = '1.1.1'
38
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rocco
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Ryan Tomayko
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-03-08 00:00:00 -08:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rdiscount
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 0
28
+ version: "0"
29
+ type: :runtime
30
+ version_requirements: *id001
31
+ - !ruby/object:Gem::Dependency
32
+ name: mustache
33
+ prerelease: false
34
+ requirement: &id002 !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ segments:
39
+ - 0
40
+ version: "0"
41
+ type: :runtime
42
+ version_requirements: *id002
43
+ description: Docco in Ruby
44
+ email: r@tomayko.com
45
+ executables:
46
+ - rocco
47
+ extensions: []
48
+
49
+ extra_rdoc_files: []
50
+
51
+ files:
52
+ - COPYING
53
+ - README.md
54
+ - Rakefile
55
+ - bin/rocco
56
+ - lib/rocco.rb
57
+ - lib/rocco/layout.mustache
58
+ - lib/rocco/layout.rb
59
+ - rocco.gemspec
60
+ has_rdoc: true
61
+ homepage: http://rtomayko.github.com/rocco/
62
+ licenses: []
63
+
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
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.6
87
+ signing_key:
88
+ specification_version: 2
89
+ summary: Docco in Ruby
90
+ test_files: []
91
+