rapi_doc 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.project ADDED
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>rapi_doc</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>com.aptana.ide.core.unifiedBuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>com.aptana.ruby.core.rubynature</nature>
16
+ </natures>
17
+ </projectDescription>
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm ruby-1.9.2-p180@rapidoc --create
1
+ rvm ruby-1.9.2@rapidoc --create
data/Gemfile CHANGED
@@ -4,12 +4,14 @@ source "http://rubygems.org"
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
6
  gem 'activesupport', '>= 2.1'
7
+ gem 'haml'
8
+ gem 'rdoc'
7
9
 
8
10
  # Add dependencies to develop your gem here.
9
11
  # Include everything needed to run rake, tests, features, etc.
10
12
  group :development do
11
- gem "rspec", "~> 2.7.0"
12
- gem "bundler", "~> 1.0.0"
13
- gem "jeweler", "~> 1.6.4"
13
+ gem "rspec", ">= 2.7.0"
14
+ gem "bundler", ">= 1.0.0"
15
+ gem "jeweler", ">= 1.6.4"
14
16
  gem "rcov", ">= 0"
15
17
  end
data/Gemfile.lock CHANGED
@@ -5,13 +5,17 @@ GEM
5
5
  multi_json (~> 1.0)
6
6
  diff-lcs (1.1.3)
7
7
  git (1.2.5)
8
+ haml (3.1.4)
8
9
  jeweler (1.6.4)
9
10
  bundler (~> 1.0)
10
11
  git (>= 1.2.5)
11
12
  rake
13
+ json (1.6.6)
12
14
  multi_json (1.0.4)
13
15
  rake (0.9.2.2)
14
16
  rcov (0.9.11)
17
+ rdoc (3.12)
18
+ json (~> 1.4)
15
19
  rspec (2.7.0)
16
20
  rspec-core (~> 2.7.0)
17
21
  rspec-expectations (~> 2.7.0)
@@ -26,7 +30,9 @@ PLATFORMS
26
30
 
27
31
  DEPENDENCIES
28
32
  activesupport (>= 2.1)
29
- bundler (~> 1.0.0)
30
- jeweler (~> 1.6.4)
33
+ bundler (>= 1.0.0)
34
+ haml
35
+ jeweler (>= 1.6.4)
31
36
  rcov
32
- rspec (~> 2.7.0)
37
+ rdoc
38
+ rspec (>= 2.7.0)
data/README.md CHANGED
@@ -13,19 +13,78 @@ Installation
13
13
  Usage
14
14
  =====
15
15
 
16
- Run `rake rapi_doc:setup` to generate config and layout files.
17
-
18
- Modify config file by adding your controllers, e.g.:
19
-
20
- books:
21
- location: "/books"
22
- controller_name: "books_controller.rb"
16
+ Run `rake rapi_doc:setup` to generate default Haml template files along with default styles.
17
+ These files are in `<application folder>/config/rapi_doc` folder.
23
18
 
24
19
  Then invoke the generation by calling:
25
20
 
26
21
  `rake rapi_doc:generate`
27
22
 
28
- Documentation Example
23
+ It will analyze `rake routes` output and find the controller files in app/controllers directory that may have the annotation.
24
+ It will confirm from the user whether he/she wants the plugin to look for annotations in each of these files.
25
+ For files confirmed by the user, it will parse the annotations and generate the HTML output using the template files and styles
26
+ in the `config/rapi_doc` folder.
27
+
28
+ `rake rapi_doc:clean`
29
+ will remove the documentation thus generated.
30
+
31
+ `rake rapi_doc:distclean`
32
+ will remove the documentation and also the Haml template files and styles created by the `rake rapi_doc:setup`
33
+
34
+
35
+ Markup Reference
36
+ ================
37
+
38
+ Controller methods and controllers themselves are documented by annotating them with "method markers" and
39
+ "resource markers" enclosed in "apidoc" comments, similar to that in RDoc.
40
+
41
+ # =begin apidoc
42
+ ... method markers
43
+ # =end
44
+
45
+ A] Method markers
46
+ -----------------
47
+
48
+ Method markers are specified like this:
49
+
50
+ # <<method-marker-name>:: <method-marker-value>
51
+
52
+ All method markers are optional.
53
+
54
+ # method: HTTP request type such as GET or POST
55
+ # access: access restrictions such as FREE, RESTRICTED for paid subscribers, etc
56
+ # return: list of return data-formats like [JSON|XML] and what the return data means
57
+ # param: name and type of the parameter expected
58
+ # output: output format like JSON, XML. It is recommended that it should include an example of such data.
59
+ # Each output marker must end with ::output-end:: on a separate line.
60
+ # request: a request generating code example
61
+ # response: a response processing code example
62
+
63
+ You can define your own custom method markers as well.
64
+ They will be available as the instance variables against which the _resource_method.html.erb template
65
+ will be evaluated.
66
+
67
+ Any other information that needs to be shown in the view can be specified in the apidoc comments as well.
68
+ It will be shown under the "Description" section for the method in the view.
69
+
70
+
71
+ B] Resource markers
72
+ -------------------
73
+
74
+ A resource, which is normally a controller object, can also be annotated with apidoc comments.
75
+
76
+ Method markers are specified the same way as the method markers:
77
+
78
+ # <<method-marker-name>:: <method-marker-value>
79
+ #
80
+ # xml: xml representation of the resource
81
+ # json: json representation
82
+
83
+ Just like in method marker, any other information that needs to be shown in the view can be specified in the apidoc comments as well.
84
+ It will be shown under the "Description" section for the method in the view.
85
+
86
+
87
+ C] Documentation Example
29
88
  ---------------------
