aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rubygems/server.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems/server.rb')
-rw-r--r--lib/rubygems/server.rb192
1 files changed, 188 insertions, 4 deletions
diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb
index 2c617ff144..44bee74abf 100644
--- a/lib/rubygems/server.rb
+++ b/lib/rubygems/server.rb
@@ -17,6 +17,7 @@ require 'rubygems/doc_manager'
# name/version/platform index
# * "/quick/" - Individual gemspecs
# * "/gems" - Direct access to download the installable gems
+# * "/rdoc?q=" - Search for installed rdoc documentation
# * legacy indexes:
# * "/Marshal.#{Gem.marshal_version}" - Full SourceIndex dump of metadata
# for installed gems
@@ -32,9 +33,20 @@ require 'rubygems/doc_manager'
class Gem::Server
+ include ERB::Util
include Gem::UserInteraction
- DOC_TEMPLATE = <<-'WEBPAGE'
+ SEARCH = <<-SEARCH
+ <form class="headerSearch" name="headerSearchForm" method="get" action="/rdoc">
+ <div id="search" style="float:right">
+ <span>Filter/Search</span>
+ <input id="q" type="text" style="width:10em" name="q"/>
+ <button type="submit" style="display:none" />
+ </div>
+ </form>
+ SEARCH
+
+ DOC_TEMPLATE = <<-'DOC_TEMPLATE'
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
@@ -47,6 +59,7 @@ class Gem::Server
</head>
<body>
<div id="fileHeader">
+<%= SEARCH %>
<h1>RubyGems Documentation Index</h1>
</div>
<!-- banner header -->
@@ -114,10 +127,10 @@ class Gem::Server
</div>
</body>
</html>
- WEBPAGE
+ DOC_TEMPLATE
# CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
- RDOC_CSS = <<-RDOCCSS
+ RDOC_CSS = <<-RDOC_CSS
body {
font-family: Verdana,Arial,Helvetica,sans-serif;
font-size: 90%;
@@ -325,7 +338,92 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
.ruby-regexp { color: #ffa07a; background: transparent; }
.ruby-value { color: #7fffd4; background: transparent; }
- RDOCCSS
+ RDOC_CSS
+
+ RDOC_NO_DOCUMENTATION = <<-'NO_DOC'
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Found documentation</title>
+ <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
+ </head>
+ <body>
+ <div id="fileHeader">
+<%= SEARCH %>
+ <h1>No documentation found</h1>
+ </div>
+
+ <div id="bodyContent">
+ <div id="contextContent">
+ <div id="description">
+ <p>No gems matched <%= h query.inspect %></p>
+
+ <p>
+ Back to <a href="/">complete gem index</a>
+ </p>
+
+ </div>
+ </div>
+ </div>
+ <div id="validator-badges">
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+ </div>
+ </body>
+</html>
+ NO_DOC
+
+ RDOC_SEARCH_TEMPLATE = <<-'RDOC_SEARCH'
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Found documentation</title>
+ <link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
+ </head>
+ <body>
+ <div id="fileHeader">
+<%= SEARCH %>
+ <h1>Found documentation</h1>
+ </div>
+ <!-- banner header -->
+
+ <div id="bodyContent">
+ <div id="contextContent">
+ <div id="description">
+ <h1>Summary</h1>
+ <p><%=doc_items.length%> documentation topics found.</p>
+ <h1>Topics</h1>
+
+ <dl>
+ <% doc_items.each do |doc_item| %>
+ <dt>
+ <b><%=doc_item[:name]%></b>
+ <a href="<%=doc_item[:url]%>">[rdoc]</a>
+ </dt>
+ <dd>
+ <%=doc_item[:summary]%>
+ <br/>
+ <br/>
+ </dd>
+ <% end %>
+ </dl>
+
+ <p>
+ Back to <a href="/">complete gem index</a>
+ </p>
+
+ </div>
+ </div>
+ </div>
+ <div id="validator-badges">
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
+ </div>
+ </body>
+</html>
+ RDOC_SEARCH
def self.run(options)
new(options[:gemdir], options[:port], options[:daemon]).run
@@ -533,6 +631,90 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
res.body = result
end
+ ##
+ # Can be used for quick navigation to the rdoc documentation. You can then
+ # define a search shortcut for your browser. E.g. in Firefox connect
+ # 'shortcut:rdoc' to http://localhost:8808/rdoc?q=%s template. Then you can
+ # directly open the ActionPack documentation by typing 'rdoc actionp'. If
+ # there are multiple hits for the search term, they are presented as a list
+ # with links.
+ #
+ # Search algorithm aims for an intuitive search:
+ # 1. first try to find the gems and documentation folders which name
+ # starts with the search term
+ # 2. search for entries, that *contain* the search term
+ # 3. show all the gems
+ #
+ # If there is only one search hit, user is immediately redirected to the
+ # documentation for the particular gem, otherwise a list with results is
+ # shown.
+ #
+ # === Additional trick - install documentation for ruby core
+ #
+ # Note: please adjust paths accordingly use for example 'locate yaml.rb' and
+ # 'gem environment' to identify directories, that are specific for your
+ # local installation
+ #
+ # 1. install ruby sources
+ # cd /usr/src
+ # sudo apt-get source ruby
+ #
+ # 2. generate documentation
+ # rdoc -o /usr/lib/ruby/gems/1.8/doc/core/rdoc \
+ # /usr/lib/ruby/1.8 ruby1.8-1.8.7.72
+ #
+ # By typing 'rdoc core' you can now access the core documentation
+
+ def rdoc(req, res)
+ query = req.query['q']
+ show_rdoc_for_pattern("#{query}*", res) && return
+ show_rdoc_for_pattern("*#{query}*", res) && return
+
+ template = ERB.new RDOC_NO_DOCUMENTATION
+
+ res['content-type'] = 'text/html'
+ res.body = template.result binding
+ end
+
+ ##
+ # Returns true and prepares http response, if rdoc for the requested gem
+ # name pattern was found.
+ #
+ # The search is based on the file system content, not on the gems metadata.
+ # This allows additional documentation folders like 'core' for the ruby core
+ # documentation - just put it underneath the main doc folder.
+
+ def show_rdoc_for_pattern(pattern, res)
+ found_gems = Dir.glob("#{@gem_dir}/doc/#{pattern}").select {|path|
+ File.exist? File.join(path, 'rdoc/index.html')
+ }
+ case found_gems.length
+ when 0
+ return false
+ when 1
+ new_path = File.basename(found_gems[0])
+ res.status = 302
+ res['Location'] = "/doc_root/#{new_path}/rdoc/index.html"
+ return true
+ else
+ doc_items = []
+ found_gems.each do |file_name|
+ base_name = File.basename(file_name)
+ doc_items << {
+ :name => base_name,
+ :url => "/doc_root/#{base_name}/rdoc/index.html",
+ :summary => ''
+ }
+ end
+
+ template = ERB.new(RDOC_SEARCH_TEMPLATE)
+ res['content-type'] = 'text/html'
+ result = template.result binding
+ res.body = result
+ return true
+ end
+ end
+
def run
@server.listen nil, @port
@@ -564,6 +746,8 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
@server.mount_proc "/", method(:root)
+ @server.mount_proc "/rdoc", method(:rdoc)
+
paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
paths.each do |mount_point, mount_dir|
@server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,