module GrapeDSL module Extend module Doc def syntax_highlight target,wrapper_begin,wrapper_end return "#{wrapper_begin}#{target}#{wrapper_end}" end # helpers for doc generation def wiki_body(route,wrapper_begin,wrapper_end,wrapper_close) require 'grape-dsl/doc_mp' description_key= :body tmp_array= Array.new() params= nil evalue= nil content_type= nil #if route.route_path == "/booking/request(.:format)" # debugger #end case route.route_description.class.to_s.downcase when "string" params= route.route_params when "hash" if !route.route_description[:content_type].nil? content_type= route.route_description[:content_type] end if description_key.nil? params= route.route_params evalue= "value[:type]" else params= route.route_description[description_key] evalue= "value" end when "nilclass" params= route.route_params params ||= "no return" content_type= "TXT" else params= route.route_params content_type= "TXT" end case params.class.to_s.downcase when "hash" if params == route.route_params tmp_hash= Hash.new params.each do |key,value| tmp_hash[key]= value[:type].to_s end params= tmp_hash end params = params.convert_all_value_to_s when "class" begin if params.to_s.include? '::' if params.to_s.downcase.include? 'boolean' params= params.to_s.split('::').last end end content_type= "TXT" end when "string" content_type= "TXT" else begin params= "no params spec" content_type= "TXT" end end content_type ||= "TXT" case content_type.to_s.downcase when "json" begin tmp_array.push syntax_highlight(content_type.to_s,wrapper_begin,wrapper_end) require "json" formatted_string= params.to_json { "{" => "{\n", "}" => "\n}", "," => ",\n" }.each do |from,to| formatted_string.gsub!(from,to) end formatted_string.gsub!(/^"/," \"") tmp_array.push formatted_string tmp_array.push wrapper_close end when "txt" begin tmp_array.push(params.inspect) end end return tmp_array end # this method help create from grape params and description a ppt like redmine wiki doc # Usage: # ##> example variable for description (hash obj) #description= Hash.new # ##> optional -> :description #description[:desc]= String.new # ##> response body like if JSON than a ruby Hash obj with the Structure and the values are the types #description[:body]= Hash.new # ##> response body code type -> like json usually same as content_type (format :xy) #description[:content_type]= String.new #> "JSON" # #desc description #params do # optional :blabla, :type => String, :desc => "bla bla desc" # requires :xy, type: String, desc: "XY desc" #end #get "xy" do # #end # ##>--------------------------------------------------------------------------------------------------- #> OR the classic #desc "My awsome String Description" #params do # optional :blabla, :type => String, :desc => "bla bla desc" # requires :xy, type: String, desc: "XY desc" #end #delete "xy" do # #end # ##>--------------------------------------------------------------------- ## For the method use # ## for a targeted specified class #Grape.create_redmine_wiki_doc target_class: REST::API, # path: File.expand_path(File.join(File.dirname(__FILE__),"test_file.txt")) # ## for all grape subclass (directs and indirects) #Grape.create_redmine_wiki_doc path: File.expand_path(File.join(File.dirname(__FILE__),"test_file.txt")) # def create_wiki_doc(*args) # default set in args begin args= Hash[*args] args.dup.each do |key,value| if key.class != Symbol args[key.to_s.to_sym]= value args.delete key end end if args[:path].nil? raise ArgumentError,"You must set a file path with a file name in order to create documentation for grape!" end args[:desc_files] ||= Array.new [:desc,:desc_file,:extra_desc_file].each do |one_key| args[:desc_files] += args[(one_key.to_s+"s").to_sym] if args[(one_key.to_s+"s").to_sym].class == Array args[:desc_files].push(args[one_key]) if args[one_key].class == String end args[:type] ||= args[:doc_type] args[:type] ||= 'wiki' #args[:path], #args[:extra_desc_file] #args[:target_class] #args[:type] end # defaults begin uni_tab= "" case args[:type].to_s.downcase when "redmine","redmine_wiki","redmine-wiki","redminewiki" begin mid_tab= " "*3 bsym= "*" isym= "_" htsym= "* " mtsym= htsym[0]*2 +" " stsym= htsym[0]*3 +" " hheader= "h3. " mheader= "h4. " sheader= "h5. " container_markup_begin= "
"
                container_markup_close= "