30
89
 
31
90
  # =begin apidoc
@@ -63,14 +122,66 @@ Documentation Example
63
122
  # Get a list of all books in the system with pagination. Defaults to 10 per page
64
123
  # =end
65
124
 
66
-
67
- Layout
68
- ------
69
125
 
70
- Documentation layout is located at `config/rapi_doc/layout.html.erb`.
126
+
127
+ Haml Templates and styles
128
+ =========================
129
+
130
+ Resource and resource method annotations are available as instance and local variables in Haml templates.
131
+ Here are the listing of variables available. But the best way to understand it is to look at the default
132
+ Haml templates generated by `rake rapi_doc:setup` in `config/rapi_doc` folder.
133
+
134
+
135
+ A] Resource Method
136
+ ------------------
137
+
138
+ @resource_name: Resource name
139
+ @method_order: the numerical order of the method
140
+ @content: All Misc info
141
+ @url: url
142
+ @access: public/privileged, etc
143
+ @return: the data format of the info
144
+ @params: params expected by this api
145
+ @outputs: array of [output_format, output example], for example, [json, ....json output.. ]
146
+ @request: example of the data expected
147
+ @response: example of the response
148
+
149
+
150
+ B] Resource
151
+ -----------
152
+
153
+ @name: name
154
+ @xml: xml representation of the resource
155
+ @json: json representation
156
+ @function_blocks: Array of resource method objects described above
157
+
158
+
159
+ Following instance variables are only available in the index template described below (and not in the resource Haml template)
160
+ @resource_methods: Array of HTML generated for each of the methods.
161
+ @resource_header: HTML generated for the resource
162
+
163
+
164
+ C] Index
165
+ --------
166
+
167
+ resource_docs: all the resource objects, whose instance variables are described above.
168
+ As mentioned before, for each resource, the HTML generated for the resource itself is available in @resource_header
169
+ and HTML generated for each of its methods is available in @resource_methods array.
170
+
171
+
172
+
173
+ D] Documentaton Output
174
+ ----------------------
175
+
176
+ Documentation generated is located in `public/apidoc` directory.
177
+
178
+ index.html: contains the HTML
179
+ styles.css: CSS styles
180
+ scripts.js: contains the script used to search within the documentation.
181
+
71
182
 
72
183
  Credit
73
184
  ======
74
185
 
75
186
  * Based on RAPI Doc by Jaap van der Meer found here: http://code.google.com/p/rapidoc/
76
- * https://github.com/sabman/rapi_doc
187
+ * https://github.com/sabman/rapi_doc
data/Rakefile CHANGED
@@ -18,10 +18,12 @@ Jeweler::Tasks.new do |gem|
18
18
  gem.homepage = "http://github.com/elc/rapi_doc"
19
19
  gem.license = "MIT"
20
20
  gem.summary = %Q{Rails API Doc Generator}
21
- gem.description = %Q{Rails API Doc Generator}
21
+ gem.description = %Q{Rails API Doc Generator. Parses the apidoc annotations to generate HTML pages.}
22
22
  gem.email = "hchoroomi@gmail.com"
23
- gem.authors = ["Husein Choroomi", "Adinda Praditya"]
23
+ gem.authors = ["Husein Choroomi", "Adinda Praditya", "Salil Wadnerkar"]
24
24
  # dependencies defined in Gemfile
25
+ gem.add_dependency 'haml'
26
+ gem.add_dependency 'rdoc'
25
27
  end
26
28
  Jeweler::RubygemsDotOrgTasks.new
27
29
 
@@ -42,8 +44,8 @@ end
42
44
 
43
45
  task :default => :test
44
46
 
45
- require 'rake/rdoctask'
46
- Rake::RDocTask.new do |rdoc|
47
+ require 'rdoc/task'
48
+ RDoc::Task.new do |rdoc|
47
49
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
50
 
49
51
  rdoc.rdoc_dir = 'rdoc'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
