docapi 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +7 -0
  5. data/Rakefile +57 -0
  6. data/VERSION +1 -0
  7. data/bin/docapi +47 -0
  8. data/docapi.gemspec +76 -0
  9. data/files/javascripts/documentation/documentation.js +26 -0
  10. data/files/javascripts/documentation/highlight.pack.js +1 -0
  11. data/files/javascripts/documentation/jquery-1.3.2.min.js +19 -0
  12. data/files/javascripts/documentation/jquery.tableofcontents.min.js +12 -0
  13. data/files/stylesheets/documentation/highlighter/ascetic.css +42 -0
  14. data/files/stylesheets/documentation/highlighter/brown_paper.css +104 -0
  15. data/files/stylesheets/documentation/highlighter/brown_papersq.png +0 -0
  16. data/files/stylesheets/documentation/highlighter/dark.css +101 -0
  17. data/files/stylesheets/documentation/highlighter/default.css +103 -0
  18. data/files/stylesheets/documentation/highlighter/far.css +113 -0
  19. data/files/stylesheets/documentation/highlighter/github.css +90 -0
  20. data/files/stylesheets/documentation/highlighter/idea.css +74 -0
  21. data/files/stylesheets/documentation/highlighter/ir_black.css +67 -0
  22. data/files/stylesheets/documentation/highlighter/magula.css +105 -0
  23. data/files/stylesheets/documentation/highlighter/school_book.css +106 -0
  24. data/files/stylesheets/documentation/highlighter/school_book.png +0 -0
  25. data/files/stylesheets/documentation/highlighter/sunburst.css +112 -0
  26. data/files/stylesheets/documentation/highlighter/vs.css +68 -0
  27. data/files/stylesheets/documentation/highlighter/zenburn.css +113 -0
  28. data/files/stylesheets/documentation/layout.css +161 -0
  29. data/lib/docapi.rb +150 -0
  30. data/test/code/reference_api.rb +141 -0
  31. data/test/doc/1-README.md +17 -0
  32. data/test/doc/2-documentation/documentation.html +186 -0
  33. data/test/doc/3-tutorials/2-ruby/example-1.rb +12 -0
  34. metadata +89 -0
