docapi 0.1.5

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.
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