data/autoscan.log ADDED
File without changes
data/configure.scan ADDED
@@ -0,0 +1,17 @@
1
+ # -*- Autoconf -*-
2
+ # Process this file with autoconf to produce a configure script.
3
+
4
+ AC_PREREQ(2.61)
5
+ AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
6
+
7
+ # Checks for programs.
8
+
9
+ # Checks for libraries.
10
+
11
+ # Checks for header files.
12
+
13
+ # Checks for typedefs, structures, and compiler characteristics.
14
+
15
+ # Checks for library functions.
16
+
17
+ AC_OUTPUT
data/lib/rapi_doc.rb CHANGED
@@ -1,76 +1,100 @@
1
- require 'erb'
1
+ require 'haml'
2
2
  require 'fileutils'
3
- require 'doc_util'
4
- require 'resource_doc'
5
- require 'rapi_config'
6
- require 'rapi_doc/railtie' if defined?(Rails)
3
+ require_relative 'rapi_doc/resource_doc'
4
+ require_relative 'rapi_doc/rapi_config'
5
+ require_relative 'rapi_doc/railtie' if defined?(Rails)
7
6
 
8
7
  module RapiDoc
9
- class RAPIDoc
8
+ module RAPIDoc
10
9
 
11
10
  include RapiConfig
11
+ include FileUtils::Verbose # so that each mv/cp/mkdir gets printed and user is aware of what is happening
12
12
 
13
- # Initalize the ApiDocGenerator
14
- def initialize(resources)
15
- puts "Apidoc started..."
16
- @resources = resources
17
- generate_templates!
18
- move_structure!
19
- puts "Finished."
13
+ def create_structure!
14
+ File.directory?(config_dir) || mkdir(config_dir)
15
+ Dir["#{template_dir}/*.*"].each do |template_file|
16
+ target_file = config_dir(File.basename(template_file))
17
+ cp template_file, config_dir if not File.exist? target_file
18
+ end
20
19
  end
21
20
 
22
- # Iterates over the resources creates views for them.
23
- # Creates an index file
24
- def generate_templates!
21
+ # Reads 'rake routes' output and gets the controller info
22
+ def get_controller_info!
23
+ controller_info = {}
24
+ routes = Dir.chdir(::Rails.root.to_s) { `rake routes` }
25
+ routes.split("\n").each do |entry|
26
+ method, url, controller_action = entry.split.slice(-3, 3)
27
+ controller, action = controller_action.split('#')
28
+ puts "For \"#{controller}\", found action \"#{action}\" with #{method} at \"#{url}\""
29
+ controller_info[controller] ||= []
30
+ controller_info[controller] << [action, method, url]
31
+ end
32
+ controller_info
33
+ end
25
34
 
26
- @resources.each do |r|
27
- r.parse_apidoc!
28
- r.generate_view!(@resources, temp_dir)
35
+ def get_resources!
36
+ #yml = get_config || []
37
+ #yml.collect { |key, val| ResourceDoc.new(key, val["location"], controller_dir(val["controller_name"])) }
38
+ controller_info = get_controller_info!
39
+ resources = []
40
+ controller_info.each do |controller, action_entries|
41
+ #controller_class = controller.capitalize + 'Controller'
42
+ controller_location = controller_dir(controller + '_controller.rb')
43
+ controller_base_routes = action_entries.select do |action, method, url|
44
+ url.index('/', 1).nil?
45
+ end
46
+ # base urls differ only by the method [GET or POST]. So, any one will do.
47
+ controller_url = controller_base_routes[0][2].gsub(/\(.*\)/, '') # omit the trailing format
48
+ #controller_methods = controller_base_routes.map { |action, method, url| method }
49
+ if block_given?
50
+ controller_include = yield [controller, controller_url, controller_location]
51
+ else
52
+ controller_include = true
53
+ end
54
+ resources << ResourceDoc.new(controller, controller_url, controller_location) if controller_include
29
55
  end
30
- generate_index!
31
- copy_styles!
56
+ resources
32
57
  end
33
58
 
34
- # generate the index file for the api views
35
- def generate_index!
36
- template = ""
37
- @page_type2 = 'dudul'
38
- File.open(class_layout_file(:target)).each { |line| template << line }
39
- parsed = ERB.new(template).result(binding)
40
- File.open(File.join(temp_dir, "class.html"), 'w') { |file| file.write parsed }
59
+ # Generates views and their index in a temp directory
60
+ def generate_templates!(resource_docs)
61
+ generate_resource_templates!(resource_docs)
62
+ copy_styles!
41
63
  end
42
64
 
65
+ # Moves the generated files in the temp directory to target directory
43
66
  def move_structure!
