rocco 0.1 → 0.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 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
- task :default => :test
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
- # read spec file and split out manifest section
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 = '#{Time.now.strftime("%Y-%m-%d")}'")
112
+ spec.sub!(/s.date = '.*'/, "s.date = '#{date}'")
57
113
  File.open(f.name, 'w') { |io| io.write(spec) }
58
- puts "updated #{f.name}"
114
+ puts "#{f.name} #{version} (#{date})"
59
115
  end
data/bin/rocco CHANGED
@@ -11,6 +11,11 @@ rescue LoadError
11
11
  warn "warn: #$!. trying again with rubygems"
12
12
  require 'rubygems'
13
13
  retry
14
+ else
15
+ require 'bluecloth'
16
+ Markdown = BlueCloth
17
+ $LOADED_FEATURES << 'rdiscount.rb'
18
+ retry
14
19
  end
15
20
  when /rocco/
16
21
  if !$:.include?(libdir)
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 can be installed with rubygems:
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
- # The [rdiscount](http://github.com/rtomayko/rdiscount) library is
34
- # required for Markdown processing.
35
- require 'rdiscount'
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` program.
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.1'
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
- # Parsing and highlighting
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 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.
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
- # 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")
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("\n<h5>DIVIDER</h5>\n")
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
- # pygments. We `popen` a pygmentize process and then fork off a
126
- # writer process.
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
- fork {
130
- fd.close_read
131
- fd.write code_blocks.join("\n# DIVIDER\n")
132
- fd.close_write
133
- exit!
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 remove
142
- # partial `<pre>` blocks. We'll add these back when we build to main
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?<span class="c1"># DIVIDER<\/span>\n?/m).
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
- # Combine the docs and code lists into the same sections style list we
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.
@@ -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>{{{ docs }}}</td>
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>
@@ -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.1'
7
- s.date = '2010-03-08'
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.md
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
- - 1
8
- version: "0.1"
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-08 00:00:00 -08:00
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.md
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.