@@ -0,0 +1,113 @@
1
+ /*
2
+
3
+ Zenburn style from voldmar.ru (c) Vladimir Epifanov <voldmar@voldmar.ru>
4
+ based on dark.css by Ivan Sagalaev
5
+
6
+ */
7
+
8
+ pre code[class]:after {
9
+ content: 'highlight: ' attr(class);
10
+ display: block; text-align: right;
11
+ font-size: smaller;
12
+ color: #CCC; background: white;
13
+ border-top: solid 1px black;
14
+ padding-top: 0.5em;
15
+ }
16
+
17
+ pre code {
18
+ display: block;
19
+ background: #3F3F3F;
20
+ color: #DCDCDC;
21
+ }
22
+
23
+ .keyword,
24
+ .tag,
25
+ .django .tag,
26
+ .django .keyword,
27
+ .css .class,
28
+ .css .id,
29
+ .lisp .title {
30
+ color: #E3CEAB;
31
+ }
32
+
33
+ .django .template_tag,
34
+ .django .variable,
35
+ .django .filter .argument {
36
+ color: #DCDCDC;
37
+ }
38
+
39
+ .number,
40
+ .date {
41
+ color: #8CD0D3;
42
+ }
43
+
44
+ .dos .envvar,
45
+ .dos .stream,
46
+ .variable,
47
+ .apache .sqbracket {
48
+ color: #EFDCBC;
49
+ }
50
+
51
+ .dos .flow,
52
+ .diff .change,
53
+ .python .exception,
54
+ .python .built_in,
55
+ .literal {
56
+ color: #EFEFAF;
57
+ }
58
+
59
+ .diff .chunk,
60
+ .ruby .subst {
61
+ color: #8F8F8F;
62
+ }
63
+
64
+ .dos .keyword,
65
+ .python .decorator,
66
+ .class .title,
67
+ .function .title,
68
+ .ini .title,
69
+ .diff .header,
70
+ .ruby .class .parent,
71
+ .apache .tag {
72
+ color: #efef8f;
73
+ }
74
+
75
+ .dos .winutils,
76
+ .ruby .symbol,
77
+ .ruby .string,
78
+ .ruby .instancevar {
79
+ color: #DCA3A3;
80
+ }
81
+
82
+ .diff .deletion,
83
+ .string,
84
+ .tag .attribute .value,
85
+ .preprocessor,
86
+ .built_in,
87
+ .sql .aggregate,
88
+ .javadoc,
89
+ .smalltalk .class,
90
+ .smalltalk .localvars,
91
+ .smalltalk .array,
92
+ .css .rules .value,
93
+ .attr_selector,
94
+ .pseudo,
95
+ .apache .cbracket {
96
+ color: #CC9393;
97
+ }
98
+
99
+ .shebang,
100
+ .diff .addition,
101
+ .comment,
102
+ .java .annotation,
103
+ .template_comment,
104
+ .pi,
105
+ .doctype {
106
+ color: #7F9F7F;
107
+ }
108
+
109
+ .html .css,
110
+ .html .javascript {
111
+ opacity: 0.5;
112
+ }
113
+
@@ -0,0 +1,161 @@
1
+ body {
2
+ /* font-size: 16px;*/
3
+ color:black;
4
+ font-family:Lucida Grande,Verdana,Arial,Helvetica,sans-serif;
5
+ font-size:90%;
6
+ width: auto;
7
+ margin: auto;
8
+ padding: 20px 300px 20px 40px;
9
+ }
10
+ h1, h2, h3, h4, h5 {
11
+ position: relative;
12
+ }
13
+ h1 {
14
+ border-bottom: 1px solid #eee;
15
+ color:#0E3062;
16
+ font-size:1.8em;
17
+ margin:0.8em 0 0.3em;
18
+ }
19
+ h2 {
20
+ font-size: 1.4em;
21
+ font-family: 'Bitstream Vera Sans Mono', Monaco, monospace, courier, 'courier new';
22
+ }
23
+ h3 {
24
+ font-family: "Courier New";
25
+ }
26
+ pre
27
+ {
28
+ /* margin: 0 0 10px 0;*/
29
+ /* padding: 10px;*/
30
+ font-size: 12px;
31
+ line-height: 150%;
32
+ font-family: 'Bitstream Vera Sans Mono', Monaco, monospace, courier, 'courier new';
33
+ background: #F8F8FF;
34
+ color: #111;
35
+ /* border: 1px solid #ddd;*/
36
+ }
37
+ pre.hidden {
38
+ cursor: pointer;
39
+ }
40
+ code, tt {
41
+ overflow: auto;
42
+ font-family: 'Bitstream Vera Sans Mono', Monaco, monospace, courier, 'courier new';
43
+ padding: 0 2px;
44
+ background: #f1f1f1;
45
+ font-size: .9em;
46
+ border-bottom: 1px solid #ddd;
47
+ }
48
+
49
+ pre.hidden:after {
50
+ content: 'hidden';
51
+ display: block; text-align: center;
52
+ font-size: smaller;
53
+ color: #000; background: white;
54
+ border-top: solid 1px #ccc;
55
+ padding-top: 0.5em;
56
+ }
57
+
58
+ pre code
59
+ {
60
+ background: transparent;
61
+ }
62
+
63
+ table.code {
64
+ width: 100%;
65
+ }
66
+
67
+ div.code pre {
68
+ margin: 0;
69
+ }
70
+ p {
71
+ margin-top: 0px;
72
+ margin-bottom: 0.5em;
73
+ }
74
+ li > p:first-child:first-line {
75
+ background-color: #ffffe0;
76
+ padding: 0px 8px;
77
+ }
78
+ span.replace {
79
+ color: orange;
80
+ }
81
+ a > span.replace {
82
+ color: inherit;
83
+ }
84
+
85
+ p.page-title {
86
+ color: #880000;
87
+ font-weight: bold;
88
+ font-size: 2em;
89
+ }
90
+ .docapi-section {
91
+ margin-left: 15px;
92
+ }
93
+ .docapi-subsection {
94
+ padding: 5px;
95
+ margin-bottom: 20px;
96
+ }
97
+ .docapi-subsection .docapi-title {
98
+ padding: 3px 10px;
99
+ font-size: 1.4em;
100
+ background: #336699;
101
+ color: #fff;
102
+ margin-bottom: 10px;
103
+ font-weight: bold;
104
+ font-family: "Courier New";
105
+ }
106
+ .docapi-subsection .docapi-subtitle {
107
+ font-size: 1.1em;
108
+ font-weight: bold;
109
+ font-family: 'Bitstream Vera Sans Mono', Monaco, monospace, courier, 'courier new';
110
+ margin:20px 2px 5px 0px;
111
+ border-left: 5px solid orange;
112
+ padding-left: 5px;
113
+ }
114
+ table {
115
+ font-size: 0.8em;
116
+ }
117
+
118
+ /*#toc {
119
+ float: right;
120
+ font-size: 10pt;
121
+ width: 200px;
122
+ padding: 10px 10px 10px 20px;
123
+ background: #efffb1;
124
+ border: solid 1px #ccd136;
125
+ margin: 0 0 10px 15px;
126
+ }*/
127
+
128
+
129
+
130
+ #toc {
131
+ position: fixed;
132
+ top: 20px;
133
+ background: none;
134
+ border: none;
135
+ right: 20px;
136
+ border-left: solid 5px #ddd;
137
+ width: 260px;
138
+ /* bottom: 20px;*/
139
+ height: 100%;
140
+ -webkit-box-sizing: border-box;
141
+ -moz-box-sizing: border-box;
142
+ }
143
+ #toc li {
144
+ padding: 5px;
145
+ }
146
+ #toc a {
147
+ background: #efffb1;
148
+ }
149
+ a.toc-top-link {
150
+ -moz-background-clip:border;
151
+ -moz-background-inline-policy:continuous;
152
+ -moz-background-origin:padding;
153
+ background:#EEEEEE none repeat scroll 0 0;
154
+ font-size:8pt;
155
+ left:-40px;
156
+ padding:4px;
157
+ position:absolute;
158
+ text-align:center;
159
+ top:5px;
160
+ width:30px;
161
+ }
data/lib/docapi.rb ADDED
@@ -0,0 +1,150 @@
1
+ require 'pathname'
2
+ require 'tempfile'
3
+ require 'maruku'
4
+ require 'fileutils'
5
+
6
+ class Docapi
7
+
8
+ FILES_TO_INCLUDE = {
9
+ :javascripts => ["./javascripts/documentation/highlight.pack.js", "./javascripts/documentation/jquery-1.3.2.min.js", "./javascripts/documentation/jquery.tableofcontents.min.js", "./javascripts/documentation/documentation.js"],
10
+ :stylesheets => ["./stylesheets/documentation/layout.css", "./stylesheets/documentation/syntax.css", "./stylesheets/documentation/highlighter/default.css"]
11
+ }
12
+
13
+ def initialize
14
+
15
+ end
16
+
17
+ def merge(input_path, output_path, options = {})
18
+ input_dir = Pathname.new(input_path)
19
+ raise ArgumentError, "Input directory does not exist" unless input_dir.directory?
20
+ output_dir = Pathname.new(output_path || Pathname.getwd+"generated-doc")
21
+ output_dir.mkpath
22
+ output = File.open(output_dir+"index.html", "w+")
23
+ output << header(:title => options[:title])
24
+ output << convert_directory(input_dir)
25
+ output << footer
26
+ output.close
27
+ # copy stylesheets and javascripts files
28
+ FileUtils.cp_r(File.join(File.dirname(__FILE__), "..", "files", "."), output_dir)
29
+ end
30
+
31
+ def convert_directory(dir, level = 1)
32
+ output = []
33
+ dir.entries.each do |entry|
34
+ next if entry.to_s =~ /^\./
35
+ path = dir+entry
36
+ title = File.basename(entry).gsub(/\d+-/, "").gsub(/\..+?$/, "")
37
+ output << "<div class='docapi-section #{title.downcase}'>"
38
+ if path.directory?
39
+ output << "<h#{level}>#{title.capitalize}</h#{level}>"
40
+ output << convert_directory(path, level+1)
41
+ else
42
+ output << convert_file(path)
43
+ end
44
+ output << '</div>'
45
+ end
46
+ output.flatten
47
+ end
48
+
49
+ def convert_file(file)
50
+ case file.extname
51
+ when ".md"
52
+ Maruku.new( File.read(file) ).to_html
53
+ when ".rb"
54
+ process_file_sections(file, 'ruby', [/^=begin (.*)$/, /^=end$/])
55
+ when ".py"
56
+ process_file_sections(file, 'python', [/^''' (.*)$/, /^'''$/])
57
+ when ".sh"
58
+ process_file_sections(file, 'bash', [/^<<ENDCOMMENT >\/dev\/null$/, /^ENDCOMMENT$/])
59
+ when ".html"
60
+ File.read(file)
61
+ end
62
+ end
63
+
64
+
65
+ def process_file_sections(file, language, regexps)
66
+ blocks = []
67
+ output = ["<div class='docapi-subsection'><div class='docapi-title'>#{File.basename(file).gsub(/^\d+-/, "")}</div>"]
68
+ File.open(file, "r").each do |line|
69
+ if line =~ regexps.first
70
+ output << write_block(blocks.pop)
71
+ blocks << {:content => "", :language => ($1 || "markdown")}
72
+ elsif line =~ regexps.last
73
+ output << write_block(blocks.pop)
74
+ else
75
+ blocks << {:content => "", :language => language} if blocks.last.nil?
76
+ blocks.last[:content] << line
77
+ end
78
+ end
79
+ output << write_block(blocks.pop)
80
+ output << '</div>'
81
+ end
82
+
83
+ def write_block(block)
84
+ if block
85
+ case block[:language]
86
+ when "markdown", "text"
87
+ Maruku.new( block[:content] ).to_html.gsub(/<pre class='(.+?)'><code>(.*?)<\/code><\/pre>/m, '<pre><code class="\1">\2</code></pre>')
88
+ else
89
+ '<pre><code class="'+block[:language]+'">'+block[:content]+'</code></pre>'
90
+ end
91
+ end
92
+ end
93
+
94
+ def generate(input_paths, output_path, options = {})
95
+ require 'rdoc'
96
+ require 'rdoc/rdoc'
97
+ rdoc_options = %w{-f html --one-file --charset=UTF-8 -U}
98
+ rdoc_options.concat input_paths
99
+ output_dir = Pathname.new(output_path || Pathname.getwd+"documentation")
100
+ raise ArgumentError, "Output directory '#{output_dir}' does not exist" unless output_dir.directory?
101
+ rdoc_output = Tempfile.new("rdoc_output.html")
102
+ old_stdout = $stdout
103
+ begin
104
+ # redirect stdout to the file
105
+ $stdout = rdoc_output
106
+ RDoc::RDoc.new.document(rdoc_options)
107
+ ensure
108
+ $stdout = old_stdout
109
+ end
110
+ rdoc_output.rewind
111
+ documentation = rdoc_output.read
112
+ rdoc_output.close
113
+ date = documentation[/<tr><td>Modified:<\/td><td>(.*?)<\/td><\/tr>/, 1]
114
+ methods = documentation.split("<h4> method: ")
115
+ methods.shift
116
+ methods.map!{ |m|
117
+ ["<div class='docapi-subsection'>", m.gsub(/<blockquote><pre>.*/m, "").gsub(/<a name="(.+?)">(.*?)<br \/>\s*?<\/a>/m, "<div class='docapi-title'><a name=\"\\1\">\\2<a></div>").gsub(/<h2>(.*?)<\/h2>/m, "<div class='docapi-subtitle'>\\1</div>").gsub(/<pre>(.*?)<\/pre>/m, "<pre><code>\\1</code></pre>"), "</div>"].join("")
118
+ }
119
+
120
+ File.open(File.join(output_dir.realpath, "documentation.html"), "w+") do |f|
121
+ # sort methods by :call-seq: length ASC. A bit dirty but...
122
+ methods.sort_by{|m| method = m[/<div class='docapi-title'><a name=".*?">(.+?)<a><\/div>/, 1].length rescue 0}.each{ |method| f << method }
123
+ end
124
+ end
125
+
126
+
127
+ def header(options = {})
128
+ output = []
129
+ output << "<html><head><title>#{options[:title] || "Documentation"}</title>"
130
+ FILES_TO_INCLUDE[:javascripts].each do |file|
131
+ output << '<script type="text/javascript" src="'+file+'"></script>'
132
+ end
133
+ FILES_TO_INCLUDE[:stylesheets].each do |file|
134
+ output << '<link media="screen" type="text/css" href="'+file+'" rel="stylesheet"/>'
135
+ end
136
+ output << %Q{
137
+ <!--[if IE]>
138
+ <style type="text/css" media="screen">
139
+ body {padding-right: 320px}
140
+ </style>
141
+ <![endif]-->}
142
+ output << "</head><body>"
143
+ end
144
+ def footer
145
+ output = []
146
+ output << "<div id='generation-date'>Generated at: <span class='date'>#{Time.now.to_s}</span></div>"
147
+ output << "</body></html>"
148
+ end
149
+
150
+ end
@@ -0,0 +1,141 @@
1
+ require 'sinatra/base'
2
+
3
+ module API
4
+ class ReferenceAPI < Sinatra::Base
5
+
6
+ ##
7
+ # :method: get(/:grid5000-resource/versions[.:format])
8
+ #
9
+ # :call-seq:
10
+ # GET /:grid5000-resource/versions[.:format]
11
+ #
12
+ # Get the list of all versions of a particular resource.
13
+ #
14
+ # == URI parameters
15
+ # <tt>grid5000-resource</tt>:: the URI of the grid5000 resource.
16
+ # <tt>format</tt>:: the requested format [json,xml] if you do not use the <tt>Accept</tt> header in your HTTP request.
17
+ #
18
+ # == Query parameters
19
+ # <tt>limit</tt>:: maximum number of versions to return.
20
+ #
21
+ # == Content-Types
22
+ # <tt>application/json</tt>:: JSON
23
+ # <tt>application/xml</tt>:: XML
24
+ #
25
+ # == Status codes
26
+ # <tt>200</tt>:: OK, the response contains the list of the versions of the requested grid5000 resource.
27
+ # <tt>404</tt>:: the requested grid5000 resource cannot be found.
28
+ # <tt>406</tt>:: the requested format is not available.
29
+ #
30
+ # == Usage
31
+ # Get the 2 latest versions of the Rennes site:
32
+ # GET /grid5000/sites/rennes/versions?limit=2 HTTP/1.1
33
+ # Accept: application/json
34
+ #
35
+ #
36
+ # HTTP/1.1 200 OK
37
+ # Date: Tue, 17 Mar 2009 13:41:45 GMT
38
+ # ETag: "0745dc6351cdd00919e8611f8f6952eb48fc9b56"
39
+ # Cache-Control: public, max-age=120
40
+ # Age: 0
41
+ # Content-Length: 496
42
+ # Content-Type: application/json;charset=utf-8
43
+ # [
44
+ # {
45
+ # "message": "Added network interfaces to helios and azur clusters.",
46
+ # "uri": "\/sites\/versions\/29202872636a3f4023b956cc7bba38c15850ec9f",
47
+ # "date": "Tue, 17 Mar 2009 09:28:27 GMT",
48
+ # "id": "29202872636a3f4023b956cc7bba38c15850ec9f"
49
+ # },
50
+ # {
51
+ # "message": "Added network interfaces to genepi nodes.",
52
+ # "uri": "\/sites\/versions\/7edfbafddb08beb8251c543c5c96e5d736bf23fa",
53
+ # "date": "Tue, 17 Mar 2009 09:17:48 GMT",
54
+ # "id": "7edfbafddb08beb8251c543c5c96e5d736bf23fa"
55
+ # }
56
+ # ]
57
+ #
58
+
59
+ #
60
+ get '*/versions.:format' do |resource_uri, format|
61
+
62
+ end
63
+
64
+ ##
65
+ # :method: get(/:grid5000-resource/versions/:version[.:format])
66
+ #
67
+ # :call-seq:
68
+ # GET /:grid5000-resource/versions/:version[.:format]
69
+ #
70
+ # Get info about a specific version.
71
+ #
72
+ # == URI parameters
73
+ # <tt>grid5000-resource</tt>:: the URI of the grid5000 resource.
74
+ # <tt>version</tt>:: the version id (40 characters long) or a UNIX timestamp.
75
+ #
76
+ # == Content-Types
77
+ # <tt>application/json</tt>:: JSON
78
+ # <tt>application/xml</tt>:: XML
79
+ #
80
+ # == Status codes
81
+ # <tt>200</tt>:: OK.
82
+ # <tt>404</tt>:: the requested grid5000 resource cannot be found, or the requested version does not exist.
83
+ # <tt>406</tt>:: the requested format is not available.
84
+ #
85
+
86
+ #
87
+ get '*/versions/:version.:format' do |resource_uri, version, format|
88
+
89
+ end
90
+
91
+ ##
92
+ # :method: get(/:grid5000-resource[.:format])
93
+ #
94
+ # :call-seq:
95
+ # GET /:grid5000-resource[.:format]
96
+ #
97
+ # Get a specific version of a Grid5000 resource.
98
+ #
99
+ # == URI parameters
100
+ # <tt>grid5000-resource</tt>:: the URI of the grid5000 resource.
101
+ #
102
+ # == Query parameters
103
+ # <tt>version</tt>:: the requested version. It can be a version id (40 characters),
104
+ # or a UNIX timestamp [default=empty (most recent version is used)].
105
+ # <tt>depth</tt>:: the number of nested sub-resources to resolve [default=1].
106
+ # <tt>resolve</tt>:: a list of comma separated sub-resources names to resolve (to be used with the +depth+ parameter) [default=all].
107
+ #
108
+ # == Content-Types
109
+ # <tt>application/json</tt>:: JSON
110
+ # <tt>application/xml</tt>:: XML
111
+ # <tt>application/zip</tt>:: the ZIP format will return a zip archive containing the set of directories and files corresponding to the required data, with all its sub-resources.
112
+ #
113
+ # == Status codes
114
+ # <tt>200</tt>:: OK, the response contains the description of the resource as it was at the requested version.
115
+ # <tt>404</tt>:: the requested grid5000 resource cannot be found, or the requested version does not exist.
116
+ # <tt>406</tt>:: Returns 406 if the requested format is not available.
117
+ #
118
+
119
+ #
120
+ get '*.:format' do |resource_uri, format|
121
+
122
+ end
123
+
124
+ private
125
+
126
+ def metadata_for_commit(commit, resource_uri)
127
+ {
128
+ 'uid' => commit.id,
129
+ 'date' => commit.committed_date.httpdate,
130
+ 'message' => commit.message,
131
+ 'author' => commit.author,
132
+ 'type' => 'version',
133
+ 'links' => [
134
+ {'rel' => 'self', 'href' => "#{resource_uri}/versions/#{commit.id}"},
135
+ {'rel' => 'parent', 'href' => "#{resource_uri}?version=#{commit.id}"}
136
+ ]
137
+ }
138
+ end
139
+
140
+ end # class ReferenceAPI
141
+ end # module API