44
- target_folder = "#{::Rails.root.to_s}/public/apidoc/"
45
- Dir.mkdir(target_folder) if (!File.directory?(target_folder))
67
+ Dir.mkdir(target_dir) if (!File.directory?(target_dir))
68
+ # Only want to move the .html, .css, .png and .js files, not the .haml templates.
69
+ html_css_files = temp_dir("*.{html,css,js,png}")
70
+ Dir[html_css_files].each { |f| mv f, target_dir }
71
+ end
46
72
 
47
- # Copy the frameset & main files
48
- FileUtils.cp frameset_file(:target), target_folder + 'index.html'
49
- FileUtils.cp main_file(:target), target_folder + 'main.html'
73
+ # Removes the generated files
74
+ def remove_structure!
75
+ rm_rf target_dir
76
+ end
50
77
 
51
- Dir.new(temp_dir).each do |d|
52
- if d =~ /^[a-zA-Z]+\.(html|css)$/ # Only want to copy over the .html files, not the .erb templates
53
- FileUtils.cp File.join(temp_dir + d), target_folder + d
54
- end
78
+ # Remove all files - config and generated
79
+ def remove_all!
80
+ remove_structure!
81
+ rm_rf config_dir
82
+ end
55
83
 
56
- #Clean up the no longer needed files
57
- filepath = "#{temp_dir}/#{d}"
58
- File.delete(filepath) unless File.directory?(filepath)
59
- end
84
+ # Creates views for the resources
85
+ def generate_resource_templates!(resource_docs)
86
+ class_template = IO.read(template_dir('_resource_header.html.haml'))
87
+ method_template = IO.read(template_dir('_resource_method.html.haml'))
88
+ resource_docs.each { |resource| resource.parse_apidoc!(class_template, method_template) }
89
+ template = IO.read(config_dir('index.html.haml'))
90
+ parsed = Haml::Engine.new(template).render(Object.new, :resource_docs => resource_docs)
91
+ File.open(temp_dir("index.html"), 'w') { |file| file.write parsed }
60
92
  end
61
93
 
62
94
  def copy_styles!
63
- Dir[File.join(File.dirname(__FILE__), '..', 'templates/*')].each do |f|
64
- if f =~ /[\/a-zA-Z\.]+\.css$/i
65
- FileUtils.cp f, temp_dir
66
- end
67
- end
95
+ css_js_files = config_dir("*.{css,js,png}")
96
+ Dir[css_js_files].each { |f| cp f, temp_dir }
68
97
  end
69
98
 
70
- private
71
-
72
- def temp_dir
73
- @temp_dir ||= "#{Dir.mktmpdir("apidoc")}/"
74
- end
75
99
  end
76
100
  end
@@ -0,0 +1,71 @@
1
+ module RapiDoc
2
+ # This class holds methods about a doc.
3
+ class MethodDoc
4
+ attr_accessor :scope, :method_order, :content, :request, :response, :outputs, :params
5
+
6
+ def initialize(resource_name, type, order)
7
+ @resource_name = resource_name
8
+ @scope = type
9
+ @method_order = order
10
+ @content = ""
11
+ @request = ""
12
+ @response = ""
13
+ @outputs = {}
14
+ @params = []
15
+ end
16
+
17
+ def process_line(line, current_scope)
18
+ #puts "In scope #{current_scope} processing: #{line}"
19
+ new_scope = current_scope
20
+ case current_scope
21
+ when :response
22
+ if line =~ /::response-end::/
23
+ new_scope = :function
24
+ else
25
+ @response << line
26
+ end
27
+ when :request
28
+ if line =~ /::request-end::/
29
+ new_scope = :function
30
+ else
31
+ @request << line
32
+ end
33
+ when :output # append output
34
+ if line =~ /::output-end::/
35
+ new_scope = :function
36
+ else
37
+ last_output_key = @outputs.keys.last
38
+ @outputs[last_output_key] << ERB::Util.html_escape(line)
39
+ end
40
+ when :class, :function
41
+ result = line.scan(/(\w+)\:\:\s*(.+)/)
42
+ if not result.empty?
43
+ key, value = result[0]
44
+ case key
45
+ when "response", "request"
46
+ new_scope = key.to_sym
47
+ when "output"
48
+ new_scope = key.to_sym
49
+ @outputs[value] = '' # add the new output format as a key
50
+ when "param"
51
+ @params << value
52
+ else # user wants this new shiny variable whose name is the key with value = value
53
+ instance_variable_set("@#{key}".to_sym, value)
54
+ define_singleton_method(key.to_sym) { value } # define accessor for the templates to read it
55
+ end
56
+ else
57
+ # add line to block
58
+ @content << line
59
+ end
60
+ else
61
+ raise ParsingException, "logic error: unknown current scope #{current_scope}"
62
+ end
63
+ new_scope
64
+ end
65
+
66
+ def get_binding
67
+ binding
68
+ end
69
+
70
+ end
71
+ end