yard 0.5.8 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of yard might be problematic. Click here for more details.

Files changed (211) hide show
  1. data/.yardopts +2 -0
  2. data/ChangeLog +1064 -0
  3. data/README.md +103 -42
  4. data/Rakefile +3 -2
  5. data/benchmarks/parsing.rb +2 -1
  6. data/bin/yard +4 -0
  7. data/bin/yard-graph +1 -1
  8. data/bin/yard-server +4 -0
  9. data/docs/GettingStarted.md +8 -8
  10. data/docs/Handlers.md +5 -5
  11. data/docs/Overview.md +5 -5
  12. data/docs/Parser.md +1 -1
  13. data/docs/Tags.md +1 -1
  14. data/docs/Templates.md +27 -6
  15. data/docs/WhatsNew.md +222 -2
  16. data/lib/rubygems_plugin.rb +1 -0
  17. data/lib/yard.rb +7 -1
  18. data/lib/yard/autoload.rb +46 -6
  19. data/lib/yard/cli/{base.rb → command.rb} +20 -6
  20. data/lib/yard/cli/command_parser.rb +87 -0
  21. data/lib/yard/cli/diff.rb +176 -0
  22. data/lib/yard/cli/gems.rb +74 -0
  23. data/lib/yard/cli/{yard_graph.rb → graph.rb} +9 -8
  24. data/lib/yard/cli/help.rb +18 -0
  25. data/lib/yard/cli/server.rb +137 -0
  26. data/lib/yard/cli/stats.rb +210 -0
  27. data/lib/yard/cli/yardoc.rb +315 -116
  28. data/lib/yard/cli/yri.rb +45 -4
  29. data/lib/yard/code_objects/base.rb +73 -30
  30. data/lib/yard/code_objects/class_object.rb +9 -1
  31. data/lib/yard/code_objects/method_object.rb +11 -0
  32. data/lib/yard/code_objects/namespace_object.rb +8 -2
  33. data/lib/yard/code_objects/proxy.rb +2 -2
  34. data/lib/yard/core_ext/array.rb +3 -49
  35. data/lib/yard/core_ext/file.rb +7 -0
  36. data/lib/yard/core_ext/insertion.rb +60 -0
  37. data/lib/yard/docstring.rb +34 -7
  38. data/lib/yard/globals.rb +2 -2
  39. data/lib/yard/handlers/base.rb +101 -20
  40. data/lib/yard/handlers/processor.rb +23 -7
  41. data/lib/yard/handlers/ruby/alias_handler.rb +1 -0
  42. data/lib/yard/handlers/ruby/attribute_handler.rb +8 -0
  43. data/lib/yard/handlers/ruby/base.rb +71 -2
  44. data/lib/yard/handlers/ruby/class_condition_handler.rb +10 -0
  45. data/lib/yard/handlers/ruby/class_handler.rb +7 -4
  46. data/lib/yard/handlers/ruby/class_variable_handler.rb +1 -0
  47. data/lib/yard/handlers/ruby/constant_handler.rb +1 -0
  48. data/lib/yard/handlers/ruby/exception_handler.rb +1 -0
  49. data/lib/yard/handlers/ruby/extend_handler.rb +2 -3
  50. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +1 -0
  51. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +2 -0
  52. data/lib/yard/handlers/ruby/legacy/base.rb +15 -2
  53. data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +5 -0
  54. data/lib/yard/handlers/ruby/legacy/class_handler.rb +7 -4
  55. data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +1 -0
  56. data/lib/yard/handlers/ruby/legacy/constant_handler.rb +1 -0
  57. data/lib/yard/handlers/ruby/legacy/exception_handler.rb +1 -0
  58. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +1 -3
  59. data/lib/yard/handlers/ruby/legacy/method_handler.rb +7 -3
  60. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +2 -1
  61. data/lib/yard/handlers/ruby/legacy/module_handler.rb +1 -0
  62. data/lib/yard/handlers/ruby/legacy/process_handler.rb +1 -0
  63. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +1 -0
  64. data/lib/yard/handlers/ruby/legacy/yield_handler.rb +1 -0
  65. data/lib/yard/handlers/ruby/method_condition_handler.rb +1 -0
  66. data/lib/yard/handlers/ruby/method_handler.rb +5 -1
  67. data/lib/yard/handlers/ruby/mixin_handler.rb +2 -1
  68. data/lib/yard/handlers/ruby/module_handler.rb +1 -0
  69. data/lib/yard/handlers/ruby/process_handler.rb +7 -1
  70. data/lib/yard/handlers/ruby/struct_handler_methods.rb +3 -0
  71. data/lib/yard/handlers/ruby/visibility_handler.rb +8 -2
  72. data/lib/yard/handlers/ruby/yield_handler.rb +1 -0
  73. data/lib/yard/logging.rb +7 -1
  74. data/lib/yard/parser/base.rb +1 -0
  75. data/lib/yard/parser/c_parser.rb +2 -0
  76. data/lib/yard/parser/ruby/ast_node.rb +82 -63
  77. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +36 -10
  78. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +1 -0
  79. data/lib/yard/parser/ruby/legacy/statement.rb +9 -5
  80. data/lib/yard/parser/ruby/legacy/statement_list.rb +20 -11
  81. data/lib/yard/parser/ruby/ruby_parser.rb +18 -1
  82. data/lib/yard/parser/source_parser.rb +6 -1
  83. data/lib/yard/registry.rb +284 -278
  84. data/lib/yard/registry_store.rb +4 -2
  85. data/lib/yard/serializers/base.rb +30 -13
  86. data/lib/yard/serializers/file_system_serializer.rb +10 -1
  87. data/lib/yard/server/adapter.rb +51 -0
  88. data/lib/yard/server/commands/base.rb +98 -0
  89. data/lib/yard/server/commands/display_file_command.rb +20 -0
  90. data/lib/yard/server/commands/display_object_command.rb +50 -0
  91. data/lib/yard/server/commands/frames_command.rb +31 -0
  92. data/lib/yard/server/commands/library_command.rb +83 -0
  93. data/lib/yard/server/commands/library_index_command.rb +23 -0
  94. data/lib/yard/server/commands/list_command.rb +44 -0
  95. data/lib/yard/server/commands/search_command.rb +67 -0
  96. data/lib/yard/server/commands/static_file_command.rb +45 -0
  97. data/lib/yard/server/doc_server_helper.rb +22 -0
  98. data/lib/yard/server/doc_server_serializer.rb +29 -0
  99. data/lib/yard/server/library_version.rb +86 -0
  100. data/lib/yard/server/rack_adapter.rb +38 -0
  101. data/lib/yard/server/router.rb +110 -0
  102. data/lib/yard/server/static_caching.rb +16 -0
  103. data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +78 -0
  104. data/lib/yard/server/templates/default/fulldoc/html/images/processing.gif +0 -0
  105. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +12 -0
  106. data/lib/yard/server/templates/default/fulldoc/html/js/live.js +32 -0
  107. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +46 -0
  108. data/lib/yard/server/templates/default/layout/html/headers.erb +11 -0
  109. data/lib/yard/server/templates/doc_server/frames/html/frames.erb +13 -0
  110. data/lib/yard/server/templates/doc_server/frames/html/setup.rb +3 -0
  111. data/lib/yard/server/templates/doc_server/full_list/html/full_list.erb +34 -0
  112. data/lib/yard/server/templates/doc_server/full_list/html/setup.rb +10 -0
  113. data/lib/yard/server/templates/doc_server/library_list/html/contents.erb +13 -0
  114. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +26 -0
  115. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +12 -0
  116. data/lib/yard/server/templates/doc_server/library_list/html/setup.rb +3 -0
  117. data/lib/yard/server/templates/doc_server/library_list/html/title.erb +2 -0
  118. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +51 -0
  119. data/lib/yard/server/templates/doc_server/processing/html/setup.rb +3 -0
  120. data/lib/yard/server/templates/doc_server/search/html/search.erb +19 -0
  121. data/lib/yard/server/templates/doc_server/search/html/setup.rb +8 -0
  122. data/lib/yard/server/webrick_adapter.rb +38 -0
  123. data/lib/yard/tags/default_factory.rb +0 -5
  124. data/lib/yard/tags/library.rb +61 -22
  125. data/lib/yard/tags/tag.rb +26 -4
  126. data/lib/yard/templates/engine.rb +12 -1
  127. data/lib/yard/templates/erb_cache.rb +2 -1
  128. data/lib/yard/templates/helpers/base_helper.rb +96 -3
  129. data/lib/yard/templates/helpers/filter_helper.rb +5 -0
  130. data/lib/yard/templates/helpers/html_helper.rb +204 -94
  131. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +4 -0
  132. data/lib/yard/templates/helpers/markup_helper.rb +58 -3
  133. data/lib/yard/templates/helpers/method_helper.rb +7 -0
  134. data/lib/yard/templates/helpers/module_helper.rb +5 -0
  135. data/lib/yard/templates/helpers/text_helper.rb +10 -1
  136. data/lib/yard/templates/helpers/uml_helper.rb +13 -0
  137. data/lib/yard/templates/section.rb +106 -0
  138. data/lib/yard/templates/template.rb +20 -19
  139. data/lib/yard/verifier.rb +21 -2
  140. data/spec/cli/command_parser_spec.rb +43 -0
  141. data/spec/cli/diff_spec.rb +170 -0
  142. data/spec/cli/help_spec.rb +22 -0
  143. data/spec/cli/server_spec.rb +140 -0
  144. data/spec/cli/stats_spec.rb +75 -0
  145. data/spec/cli/yardoc_spec.rb +438 -182
  146. data/spec/cli/yri_spec.rb +13 -1
  147. data/spec/code_objects/base_spec.rb +51 -6
  148. data/spec/code_objects/class_object_spec.rb +15 -1
  149. data/spec/code_objects/method_object_spec.rb +29 -0
  150. data/spec/code_objects/namespace_object_spec.rb +150 -129
  151. data/spec/core_ext/array_spec.rb +4 -23
  152. data/spec/core_ext/insertion_spec.rb +37 -0
  153. data/spec/docstring_spec.rb +63 -0
  154. data/spec/handlers/attribute_handler_spec.rb +4 -0
  155. data/spec/handlers/base_spec.rb +98 -26
  156. data/spec/handlers/class_handler_spec.rb +5 -1
  157. data/spec/handlers/examples/attribute_handler_001.rb.txt +5 -0
  158. data/spec/handlers/examples/class_handler_001.rb.txt +4 -0
  159. data/spec/handlers/examples/module_handler_001.rb.txt +6 -1
  160. data/spec/handlers/examples/visibility_handler_001.rb.txt +4 -0
  161. data/spec/handlers/method_handler_spec.rb +5 -0
  162. data/spec/handlers/module_handler_spec.rb +4 -0
  163. data/spec/handlers/visibility_handler_spec.rb +6 -0
  164. data/spec/parser/source_parser_spec.rb +24 -0
  165. data/spec/registry_spec.rb +44 -8
  166. data/spec/server/adapter_spec.rb +38 -0
  167. data/spec/server/commands/base_spec.rb +87 -0
  168. data/spec/server/commands/static_file_command_spec.rb +67 -0
  169. data/spec/server/doc_server_serializer_spec.rb +58 -0
  170. data/spec/server/router_spec.rb +115 -0
  171. data/spec/server/spec_helper.rb +17 -0
  172. data/spec/server/static_caching_spec.rb +39 -0
  173. data/spec/server/webrick_servlet_spec.rb +20 -0
  174. data/spec/templates/constant_spec.rb +40 -0
  175. data/spec/templates/engine_spec.rb +9 -5
  176. data/spec/templates/examples/class002.html +1 -3
  177. data/spec/templates/examples/constant001.txt +25 -0
  178. data/spec/templates/examples/constant002.txt +7 -0
  179. data/spec/templates/examples/constant003.txt +11 -0
  180. data/spec/templates/examples/module001.txt +1 -1
  181. data/spec/templates/examples/module002.html +319 -0
  182. data/spec/templates/helpers/base_helper_spec.rb +2 -2
  183. data/spec/templates/helpers/html_helper_spec.rb +93 -3
  184. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +5 -0
  185. data/spec/templates/helpers/markup_helper_spec.rb +94 -67
  186. data/spec/templates/helpers/shared_signature_examples.rb +9 -0
  187. data/spec/templates/helpers/text_helper_spec.rb +12 -0
  188. data/spec/templates/module_spec.rb +21 -4
  189. data/spec/templates/section_spec.rb +146 -0
  190. data/spec/templates/template_spec.rb +9 -20
  191. data/templates/default/class/setup.rb +5 -5
  192. data/templates/default/constant/text/header.erb +11 -0
  193. data/templates/default/constant/text/setup.rb +3 -0
  194. data/templates/default/fulldoc/html/css/style.css +29 -3
  195. data/templates/default/fulldoc/html/js/app.js +67 -1
  196. data/templates/default/fulldoc/html/js/full_list.js +3 -8
  197. data/templates/default/fulldoc/html/js/jquery.js +150 -15
  198. data/templates/default/fulldoc/html/setup.rb +9 -0
  199. data/templates/default/layout/html/footer.erb +1 -1
  200. data/templates/default/layout/html/setup.rb +7 -25
  201. data/templates/default/method_details/html/source.erb +1 -1
  202. data/templates/default/module/html/attribute_summary.erb +2 -2
  203. data/templates/default/module/html/method_summary.erb +2 -2
  204. data/templates/default/module/setup.rb +27 -4
  205. data/templates/default/onefile/html/files.erb +5 -0
  206. data/templates/default/onefile/html/layout.erb +22 -0
  207. data/templates/default/onefile/html/readme.erb +3 -0
  208. data/templates/default/onefile/html/setup.rb +40 -0
  209. data/templates/default/root/html/setup.rb +1 -0
  210. data/templates/default/tags/setup.rb +26 -33
  211. metadata +80 -10