" toc_mark= "\n{{>toc}}\n" end when "github","wiki","md" begin mid_tab= " "*3 bsym= "*" isym= "_" htsym= "* " mtsym= " * " stsym= " * " hheader= "## " mheader= "### " sheader= "#### " container_markup_begin= "```" container_markup_end= "" container_markup_close= "```" toc_mark= "" end else raise ArgumentError, "invalid :type has been set, try github or redmine" end end # site name begin write_out_array = Array.new write_out_array.push "#{hheader}#{$0} REST Interface Documentation\n\n" end # description begin args[:desc_files].each do |extra_desc_file_path| write_out_array.push "#{sheader}#{extra_desc_file_path.split(File::Separator).last.split('.')[0].camelcase}\n" write_out_array.push " "+File.open(extra_desc_file_path,"r").read+"\n" end end # table of contents begin write_out_array.push toc_mark end # classes array begin rest_models= Array.new end if args[:target_class].nil? Grape::API.each_subclass do |one_class| rest_models.push(one_class) end else if args[:target_class].class != Class && args[:target_class] != nil raise ArgumentError, "invalid input :target_class is not a Class obj" end rest_models.push(args[:target_class]) end rest_models.each do |rest_api_model| next if Grape::API == rest_api_model rest_api_model.routes.map do |route| method_name= "#{hheader}Request: #{route.route_path} call: #{route.route_method.to_s.downcase} part" # check that does the method already in the documentation unless write_out_array.include?(method_name) # create call name begin write_out_array.push method_name end # request begin # create request description begin write_out_array.push("\n"+(uni_tab*1)+"#{mheader}Request description") case route.route_description.class.to_s.downcase when "string" route.route_description.each_line do |one_line| write_out_array.push((uni_tab*2)+htsym+one_line.chomp) end when "hash" begin sym_to_find= :desc if route.route_description[sym_to_find].nil? sym_to_find= :description end route.route_description[sym_to_find].each_line do |one_line| write_out_array.push((uni_tab*2)+htsym+one_line.chomp) end end end end # pre request begin write_out_array.push("\n#{mheader}request\n") end # create route method begin write_out_array.push((uni_tab*2)+"#{htsym}#{bsym}method:#{bsym}#{mid_tab} #{route.route_method}") end # create route path begin write_out_array.push((uni_tab*2)+"#{htsym}#{bsym}path:#{bsym}#{mid_tab} #{route.route_path}") end # create route content_type begin write_out_array.push((uni_tab*2)+"#{htsym}#{bsym}headers:#{bsym}#{mid_tab}") rest_api_model.content_types.each do |one_format_type,one_format_header| write_out_array.push "#{mtsym}#{uni_tab*2}#{one_format_header}" end write_out_array.push "" end # parameters begin new_docs_element= Array.new if route.route_params.count == 0 new_docs_element.push " No specified or special params" else new_docs_element.push "" new_docs_element.push "#{htsym}#{isym}#{bsym}Parameters#{bsym}#{isym}" route.route_params.each do |key,value| new_docs_element.push "#{mtsym}#{isym}#{key}#{isym}" value.each do |value_key,value_value| new_docs_element.push "#{stsym}#{value_key}: #{value_value}" end end new_docs_element.push "\n" end refactored_element= Array.new new_docs_element.each do |one_element| refactored_element.push((uni_tab*2)+one_element) end write_out_array.push refactored_element.join("\n") end end # response begin # pre response begin write_out_array.push("\n#{mheader}response\n") end #create route content_type begin if !Grape::Endpoint.config_obj.nil? write_out_array.push((uni_tab*2)+"#{sheader}Extra headers:") Grape::Endpoint.header_config_obj.each do |header_key,header_value| write_out_array.push "#{htsym}#{header_key}: #{header_value.join(', ')}" end write_out_array.push "" end end # create response bodies begin #TODO check out why not working normaly with evry path! write_out_array.push((uni_tab*2)+"#{sheader}*body:*") wiki_body(route,container_markup_begin,container_markup_end,container_markup_close ).each do |one_element| write_out_array.push one_element end write_out_array.push "" end end # error resp begin # pre error begin write_out_array.push("\n#{mheader}response in case of failure\n") end # create error response headers begin end # create error response bodies begin #write_out_array.push((uni_tab*2)+"*body:*") write_out_array.push((uni_tab*2)+"#{htsym}*Internal Server Error:500*") end end # after space begin write_out_array.push "\n----\n" end end end end File.new(args[:path],"w").write write_out_array.join("\n") return nil end alias :create_ppt_doc :create_wiki_doc end end end Grape.__send__ :extend, ::GrapeDSL::Extend::Doc