fl-rocco 1.0.0
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/CHANGES.md +73 -0
- data/COPYING +18 -0
- data/README +23 -0
- data/Rakefile +115 -0
- data/bin/rocco +74 -0
- data/lib/rocco.rb +493 -0
- data/lib/rocco/comment_styles.rb +56 -0
- data/lib/rocco/layout.mustache +46 -0
- data/lib/rocco/layout.rb +64 -0
- data/lib/rocco/tasks.rb +123 -0
- data/lib/rocco/version.rb +3 -0
- data/rocco.gemspec +65 -0
- data/test/fixtures/issue10.iso-8859-1.rb +1 -0
- data/test/fixtures/issue10.utf-8.rb +1 -0
- data/test/helper.rb +25 -0
- data/test/suite.rb +5 -0
- data/test/test_basics.rb +63 -0
- data/test/test_block_comment_styles.rb +64 -0
- data/test/test_block_comments.rb +101 -0
- data/test/test_comment_normalization.rb +25 -0
- data/test/test_commentchar_detection.rb +28 -0
- data/test/test_descriptive_section_names.rb +30 -0
- data/test/test_docblock_annotations.rb +23 -0
- data/test/test_heredoc.rb +13 -0
- data/test/test_language_detection.rb +27 -0
- data/test/test_reported_issues.rb +84 -0
- data/test/test_skippable_lines.rb +64 -0
- data/test/test_source_list.rb +29 -0
- data/test/test_stylesheet.rb +23 -0
- metadata +110 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
class Rocco
|
2
|
+
module CommentStyles
|
3
|
+
C_STYLE_COMMENTS = {
|
4
|
+
:single => "//",
|
5
|
+
:multi => { :start => "/**", :middle => "*", :end => "*/" },
|
6
|
+
:heredoc => nil
|
7
|
+
}
|
8
|
+
|
9
|
+
COMMENT_STYLES = {
|
10
|
+
"bash" => { :single => "#", :multi => nil },
|
11
|
+
"c" => C_STYLE_COMMENTS,
|
12
|
+
"coffee-script" => {
|
13
|
+
:single => "#",
|
14
|
+
:multi => { :start => "###", :middle => nil, :end => "###" },
|
15
|
+
:heredoc => nil
|
16
|
+
},
|
17
|
+
"cpp" => C_STYLE_COMMENTS,
|
18
|
+
"csharp" => C_STYLE_COMMENTS,
|
19
|
+
"css" => {
|
20
|
+
:single => nil,
|
21
|
+
:multi => { :start => "/**", :middle => "*", :end => "*/" },
|
22
|
+
:heredoc => nil
|
23
|
+
},
|
24
|
+
"html" => {
|
25
|
+
:single => nil,
|
26
|
+
:multi => { :start => '<!--', :middle => nil, :end => '-->' },
|
27
|
+
:heredoc => nil
|
28
|
+
},
|
29
|
+
"java" => C_STYLE_COMMENTS,
|
30
|
+
"js" => C_STYLE_COMMENTS,
|
31
|
+
"lua" => {
|
32
|
+
:single => "--",
|
33
|
+
:multi => nil,
|
34
|
+
:heredoc => nil
|
35
|
+
},
|
36
|
+
"php" => C_STYLE_COMMENTS,
|
37
|
+
"python" => {
|
38
|
+
:single => "#",
|
39
|
+
:multi => { :start => '"""', :middle => nil, :end => '"""' },
|
40
|
+
:heredoc => nil
|
41
|
+
},
|
42
|
+
"rb" => {
|
43
|
+
:single => "#",
|
44
|
+
:multi => { :start => '=begin', :middle => nil, :end => '=end' },
|
45
|
+
:heredoc => "<<-"
|
46
|
+
},
|
47
|
+
"scala" => C_STYLE_COMMENTS,
|
48
|
+
"scheme" => { :single => ";;", :multi => nil, :heredoc => nil },
|
49
|
+
"xml" => {
|
50
|
+
:single => nil,
|
51
|
+
:multi => { :start => '<!--', :middle => nil, :end => '-->' },
|
52
|
+
:heredoc => nil
|
53
|
+
},
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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="{{ stylesheet }}">
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div id='container'>
|
10
|
+
<div id="background"></div>
|
11
|
+
{{#sources?}}
|
12
|
+
<div id="jump_to">
|
13
|
+
Jump To …
|
14
|
+
<div id="jump_wrapper">
|
15
|
+
<div id="jump_page">
|
16
|
+
{{#sources}}
|
17
|
+
<a class="source" href="{{ url }}">{{ basename }}</a>
|
18
|
+
{{/sources}}
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
{{/sources?}}
|
23
|
+
<table cellspacing=0 cellpadding=0>
|
24
|
+
<thead>
|
25
|
+
<tr>
|
26
|
+
<th class=docs><h1>{{ title }}</h1></th>
|
27
|
+
<th class=code></th>
|
28
|
+
</tr>
|
29
|
+
</thead>
|
30
|
+
<tbody>
|
31
|
+
{{#sections}}
|
32
|
+
<tr id='section-{{ section_id }}'>
|
33
|
+
<td class=docs>
|
34
|
+
<div class="pilwrap">
|
35
|
+
<a class="pilcrow" href="#section-{{ section_id }}">¶</a>
|
36
|
+
</div>
|
37
|
+
{{{ docs }}}
|
38
|
+
</td>
|
39
|
+
<td class=code>
|
40
|
+
<div class='highlight'><pre>{{{ code }}}</pre></div>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
{{/sections}}
|
44
|
+
</table>
|
45
|
+
</div>
|
46
|
+
</body>
|
data/lib/rocco/layout.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'mustache'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
class Rocco::Layout < Mustache
|
5
|
+
self.template_path = "#{File.dirname(__FILE__)}/.."
|
6
|
+
|
7
|
+
def initialize(doc, stylesheet, file=nil)
|
8
|
+
@doc = doc
|
9
|
+
@stylesheet = stylesheet
|
10
|
+
if not file.nil?
|
11
|
+
Rocco::Layout.template_file = file
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def title
|
16
|
+
File.basename(@doc.file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def stylesheet
|
20
|
+
@stylesheet
|
21
|
+
end
|
22
|
+
|
23
|
+
def file
|
24
|
+
@doc.file
|
25
|
+
end
|
26
|
+
|
27
|
+
def sections
|
28
|
+
num = 0
|
29
|
+
@doc.sections.map do |docs,code|
|
30
|
+
code ||= ''
|
31
|
+
is_header = /^<h.>(.+)<\/h.>$/.match( docs )
|
32
|
+
header_text = is_header && is_header[1].split.join("_")
|
33
|
+
num += 1
|
34
|
+
{
|
35
|
+
:docs => docs,
|
36
|
+
:docs? => !docs.empty?,
|
37
|
+
:header? => is_header,
|
38
|
+
|
39
|
+
:code => code,
|
40
|
+
:code? => !code.empty?,
|
41
|
+
|
42
|
+
:empty? => ( code.empty? && docs.empty? ),
|
43
|
+
:section_id => is_header ? header_text : num
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sources?
|
49
|
+
@doc.sources.length > 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def sources
|
53
|
+
currentpath = Pathname.new( File.dirname( @doc.file ) )
|
54
|
+
@doc.sources.sort.map do |source|
|
55
|
+
htmlpath = Pathname.new( source.sub( Regexp.new( "#{File.extname(source)}$"), ".html" ) )
|
56
|
+
|
57
|
+
{
|
58
|
+
:path => source,
|
59
|
+
:basename => File.basename(source),
|
60
|
+
:url => htmlpath.relative_path_from( currentpath )
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/rocco/tasks.rb
ADDED
@@ -0,0 +1,123 @@
|
|
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
|
+
# Finally, it is also possible to specify which Pygments language you would
|
37
|
+
# like to use to highlight the code, as well as the comment characters for the
|
38
|
+
# language in the `options` hash:
|
39
|
+
#
|
40
|
+
# Rocco::make 'html/', 'lib/thing/**/*.rb', {
|
41
|
+
# :language => 'io',
|
42
|
+
# :comment_chars => '#'
|
43
|
+
# }
|
44
|
+
#
|
45
|
+
|
46
|
+
# Might be nice to defer this until we actually need to build docs but this
|
47
|
+
# will have to do for now.
|
48
|
+
require 'rocco'
|
49
|
+
|
50
|
+
# Reopen the Rocco class and add a `make` class method. This is a simple bit
|
51
|
+
# of sugar over `Rocco::Task.new`. If you want your Rake task to be named
|
52
|
+
# something other than `:rocco`, you can use `Rocco::Task` directly.
|
53
|
+
class Rocco
|
54
|
+
def self.make(dest='docs/', source_files='lib/**/*.rb', options={})
|
55
|
+
Task.new(:rocco, dest, source_files, options)
|
56
|
+
end
|
57
|
+
|
58
|
+
# `Rocco::Task.new` takes a task name, the destination directory docs
|
59
|
+
# should be built under, and a source file pattern or file list.
|
60
|
+
class Task
|
61
|
+
include Rake::DSL if defined?(Rake::DSL)
|
62
|
+
|
63
|
+
def initialize(task_name, dest='docs/', sources='lib/**/*.rb', options={})
|
64
|
+
@name = task_name
|
65
|
+
@dest = dest[-1] == ?/ ? dest : "#{dest}/"
|
66
|
+
@sources = FileList[sources]
|
67
|
+
@options = options
|
68
|
+
|
69
|
+
# Make sure there's a `directory` task defined for our destination.
|
70
|
+
define_directory_task @dest
|
71
|
+
|
72
|
+
# Run over the source file list, constructing destination filenames
|
73
|
+
# and defining file tasks.
|
74
|
+
@sources.each do |source_file|
|
75
|
+
dest_file = source_file.sub(Regexp.new("#{File.extname(source_file)}$"), ".html")
|
76
|
+
define_file_task source_file, "#{@dest}#{dest_file}"
|
77
|
+
|
78
|
+
# If `rake/clean` was required, add the generated files to the list.
|
79
|
+
# That way all Rocco generated are removed when running `rake clean`.
|
80
|
+
CLEAN.include "#{@dest}#{dest_file}" if defined? CLEAN
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Define the destination directory task and make the `:rocco` task depend
|
85
|
+
# on it. This causes the destination directory to be created if it doesn't
|
86
|
+
# already exist.
|
87
|
+
def define_directory_task(path)
|
88
|
+
directory path
|
89
|
+
task @name => path
|
90
|
+
end
|
91
|
+
|
92
|
+
# Setup a `file` task for a single Rocco output file (`dest_file`). It
|
93
|
+
# depends on the source file, the destination directory, and all of Rocco's
|
94
|
+
# internal source code, so that the destination file is rebuilt when any of
|
95
|
+
# those changes.
|
96
|
+
#
|
97
|
+
# You can run these tasks directly with Rake:
|
98
|
+
#
|
99
|
+
# rake docs/foo.html docs/bar.html
|
100
|
+
#
|
101
|
+
# ... would generate the `foo.html` and `bar.html` files but only if they
|
102
|
+
# don't already exist or one of their dependencies was changed.
|
103
|
+
def define_file_task(source_file, dest_file)
|
104
|
+
prerequisites = [@dest, source_file] + rocco_source_files
|
105
|
+
file dest_file => prerequisites do |f|
|
106
|
+
verbose { puts "rocco: #{source_file} -> #{dest_file}" }
|
107
|
+
rocco = Rocco.new(source_file, @sources.to_a, @options)
|
108
|
+
FileUtils.mkdir_p(File.dirname(dest_file))
|
109
|
+
File.open(dest_file, 'wb') { |fd| fd.write(rocco.to_html) }
|
110
|
+
end
|
111
|
+
task @name => dest_file
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return a `FileList` that includes all of Roccos source files. This causes
|
115
|
+
# output files to be regenerated properly when someone upgrades the Rocco
|
116
|
+
# library.
|
117
|
+
def rocco_source_files
|
118
|
+
libdir = File.expand_path('../..', __FILE__)
|
119
|
+
FileList["#{libdir}/rocco.rb", "#{libdir}/rocco/**"]
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
data/rocco.gemspec
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# rocco.gemspec
|
2
|
+
#
|
3
|
+
# To update this file's version, date, and file list, change the VERSION
|
4
|
+
# constant in lib/rocco.rb and run `rake rocco.gemspec`.
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
+
|
10
|
+
s.name = 'fl-rocco'
|
11
|
+
s.version = '1.0.0'
|
12
|
+
s.date = '2012-01-10'
|
13
|
+
|
14
|
+
s.description = "Docco in Ruby"
|
15
|
+
s.summary = s.description
|
16
|
+
|
17
|
+
s.authors = ["Ryan Tomayko", "Mike West"]
|
18
|
+
s.email = ["r@tomayko.com", "<mike@mikewest.org>"]
|
19
|
+
|
20
|
+
# = MANIFEST =
|
21
|
+
s.files = %w[
|
22
|
+
CHANGES.md
|
23
|
+
COPYING
|
24
|
+
README
|
25
|
+
Rakefile
|
26
|
+
bin/rocco
|
27
|
+
lib/rocco.rb
|
28
|
+
lib/rocco/comment_styles.rb
|
29
|
+
lib/rocco/layout.mustache
|
30
|
+
lib/rocco/layout.rb
|
31
|
+
lib/rocco/tasks.rb
|
32
|
+
lib/rocco/version.rb
|
33
|
+
rocco.gemspec
|
34
|
+
test/fixtures/issue10.iso-8859-1.rb
|
35
|
+
test/fixtures/issue10.utf-8.rb
|
36
|
+
test/helper.rb
|
37
|
+
test/suite.rb
|
38
|
+
test/test_basics.rb
|
39
|
+
test/test_block_comment_styles.rb
|
40
|
+
test/test_block_comments.rb
|
41
|
+
test/test_comment_normalization.rb
|
42
|
+
test/test_commentchar_detection.rb
|
43
|
+
test/test_descriptive_section_names.rb
|
44
|
+
test/test_docblock_annotations.rb
|
45
|
+
test/test_heredoc.rb
|
46
|
+
test/test_language_detection.rb
|
47
|
+
test/test_reported_issues.rb
|
48
|
+
test/test_skippable_lines.rb
|
49
|
+
test/test_source_list.rb
|
50
|
+
test/test_stylesheet.rb
|
51
|
+
]
|
52
|
+
# = MANIFEST =
|
53
|
+
|
54
|
+
s.executables = ["rocco"]
|
55
|
+
|
56
|
+
s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
|
57
|
+
s.add_dependency 'redcarpet', '~> 1.17'
|
58
|
+
s.add_dependency 'mustache'
|
59
|
+
s.add_development_dependency 'rake', '~> 0.9'
|
60
|
+
|
61
|
+
s.has_rdoc = false
|
62
|
+
s.homepage = "http://rtomayko.github.com/rocco/"
|
63
|
+
s.require_paths = %w[lib]
|
64
|
+
s.rubygems_version = '1.1.1'
|
65
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# hello w�rld
|
@@ -0,0 +1 @@
|
|
1
|
+
# hello ąćęłńóśźż
|
data/test/helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
rootdir = File.expand_path('../../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift "#{rootdir}/lib"
|
3
|
+
|
4
|
+
require 'test/unit'
|
5
|
+
begin; require 'turn'; rescue LoadError; end
|
6
|
+
begin
|
7
|
+
require 'rdiscount'
|
8
|
+
rescue LoadError
|
9
|
+
if !defined?(Gem)
|
10
|
+
require 'rubygems'
|
11
|
+
retry
|
12
|
+
end
|
13
|
+
end
|
14
|
+
require 'rocco'
|
15
|
+
|
16
|
+
def roccoize( filename, contents, options = {} )
|
17
|
+
Rocco.new( filename, [ filename ], options ) {
|
18
|
+
contents
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def fb_assert_val( str )
|
23
|
+
return str.strip if Rocco::MD_BLUECLOTH
|
24
|
+
str
|
25
|
+
end
|
data/test/suite.rb
ADDED
data/test/test_basics.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
class RoccoBasicTests < Test::Unit::TestCase
|
4
|
+
def test_rocco_exists_and_is_instancable
|
5
|
+
roccoize( "filename.rb", "# Comment 1\ndef codeblock\nend\n" )
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_filename
|
9
|
+
r = roccoize( "filename.rb", "# Comment 1\ndef codeblock\nend\n" )
|
10
|
+
assert_equal "filename.rb", r.file
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_sources
|
14
|
+
r = roccoize( "filename.rb", "# Comment 1\ndef codeblock\nend\n" )
|
15
|
+
assert_equal [ "filename.rb" ], r.sources
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_sections
|
19
|
+
r = roccoize( "filename.rb", "# Comment 1\ndef codeblock\nend\n" )
|
20
|
+
assert_equal 1, r.sections.length
|
21
|
+
assert_equal 2, r.sections[ 0 ].length
|
22
|
+
assert_equal fb_assert_val("<p>Comment 1</p>\n"), r.sections[ 0 ][ 0 ]
|
23
|
+
assert_equal "<span class=\"k\">def</span> <span class=\"nf\">codeblock</span>\n<span class=\"k\">end</span>", r.sections[ 0 ][ 1 ]
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_parsing
|
27
|
+
r = Rocco.new( 'test' ) { "" } # Generate throwaway instance so I can test `parse`
|
28
|
+
assert_equal(
|
29
|
+
[
|
30
|
+
[ [ "Comment 1" ], [ "def codeblock", "end" ] ]
|
31
|
+
],
|
32
|
+
r.parse( "# Comment 1\ndef codeblock\nend\n" )
|
33
|
+
)
|
34
|
+
assert_equal(
|
35
|
+
[
|
36
|
+
[ [ "Comment 1" ], [ "def codeblock" ] ],
|
37
|
+
[ [ "Comment 2" ], [ "end" ] ]
|
38
|
+
],
|
39
|
+
r.parse( "# Comment 1\ndef codeblock\n# Comment 2\nend\n" )
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_splitting
|
44
|
+
r = Rocco.new( 'test' ) { "" } # Generate throwaway instance so I can test `split`
|
45
|
+
assert_equal(
|
46
|
+
[
|
47
|
+
[ "Comment 1" ],
|
48
|
+
[ "def codeblock\nend" ]
|
49
|
+
],
|
50
|
+
r.split([ [ [ "Comment 1" ], [ "def codeblock", "end" ] ] ])
|
51
|
+
)
|
52
|
+
assert_equal(
|
53
|
+
[
|
54
|
+
[ "Comment 1", "Comment 2" ],
|
55
|
+
[ "def codeblock", "end" ]
|
56
|
+
],
|
57
|
+
r.split( [
|
58
|
+
[ [ "Comment 1" ], [ "def codeblock" ] ],
|
59
|
+
[ [ "Comment 2" ], [ "end" ] ]
|
60
|
+
] )
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|