@@ -0,0 +1,23 @@
1
+ module YARD
2
+ module Server
3
+ module Commands
4
+ class LibraryIndexCommand < Base
5
+ attr_accessor :options
6
+
7
+ def run
8
+ return unless path.empty?
9
+
10
+ self.options = SymbolHash.new(false).update(
11
+ :markup => :rdoc,
12
+ :format => :html,
13
+ :libraries => adapter.libraries,
14
+ :adapter => adapter,
15
+ :template => :doc_server,
16
+ :type => :library_list
17
+ )
18
+ render
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,44 @@
1
+ module YARD
2
+ module Server
3
+ module Commands
4
+ class ListCommand < LibraryCommand
5
+ include Templates::Helpers::BaseHelper
6
+
7
+ def items; raise NotImplementedError end
8
+ def type; raise NotImplementedError end
9
+
10
+ def run
11
+ options.update(:items => items, :template => :doc_server,
12
+ :list_type => request.path.split('/').last, :type => :full_list)
13
+ render
14
+ end
15
+ end
16
+
17
+ class ListClassesCommand < ListCommand
18
+ def type; :class end
19
+
20
+ def items
21
+ Registry.load_all
22
+ run_verifier(Registry.all(:class, :module))
23
+ end
24
+ end
25
+
26
+ class ListMethodsCommand < ListCommand
27
+ include Templates::Helpers::ModuleHelper
28
+
29
+ def type; :methods end
30
+
31
+ def items
32
+ Registry.load_all
33
+ items = Registry.all(:method).sort_by {|m| m.name.to_s }
34
+ prune_method_listing(items)
35
+ end
36
+ end
37
+
38
+ class ListFilesCommand < ListCommand
39
+ def type; :files end
40
+ def items; options[:files] end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,67 @@
1
+ module YARD
2
+ module Server
3
+ module Commands
4
+ class SearchCommand < LibraryCommand
5
+ attr_accessor :results, :query
6
+
7
+ def run
8
+ Registry.load_all
9
+ self.query = request.query['q']
10
+ redirect("/#{adapter.router.docs_prefix}/#{single_library ? library : ''}") if query =~ /\A\s*\Z/
11
+ if found = Registry.at(query)
12
+ redirect(serializer.serialized_path(found))
13
+ end
14
+ search_for_object
15
+ request.xhr? ? serve_xhr : serve_normal
16
+ end
17
+
18
+ def visible_results
19
+ results[0, 10]
20
+ end
21
+
22
+ private
23
+
24
+ def serve_xhr
25
+ self.headers['Content-Type'] = 'text/plain'
26
+ self.body = visible_results.map {|o|
27
+ [(o.type == :method ? o.name(true) : o.name).to_s,
28
+ o.path,
29
+ o.namespace.root? ? '' : o.namespace.path,
30
+ serializer.serialized_path(o)
31
+ ].join(",")
32
+ }.join("\n")
33
+ end
34
+
35
+ def serve_normal
36
+ options.update(
37
+ :visible_results => visible_results,
38
+ :query => query,
39
+ :results => results,
40
+ :template => :doc_server,
41
+ :type => :search
42
+ )
43
+ self.body = Templates::Engine.render(options)
44
+ end
45
+
46
+ def search_for_object
47
+ splitquery = query.split(/\s+/).map {|c| c.downcase }.reject {|m| m.empty? }
48
+ self.results = Registry.all.select {|o|
49
+ o.path.downcase.include?(query.downcase)
50
+ }.reject {|o|
51
+ name = (o.type == :method ? o.name(true) : o.name).to_s.downcase
52
+ !name.include?(query.downcase) ||
53
+ case o.type
54
+ when :method
55
+ !(query =~ /[#.]/) && query.include?("::")
56
+ when :class, :module, :constant, :class_variable
57
+ query =~ /[#.]/
58
+ end
59
+ }.sort_by {|o|
60
+ name = (o.type == :method ? o.name(true) : o.name).to_s
61
+ name.length.to_f / query.length.to_f
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,45 @@
1
+ require 'webrick/httputils'
2
+
3
+ module YARD
4
+ module Server
5
+ module Commands
6
+ class StaticFileCommand < Base
7
+ include WEBrick::HTTPUtils
8
+
9
+ DefaultMimeTypes['js'] = 'text/javascript'
10
+
11
+ STATIC_PATHS = [
12
+ File.join(YARD::TEMPLATE_ROOT, 'default', 'fulldoc', 'html'),
13
+ File.join(File.dirname(__FILE__), '..', 'templates', 'default', 'fulldoc', 'html')
14
+ ]
15
+
16
+ def run
17
+ path = File.cleanpath(request.path).gsub(%r{^(../)+}, '')
18
+ ([adapter.document_root] + STATIC_PATHS).compact.each do |path_prefix|
19
+ file = File.join(path_prefix, path)
20
+ if File.exist?(file)
21
+ ext = "." + (request.path[/\.(\w+)$/, 1] || "html")
22
+ headers['Content-Type'] = mime_type(ext, DefaultMimeTypes)
23
+ self.body = File.read(file)
24
+ return
25
+ end
26
+ end
27
+ favicon?
28
+ self.status = 404
29
+ end
30
+
31
+ private
32
+
33
+ # Return an empty favicon.ico if it does not exist so that
34
+ # browsers don't complain.
35
+ def favicon?
36
+ return unless request.path == '/favicon.ico'
37
+ self.headers['Content-Type'] = 'image/png'
38
+ self.status = 200
39
+ self.body = ''
40
+ raise FinishRequest
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ module YARD
2
+ module Server
3
+ module DocServerHelper
4
+ def url_for(obj, anchor = nil, relative = false)
5
+ return '' if obj.nil?
6
+ return "/#{obj}" if String === obj
7
+ super(obj, anchor, false)
8
+ end
9
+
10
+ def url_for_file(filename, anchor = nil)
11
+ "/#{base_path(router.docs_prefix)}/file/" + filename.sub(%r{^#{@library.source_path.to_s}/}, '') +
12
+ (anchor ? "##{anchor}" : "")
13
+ end
14
+
15
+ def base_path(path)
16
+ path + (@single_library ? '' : "/#{@library}")
17
+ end
18
+
19
+ def router; @adapter.router end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ require 'webrick/httputils'
2
+
3
+ module YARD
4
+ module Server
5
+ class DocServerSerializer < Serializers::FileSystemSerializer
6
+ include WEBrick::HTTPUtils
7
+
8
+ def initialize(command)
9
+ super(:command => command, :extension => '')
10
+ end
11
+
12
+ def serialized_path(object)
13
+ path = case object
14
+ when CodeObjects::RootObject
15
+ "toplevel"
16
+ when CodeObjects::MethodObject
17
+ return escape_path(serialized_path(object.namespace) + (object.scope == :instance ? ":" : ".") + object.name.to_s)
18
+ when CodeObjects::ConstantObject, CodeObjects::ClassVariableObject
19
+ return escape_path(serialized_path(object.namespace)) + "##{object.name}-#{object.type}"
20
+ else
21
+ object.path.gsub('::', '/')
22
+ end
23
+ command = options[:command]
24
+ library_path = command.single_library ? '' : '/' + command.library.to_s
25
+ return escape_path(File.join('', command.adapter.router.docs_prefix, library_path, path))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,86 @@
1
+ require 'fileutils'
2
+
3
+ module YARD
4
+ module Server
5
+ class LibraryNotPreparedError < RuntimeError; end
6
+
7
+ class LibraryVersion
8
+ attr_accessor :name
9
+ attr_accessor :version
10
+ attr_accessor :yardoc_file
11
+ attr_accessor :source
12
+ attr_accessor :source_path
13
+
14
+ def initialize(name, version = nil, yardoc = nil, source = :disk)
15
+ self.name = name
16
+ self.yardoc_file = yardoc
17
+ self.version = version
18
+ self.source = source
19
+ self.source_path = load_source_path
20
+ end
21
+
22
+ def to_s(url_format = true)
23
+ version ? "#{name}#{url_format ? '/' : '-'}#{version}" : "#{name}"
24
+ end
25
+
26
+ def hash; to_s.hash end
27
+
28
+ def eql?(other)
29
+ other.is_a?(LibraryVersion) && other.name == name &&
30
+ other.version == version && other.yardoc_file == yardoc_file
31
+ end
32
+ alias == eql?
33
+ alias equal? eql?
34
+
35
+ def prepare!
36
+ return if yardoc_file
37
+ meth = "load_yardoc_from_#{source}"
38
+ send(meth) if respond_to?(meth)
39
+ end
40
+
41
+ def gemspec
42
+ ver = version ? "= #{version}" : ">= 0"
43
+ Gem.source_index.find_name(name, ver).first
44
+ end
45
+
46
+ protected
47
+
48
+ def load_yardoc_from_disk
49
+ nil
50
+ end
51
+
52
+ def load_yardoc_from_gem
53
+ require 'rubygems'
54
+ ver = version ? "= #{version}" : ">= 0"
55
+ self.yardoc_file = Registry.yardoc_file_for_gem(name, ver)
56
+ unless yardoc_file && File.directory?(yardoc_file)
57
+ Thread.new do
58
+ # Build gem docs on demand
59
+ log.debug "Building gem docs for #{to_s(false)}"
60
+ CLI::Gems.run(name, ver)
61
+ self.yardoc_file = Registry.yardoc_file_for_gem(name, ver)
62
+ FileUtils.touch(File.join(yardoc_file, 'complete'))
63
+ end
64
+ end
65
+ unless yardoc_file && File.exist?(File.join(yardoc_file, 'complete'))
66
+ raise LibraryNotPreparedError
67
+ end
68
+ end
69
+
70
+ def source_path_for_disk
71
+ File.dirname(yardoc_file) if yardoc_file
72
+ end
73
+
74
+ def source_path_for_gem
75
+ gemspec.full_gem_path if gemspec
76
+ end
77
+
78
+ private
79
+
80
+ def load_source_path
81
+ meth = "source_path_for_#{source}"
82
+ send(meth) if respond_to?(meth)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,38 @@
1
+ require 'rack'
2
+ require 'webrick/httputils'
3
+
4
+ module YARD
5
+ module Server
6
+ class RackMiddleware
7
+ def initialize(app, opts = {})
8
+ args = [opts[:libraries] || {}, opts[:options] || {}, opts[:server_options] || {}]
9
+ @app = RackAdapter.new(*args)
10
+ end
11
+
12
+ def call(env) @app.call(env) end
13
+ end
14
+
15
+ class RackAdapter < Adapter
16
+ include WEBrick::HTTPUtils
17
+
18
+ def call(env)
19
+ request = Rack::Request.new(env)
20
+ request.path_info = unescape(request.path_info) # unescape things like %3F
21
+ router.call(request)
22
+ end
23
+
24
+ def start
25
+ server = Rack::Server.new(server_options)
26
+ server.instance_variable_set("@app", self)
27
+ trap("INT") { server.shutdown }
28
+ server.start
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # @private
35
+ class Rack::Request
36
+ alias query params
37
+ def xhr?; (env['HTTP_X_REQUESTED_WITH'] || "").downcase == "xmlhttprequest" end
38
+ end
@@ -0,0 +1,110 @@
1
+ module YARD
2
+ module Server
3
+ class Router
4
+ include StaticCaching
5
+ include Commands
6
+
7
+ attr_accessor :request
8
+
9
+ attr_accessor :adapter
10
+
11
+ def initialize(adapter)
12
+ self.adapter = adapter
13
+ end
14
+
15
+ def call(request)
16
+ self.request = request
17
+ if result = (check_static_cache || route)
18
+ result
19
+ else
20
+ StaticFileCommand.new(adapter.options).call(request)
21
+ end
22
+ end
23
+
24
+ def docs_prefix; 'docs' end
25
+ def list_prefix; 'list' end
26
+ def search_prefix; 'search' end
27
+
28
+ # @return [Array(LibraryVersion, Array<String>)] the library followed
29
+ # by the rest of the path components in the request path. LibraryVersion
30
+ # will be nil if no matching library was found.
31
+ def parse_library_from_path(paths)
32
+ return [adapter.libraries.values.first.first, paths] if adapter.options[:single_library]
33
+ library, paths = nil, paths.dup
34
+ if libs = adapter.libraries[paths.first]
35
+ paths.shift
36
+ if library = libs.find {|l| l.version == paths.first }
37
+ paths.shift
38
+ else # use the last lib in the list
39
+ library = libs.last
40
+ end
41
+ end
42
+ [library, paths]
43
+ end
44
+
45
+ private
46
+
47
+ def route
48
+ path = request.path.gsub(%r{//+}, '/').gsub(%r{^/|/$}, '')
49
+ return route_index if path.empty? || path == docs_prefix
50
+ case path
51
+ when /^(#{docs_prefix}|#{list_prefix}|#{search_prefix})(\/.*|$)/
52
+ prefix = $1
53
+ paths = $2.gsub(%r{^/|/$}, '').split('/')
54
+ library, paths = *parse_library_from_path(paths)
55
+ return unless library
56
+ return case prefix
57
+ when docs_prefix; route_docs(library, paths)
58
+ when list_prefix; route_list(library, paths)
59
+ when search_prefix; route_search(library, paths)
60
+ end
61
+ end
62
+ nil
63
+ end
64
+
65
+ def route_docs(library, paths)
66
+ return route_index if library.nil?
67
+ case paths.first
68
+ when "frames"
69
+ paths.shift
70
+ cmd = FramesCommand
71
+ when "file"
72
+ paths.shift
73
+ cmd = DisplayFileCommand
74
+ else
75
+ cmd = DisplayObjectCommand
76
+ end
77
+ cmd = cmd.new(final_options(library, paths))
78
+ cmd.call(request)
79
+ end
80
+
81
+ def route_index
82
+ if adapter.options[:single_library]
83
+ route_docs(adapter.libraries.values.first.first, [])
84
+ else
85
+ LibraryIndexCommand.new(adapter.options.merge(:path => '')).call(request)
86
+ end
87
+ end
88
+
89
+ def route_list(library, paths)
90
+ return if paths.empty?
91
+ case paths.shift
92
+ when "class"; cmd = ListClassesCommand
93
+ when "methods"; cmd = ListMethodsCommand
94
+ when "files"; cmd = ListFilesCommand
95
+ else; return
96
+ end
97
+ cmd.new(final_options(library, paths)).call(request)
98
+ end
99
+
100
+ def route_search(library, paths)
101
+ return unless paths.empty?
102
+ SearchCommand.new(final_options(library, paths)).call(request)
103
+ end
104
+
105
+ def final_options(library, paths)
106
+ adapter.options.merge(:library => library, :path => paths.join('/'))
107
+ end
108
+ end
109
+ end
110
+ end