Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

init commit

  • Loading branch information...
commit 26397472ac8542105fe07cabd4c29e4432d06f5d 0 parents
@shingara authored
Showing with 8,822 additions and 0 deletions.
  1. +18 −0 .gitignore
  2. +35 −0 Rakefile
  3. +2 −0  app/controllers/application.rb
  4. +13 −0 app/controllers/exceptions.rb
  5. +5 −0 app/helpers/global_helpers.rb
  6. +17 −0 app/models/user.rb
  7. +63 −0 app/views/exceptions/not_acceptable.html.erb
  8. +47 −0 app/views/exceptions/not_found.html.erb
  9. +12 −0 app/views/layout/application.html.erb
  10. +2 −0  autotest/discover.rb
  11. +152 −0 autotest/merb.rb
  12. +165 −0 autotest/merb_rspec.rb
  13. +33 −0 config/database.yml
  14. +23 −0 config/dependencies.rb
  15. +15 −0 config/environments/development.rb
  16. +10 −0 config/environments/production.rb
  17. +11 −0 config/environments/rake.rb
  18. +10 −0 config/environments/staging.rb
  19. +12 −0 config/environments/test.rb
  20. +24 −0 config/init.rb
  21. +11 −0 config/rack.rb
  22. +44 −0 config/router.rb
  23. +1,362 −0 doc/rdoc/generators/merb_generator.rb
  24. +640 −0 doc/rdoc/generators/template/merb/api_grease.js
  25. +37 −0 doc/rdoc/generators/template/merb/index.html.erb
  26. +252 −0 doc/rdoc/generators/template/merb/merb.css
  27. +351 −0 doc/rdoc/generators/template/merb/merb.rb
  28. +492 −0 doc/rdoc/generators/template/merb/merb_doc_styles.css
  29. +2,515 −0 doc/rdoc/generators/template/merb/prototype.js
  30. +44 −0 merb/merb-auth/setup.rb
  31. +11 −0 merb/merb-auth/strategies.rb
  32. +9 −0 merb/session/session.rb
  33. +17 −0 public/.htaccess
  34. BIN  public/favicon.ico
  35. BIN  public/images/merb.jpg
  36. +1 −0  public/javascripts/application.js
  37. +32 −0 public/javascripts/jquery.js
  38. +22 −0 public/merb.fcgi
  39. +5 −0 public/robots.txt
  40. +119 −0 public/stylesheets/master.css
  41. 0  spec/spec.opts
  42. +20 −0 spec/spec_helper.rb
  43. +149 −0 tasks/doc.thor
  44. +2,020 −0 tasks/merb.thor
18 .gitignore
@@ -0,0 +1,18 @@
+.DS_Store
+log/*
+tmp/*
+TAGS
+*~
+.#*
+schema/schema.rb
+schema/*_structure.sql
+schema/*.sqlite3
+schema/*.sqlite
+schema/*.db
+*.sqlite
+*.sqlite3
+*.db
+src/*
+.hgignore
+.hg/*
+.svn/*
35 Rakefile
@@ -0,0 +1,35 @@
+require 'rubygems'
+require 'rake/rdoctask'
+
+require 'merb-core'
+require 'merb-core/tasks/merb'
+
+include FileUtils
+
+# Load the basic runtime dependencies; this will include
+# any plugins and therefore plugin rake tasks.
+init_env = ENV['MERB_ENV'] || 'rake'
+Merb.load_dependencies(:environment => init_env)
+
+# Get Merb plugins and dependencies
+Merb::Plugins.rakefiles.each { |r| require r }
+
+# Load any app level custom rakefile extensions from lib/tasks
+tasks_path = File.join(File.dirname(__FILE__), "lib", "tasks")
+rake_files = Dir["#{tasks_path}/*.rake"]
+rake_files.each{|rake_file| load rake_file }
+
+desc "Start runner environment"
+task :merb_env do
+ Merb.start_environment(:environment => init_env, :adapter => 'runner')
+end
+
+require 'spec/rake/spectask'
+require 'merb-core/test/tasks/spectasks'
+desc 'Default: run spec examples'
+task :default => 'spec'
+
+##############################################################################
+# ADD YOUR CUSTOM TASKS IN /lib/tasks
+# NAME YOUR RAKE FILES file_name.rake
+##############################################################################
2  app/controllers/application.rb
@@ -0,0 +1,2 @@
+class Application < Merb::Controller
+end
13 app/controllers/exceptions.rb
@@ -0,0 +1,13 @@
+class Exceptions < Merb::Controller
+
+ # handle NotFound exceptions (404)
+ def not_found
+ render :format => :html
+ end
+
+ # handle NotAcceptable exceptions (406)
+ def not_acceptable
+ render :format => :html
+ end
+
+end
5 app/helpers/global_helpers.rb
@@ -0,0 +1,5 @@
+module Merb
+ module GlobalHelpers
+ # helpers defined here available to all views.
+ end
+end
17 app/models/user.rb
@@ -0,0 +1,17 @@
+# This is a default user class used to activate merb-auth. Feel free to change from a User to
+# Some other class, or to remove it altogether. If removed, merb-auth may not work by default.
+#
+# Don't forget that by default the salted_user mixin is used from merb-more
+# You'll need to setup your db as per the salted_user mixin, and you'll need
+# To use :password, and :password_confirmation when creating a user
+#
+# see merb/merb-auth/setup.rb to see how to disable the salted_user mixin
+#
+# You will need to setup your database and create a user.
+class User
+ include DataMapper::Resource
+
+ property :id, Serial
+ property :login, String
+
+end
63 app/views/exceptions/not_acceptable.html.erb
@@ -0,0 +1,63 @@
+<div id="container">
+ <div id="header-container">
+ <img src="/images/merb.jpg" />
+ <!-- <h1>Mongrel + Erb</h1> -->
+ <h2>pocket rocket web framework</h2>
+ <hr />
+ </div>
+
+ <div id="left-container">
+ <h3>Exception:</h3>
+ <p><%= request.exceptions.first.message %></p>
+ </div>
+
+ <div id="main-container">
+ <h3>Why am I seeing this page?</h3>
+ <p>Merb couldn't find an appropriate content_type to return,
+ based on what you said was available via provides() and
+ what the client requested.</p>
+
+ <h3>How to add a mime-type</h3>
+ <pre><code>
+ Merb.add_mime_type :pdf, :to_pdf, %w[application/pdf], &quot;Content-Encoding&quot; =&gt; &quot;gzip&quot;
+ </code></pre>
+ <h3>What this means is:</h3>
+ <ul>
+ <li>Add a mime-type for :pdf</li>
+ <li>Register the method for converting objects to PDF as <code>#to_pdf</code>.</li>
+ <li>Register the incoming mime-type "Accept" header as <code>application/pdf</code>.</li>
+ <li>Specify a new header for PDF types so it will set <code>Content-Encoding</code> to gzip.</li>
+ </ul>
+
+ <h3>You can then do:</h3>
+ <pre><code>
+ class Foo &lt; Application
+ provides :pdf
+ end
+ </code></pre>
+
+ <h3>Where can I find help?</h3>
+ <p>If you have any questions or if you can't figure something out, please take a
+ look at our <a href="http://merbivore.com/"> project page</a>,
+ feel free to come chat at irc.freenode.net, channel #merb,
+ or post to <a href="http://groups.google.com/group/merb">merb mailing list</a>
+ on Google Groups.</p>
+
+ <h3>What if I've found a bug?</h3>
+ <p>If you want to file a bug or make your own contribution to Merb,
+ feel free to register and create a ticket at our
+ <a href="http://merb.lighthouseapp.com/">project development page</a>
+ on Lighthouse.</p>
+
+ <h3>How do I edit this page?</h3>
+ <p>You can change what people see when this happens by editing <tt>app/views/exceptions/not_acceptable.html.erb</tt>.</p>
+
+ </div>
+
+ <div id="footer-container">
+ <hr />
+ <div class="left"></div>
+ <div class="right">&copy; 2008 the merb dev team</div>
+ <p>&nbsp;</p>
+ </div>
+</div>
47 app/views/exceptions/not_found.html.erb
@@ -0,0 +1,47 @@
+<div id="container">
+ <div id="header-container">
+ <img src="/images/merb.jpg" />
+ <!-- <h1>Mongrel + Erb</h1> -->
+ <h2>pocket rocket web framework</h2>
+ <hr />
+ </div>
+
+ <div id="left-container">
+ <h3>Exception:</h3>
+ <p><%= request.exceptions.first.message %></p>
+ </div>
+
+ <div id="main-container">
+ <h3>Welcome to Merb!</h3>
+ <p>Merb is a light-weight MVC framework written in Ruby. We hope you enjoy it.</p>
+
+ <h3>Where can I find help?</h3>
+ <p>If you have any questions or if you can't figure something out, please take a
+ look at our <a href="http://merbivore.com/"> project page</a>,
+ feel free to come chat at irc.freenode.net, channel #merb,
+ or post to <a href="http://groups.google.com/group/merb">merb mailing list</a>
+ on Google Groups.</p>
+
+ <h3>What if I've found a bug?</h3>
+ <p>If you want to file a bug or make your own contribution to Merb,
+ feel free to register and create a ticket at our
+ <a href="http://merb.lighthouseapp.com/">project development page</a>
+ on Lighthouse.</p>
+
+ <h3>How do I edit this page?</h3>
+ <p>You're seeing this page because you need to edit the following files:
+ <ul>
+ <li>config/router.rb <strong><em>(recommended)</em></strong></li>
+ <li>app/views/exceptions/not_found.html.erb <strong><em>(recommended)</em></strong></li>
+ <li>app/views/layout/application.html.erb <strong><em>(change this layout)</em></strong></li>
+ </ul>
+ </p>
+ </div>
+
+ <div id="footer-container">
+ <hr />
+ <div class="left"></div>
+ <div class="right">&copy; 2008 the merb dev team</div>
+ <p>&nbsp;</p>
+ </div>
+</div>
12 app/views/layout/application.html.erb
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
+ <head>
+ <title>Fresh Merb App</title>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <link rel="stylesheet" href="/stylesheets/master.css" type="text/css" media="screen" charset="utf-8" />
+ </head>
+ <body>
+ <%#= message[:notice] %>
+ <%= catch_content :for_layout %>
+ </body>
+</html>
2  autotest/discover.rb
@@ -0,0 +1,2 @@
+Autotest.add_discovery { "merb" }
+Autotest.add_discovery { "rspec" }
152 autotest/merb.rb
@@ -0,0 +1,152 @@
+# Adapted from Autotest::Rails
+require 'autotest'
+
+class Autotest::Merb < Autotest
+
+ # +model_tests_dir+:: the directory to find model-centric tests
+ # +controller_tests_dir+:: the directory to find controller-centric tests
+ # +view_tests_dir+:: the directory to find view-centric tests
+ # +fixtures_dir+:: the directory to find fixtures in
+ attr_accessor :model_tests_dir, :controller_tests_dir, :view_tests_dir, :fixtures_dir
+
+ def initialize
+ super
+
+ initialize_test_layout
+
+ # Ignore any happenings in these directories
+ add_exception %r%^\./(?:doc|log|public|tmp|\.git|\.hg|\.svn|framework|gems|schema|\.DS_Store|autotest|bin|.*\.sqlite3)%
+ # Ignore SCM directories and custom Autotest mappings
+ %w[.svn .hg .git .autotest].each { |exception| add_exception(exception) }
+
+
+ # Ignore any mappings that Autotest may have already set up
+ clear_mappings
+
+ # Any changes to a file in the root of the 'lib' directory will run any
+ # model test with a corresponding name.
+ add_mapping %r%^lib\/.*\.rb% do |filename, _|
+ files_matching Regexp.new(["^#{model_test_for(filename)}$"])
+ end
+
+ # Any changes to a fixture will run corresponding view, controller and
+ # model tests
+ add_mapping %r%^#{fixtures_dir}/(.*)s.yml% do |_, m|
+ [
+ model_test_for(m[1]),
+ controller_test_for(m[1]),
+ view_test_for(m[1])
+ ]
+ end
+
+ # Any change to a test will cause it to be run
+ add_mapping %r%^test/(unit|models|integration|controllers|views|functional)/.*rb$% do |filename, _|
+ filename
+ end
+
+ # Any change to a model will cause it's corresponding test to be run
+ add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
+ model_test_for(m[1])
+ end
+
+ # Any change to the global helper will result in all view and controller
+ # tests being run
+ add_mapping %r%^app/helpers/global_helpers.rb% do
+ files_matching %r%^test/(views|functional|controllers)/.*_test\.rb$%
+ end
+
+ # Any change to a helper will run it's corresponding view and controller
+ # tests, unless the helper is the global helper. Changes to the global
+ # helper run all view and controller tests.
+ add_mapping %r%^app/helpers/(.*)_helper(s)?.rb% do |_, m|
+ if m[1] == "global" then
+ files_matching %r%^test/(views|functional|controllers)/.*_test\.rb$%
+ else
+ [
+ view_test_for(m[1]),
+ controller_test_for(m[1])
+ ]
+ end
+ end
+
+ # Changes to views result in their corresponding view and controller test
+ # being run
+ add_mapping %r%^app/views/(.*)/% do |_, m|
+ [
+ view_test_for(m[1]),
+ controller_test_for(m[1])
+ ]
+ end
+
+ # Changes to a controller result in its corresponding test being run. If
+ # the controller is the exception or application controller, all
+ # controller tests are run.
+ add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
+ if ["application", "exception"].include?(m[1])
+ files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
+ else
+ controller_test_for(m[1])
+ end
+ end
+
+ # If a change is made to the router, run all controller and view tests
+ add_mapping %r%^config/router.rb$% do # FIX
+ files_matching %r%^test/(controllers|views|functional)/.*_test\.rb$%
+ end
+
+ # If any of the major files governing the environment are altered, run
+ # everything
+ add_mapping %r%^test/test_helper.rb|config/(init|rack|environments/test.rb|database.yml)% do # FIX
+ files_matching %r%^test/(unit|models|controllers|views|functional)/.*_test\.rb$%
+ end
+ end
+
+private
+
+ # Determines the paths we can expect tests or specs to reside, as well as
+ # corresponding fixtures.
+ def initialize_test_layout
+ self.model_tests_dir = "test/unit"
+ self.controller_tests_dir = "test/functional"
+ self.view_tests_dir = "test/views"
+ self.fixtures_dir = "test/fixtures"
+ end
+
+ # Given a filename and the test type, this method will return the
+ # corresponding test's or spec's name.
+ #
+ # ==== Arguments
+ # +filename+<String>:: the file name of the model, view, or controller
+ # +kind_of_test+<Symbol>:: the type of test we that we should run
+ #
+ # ==== Returns
+ # String:: the name of the corresponding test or spec
+ #
+ # ==== Example
+ #
+ # > test_for("user", :model)
+ # => "user_test.rb"
+ # > test_for("login", :controller)
+ # => "login_controller_test.rb"
+ # > test_for("form", :view)
+ # => "form_view_spec.rb" # If you're running a RSpec-like suite
+ def test_for(filename, kind_of_test)
+ name = [filename]
+ name << kind_of_test.to_s if kind_of_test == :view
+ name << "test"
+ return name.join("_") + ".rb"
+ end
+
+ def model_test_for(filename)
+ [model_tests_dir, test_for(filename, :model)].join("/")
+ end
+
+ def controller_test_for(filename)
+ [controller_tests_dir, test_for(filename, :controller)].join("/")
+ end
+
+ def view_test_for(filename)
+ [view_tests_dir, test_for(filename, :view)].join("/")
+ end
+
+end
165 autotest/merb_rspec.rb
@@ -0,0 +1,165 @@
+# Adapted from Autotest::Rails, RSpec's autotest class, as well as merb-core's.
+require 'autotest'
+
+class RspecCommandError < StandardError; end
+
+# This class maps your application's structure so Autotest can understand what
+# specs to run when files change.
+#
+# Fixtures are _not_ covered by this class. If you change a fixture file, you
+# will have to run your spec suite manually, or, better yet, provide your own
+# Autotest map explaining how your fixtures are set up.
+class Autotest::MerbRspec < Autotest
+ def initialize
+ super
+
+ # Ignore any happenings in these directories
+ add_exception %r%^\./(?:doc|log|public|tmp|\.git|\.hg|\.svn|framework|gems|schema|\.DS_Store|autotest|bin|.*\.sqlite3|.*\.thor)%
+ # Ignore SCM directories and custom Autotest mappings
+ %w[.svn .hg .git .autotest].each { |exception| add_exception(exception) }
+
+ # Ignore any mappings that Autotest may have already set up
+ clear_mappings
+
+ # Anything in /lib could have a spec anywhere, if at all. So, look for
+ # files with roughly the same name as the file in /lib
+ add_mapping %r%^lib\/(.*)\.rb% do |_, m|
+ files_matching %r%^spec\/#{m[1]}%
+ end
+
+ add_mapping %r%^spec/(spec_helper|shared/.*)\.rb$% do
+ all_specs
+ end
+
+ # Changing a spec will cause it to run itself
+ add_mapping %r%^spec/.*\.rb$% do |filename, _|
+ filename
+ end
+
+ # Any change to a model will cause it's corresponding test to be run
+ add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
+ spec_for(m[1], 'model')
+ end
+
+ # Any change to global_helpers will result in all view and controller
+ # tests being run
+ add_mapping %r%^app/helpers/global_helpers\.rb% do
+ files_matching %r%^spec/(views|controllers|helpers|requests)/.*_spec\.rb$%
+ end
+
+ # Any change to a helper will cause its spec to be run
+ add_mapping %r%^app/helpers/((.*)_helper(s)?)\.rb% do |_, m|
+ spec_for(m[1], 'helper')
+ end
+
+ # Changes to a view cause its spec to be run
+ add_mapping %r%^app/views/(.*)/% do |_, m|
+ spec_for(m[1], 'view')
+ end
+
+ # Changes to a controller result in its corresponding spec being run. If
+ # the controller is the exception or application controller, all
+ # controller specs are run.
+ add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
+ if ["application", "exception"].include?(m[1])
+ files_matching %r%^spec/controllers/.*_spec\.rb$%
+ else
+ spec_for(m[1], 'controller')
+ end
+ end
+
+ # If a change is made to the router, run controller, view and helper specs
+ add_mapping %r%^config/router.rb$% do
+ files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$%
+ end
+
+ # If any of the major files governing the environment are altered, run
+ # everything
+ add_mapping %r%^config/(init|rack|environments/test).*\.rb|database\.yml% do
+ all_specs
+ end
+ end
+
+ def failed_results(results)
+ results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m)
+ end
+
+ def handle_results(results)
+ @failures = failed_results(results)
+ @files_to_test = consolidate_failures(@failures)
+ @files_to_test.empty? && !$TESTING ? hook(:green) : hook(:red)
+ @tainted = !@files_to_test.empty?
+ end
+
+ def consolidate_failures(failed)
+ filters = Hash.new { |h,k| h[k] = [] }
+ failed.each do |spec, failed_trace|
+ if f = test_files_for(failed).find { |f| f =~ /spec\// }
+ filters[f] << spec
+ break
+ end
+ end
+ filters
+ end
+
+ def make_test_cmd(specs_to_runs)
+ [
+ ruby,
+ "-S",
+ spec_command,
+ add_options_if_present,
+ files_to_test.keys.flatten.join(' ')
+ ].join(' ')
+ end
+
+ def add_options_if_present
+ File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
+ end
+
+ # Finds the proper spec command to use. Precendence is set in the
+ # lazily-evaluated method spec_commands. Alias + Override that in
+ # ~/.autotest to provide a different spec command then the default
+ # paths provided.
+ def spec_command(separator=File::ALT_SEPARATOR)
+ unless defined?(@spec_command)
+ @spec_command = spec_commands.find { |cmd| File.exists?(cmd) }
+
+ raise RspecCommandError, "No spec command could be found" unless @spec_command
+
+ @spec_command.gsub!(File::SEPARATOR, separator) if separator
+ end
+ @spec_command
+ end
+
+ # Autotest will look for spec commands in the following
+ # locations, in this order:
+ #
+ # * default spec bin/loader installed in Rubygems
+ # * any spec command found in PATH
+ def spec_commands
+ [File.join(Config::CONFIG['bindir'], 'spec'), 'spec']
+ end
+
+private
+
+ # Runs +files_matching+ for all specs
+ def all_specs
+ files_matching %r%^spec/.*_spec\.rb$%
+ end
+
+ # Generates a path to some spec given its kind and the match from a mapping
+ #
+ # ==== Arguments
+ # match<String>:: the match from a mapping
+ # kind<String>:: the kind of spec that the match represents
+ #
+ # ==== Returns
+ # String
+ #
+ # ==== Example
+ # > spec_for('post', :view')
+ # => "spec/views/post_spec.rb"
+ def spec_for(match, kind)
+ File.join("spec", kind + 's', "#{match}_spec.rb")
+ end
+end
33 config/database.yml
@@ -0,0 +1,33 @@
+---
+# This is a sample database file for the DataMapper ORM
+development: &defaults
+ # These are the settings for repository :default
+ adapter: sqlite3
+ database: sample_development.db
+
+ # Add more repositories
+ # repositories:
+ # repo1:
+ # adapter: sqlite3
+ # database: sample_1_development.db
+ # repo2:
+ # ...
+
+test:
+ <<: *defaults
+ database: sample_test.db
+
+ # repositories:
+ # repo1:
+ # database: sample_1_test.db
+
+production:
+ <<: *defaults
+ database: production.db
+
+ # repositories:
+ # repo1:
+ # database: sample_production.db
+
+rake:
+ <<: *defaults
23 config/dependencies.rb
@@ -0,0 +1,23 @@
+# dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading.
+merb_gems_version = "1.0"
+dm_gems_version = "0.9.6"
+
+# For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components
+dependency "merb-action-args", merb_gems_version
+dependency "merb-assets", merb_gems_version
+dependency "merb-cache", merb_gems_version
+dependency "merb-helpers", merb_gems_version
+dependency "merb-mailer", merb_gems_version
+dependency "merb-slices", merb_gems_version
+dependency "merb-auth-core", merb_gems_version
+dependency "merb-auth-more", merb_gems_version
+dependency "merb-auth-slice-password", merb_gems_version
+dependency "merb-param-protection", merb_gems_version
+dependency "merb-exceptions", merb_gems_version
+
+dependency "dm-core", dm_gems_version
+dependency "dm-aggregates", dm_gems_version
+dependency "dm-migrations", dm_gems_version
+dependency "dm-timestamps", dm_gems_version
+dependency "dm-types", dm_gems_version
+dependency "dm-validations", dm_gems_version
15 config/environments/development.rb
@@ -0,0 +1,15 @@
+Merb.logger.info("Loaded DEVELOPMENT Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = true
+ c[:reload_templates] = true
+ c[:reload_classes] = true
+ c[:reload_time] = 0.5
+ c[:ignore_tampered_cookies] = true
+ c[:log_auto_flush ] = true
+ c[:log_level] = :debug
+
+ c[:log_stream] = STDOUT
+ c[:log_file] = nil
+ # Or redirect logging into a file:
+ # c[:log_file] = Merb.root / "log" / "development.log"
+}
10 config/environments/production.rb
@@ -0,0 +1,10 @@
+Merb.logger.info("Loaded PRODUCTION Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = false
+ c[:reload_classes] = false
+ c[:log_level] = :error
+
+ c[:log_file] = Merb.root / "log" / "production.log"
+ # or redirect logger using IO handle
+ # c[:log_stream] = STDOUT
+}
11 config/environments/rake.rb
@@ -0,0 +1,11 @@
+Merb.logger.info("Loaded RAKE Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = true
+ c[:reload_classes] = false
+ c[:log_auto_flush ] = true
+
+ c[:log_stream] = STDOUT
+ c[:log_file] = nil
+ # Or redirect logging into a file:
+ # c[:log_file] = Merb.root / "log" / "development.log"
+}
10 config/environments/staging.rb
@@ -0,0 +1,10 @@
+Merb.logger.info("Loaded STAGING Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = false
+ c[:reload_classes] = false
+ c[:log_level] = :error
+
+ c[:log_file] = Merb.root / "log" / "staging.log"
+ # or redirect logger using IO handle
+ # c[:log_stream] = STDOUT
+}
12 config/environments/test.rb
@@ -0,0 +1,12 @@
+Merb.logger.info("Loaded TEST Environment...")
+Merb::Config.use { |c|
+ c[:testing] = true
+ c[:exception_details] = true
+ c[:log_auto_flush ] = true
+ # log less in testing environment
+ c[:log_level] = :error
+
+ #c[:log_file] = Merb.root / "log" / "test.log"
+ # or redirect logger using IO handle
+ c[:log_stream] = STDOUT
+}
24 config/init.rb
@@ -0,0 +1,24 @@
+# Go to http://wiki.merbivore.com/pages/init-rb
+
+require 'config/dependencies.rb'
+
+use_orm :datamapper
+use_test :rspec
+use_template_engine :erb
+
+Merb::Config.use do |c|
+ c[:use_mutex] = false
+ c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper
+
+ # cookie session store configuration
+ c[:session_secret_key] = '6b1c16afb63c08e341d08386a8be8b4a65334865' # required for cookie session store
+ # c[:session_id_key] = '_session_id' # cookie session id key, defaults to "_session_id"
+end
+
+Merb::BootLoader.before_app_loads do
+ # This will get executed after dependencies have been loaded but before your app's classes have loaded.
+end
+
+Merb::BootLoader.after_app_loads do
+ # This will get executed after your app's classes have been loaded.
+end
11 config/rack.rb
@@ -0,0 +1,11 @@
+# use PathPrefix Middleware if :path_prefix is set in Merb::Config
+if prefix = ::Merb::Config[:path_prefix]
+ use Merb::Rack::PathPrefix, prefix
+end
+
+# comment this out if you are running merb behind a load balancer
+# that serves static files
+use Merb::Rack::Static, Merb.dir_for(:public)
+
+# this is our main merb application
+run Merb::Rack::Application.new
44 config/router.rb
@@ -0,0 +1,44 @@
+# Merb::Router is the request routing mapper for the merb framework.
+#
+# You can route a specific URL to a controller / action pair:
+#
+# match("/contact").
+# to(:controller => "info", :action => "contact")
+#
+# You can define placeholder parts of the url with the :symbol notation. These
+# placeholders will be available in the params hash of your controllers. For example:
+#
+# match("/books/:book_id/:action").
+# to(:controller => "books")
+#
+# Or, use placeholders in the "to" results for more complicated routing, e.g.:
+#
+# match("/admin/:module/:controller/:action/:id").
+# to(:controller => ":module/:controller")
+#
+# You can specify conditions on the placeholder by passing a hash as the second
+# argument of "match"
+#
+# match("/registration/:course_name", :course_name => /^[a-z]{3,5}-\d{5}$/).
+# to(:controller => "registration")
+#
+# You can also use regular expressions, deferred routes, and many other options.
+# See merb/specs/merb/router.rb for a fairly complete usage sample.
+
+Merb.logger.info("Compiling routes...")
+Merb::Router.prepare do
+ # RESTful routes
+ # resources :posts
+
+ # Adds the required routes for merb-auth using the password slice
+ slice(:merb_auth_slice_password, :name_prefix => nil, :path_prefix => "")
+
+ # This is the default route for /:controller/:action/:id
+ # This is fine for most cases. If you're heavily using resource-based
+ # routes, you may want to comment/remove this line to prevent
+ # clients from calling your create or destroy actions with a GET
+ default_routes
+
+ # Change this for your home page to be available at /
+ # match('/').to(:controller => 'whatever', :action =>'index')
+end
1,362 doc/rdoc/generators/merb_generator.rb
@@ -0,0 +1,1362 @@
+
+# # We're responsible for generating all the HTML files
+# from the object tree defined in code_objects.rb. We
+# generate:
+#
+# [files] an html file for each input file given. These
+# input files appear as objects of class
+# TopLevel
+#
+# [classes] an html file for each class or module encountered.
+# These classes are not grouped by file: if a file
+# contains four classes, we'll generate an html
+# file for the file itself, and four html files
+# for the individual classes.
+#
+# Method descriptions appear in whatever entity (file, class,
+# or module) that contains them.
+#
+# We generate files in a structure below a specified subdirectory,
+# normally +doc+.
+#
+# opdir
+# |
+# |___ files
+# | |__ per file summaries
+# |
+# |___ classes
+# |__ per class/module descriptions
+#
+# HTML is generated using the Template class.
+#
+
+require 'ftools'
+
+require 'rdoc/options'
+require 'rdoc/template'
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_html'
+require 'cgi'
+
+module Generators
+
+ # Name of sub-direcories that hold file and class/module descriptions
+
+ FILE_DIR = "files"
+ CLASS_DIR = "classes"
+ CSS_NAME = "stylesheet.css"
+
+
+ ##
+ # Build a hash of all items that can be cross-referenced.
+ # This is used when we output required and included names:
+ # if the names appear in this hash, we can generate
+ # an html cross reference to the appropriate description.
+ # We also use this when parsing comment blocks: any decorated
+ # words matching an entry in this list are hyperlinked.
+
+ class AllReferences
+ @@refs = {}
+
+ def AllReferences::reset
+ @@refs = {}
+ end
+
+ def AllReferences.add(name, html_class)
+ @@refs[name] = html_class
+ end
+
+ def AllReferences.[](name)
+ @@refs[name]
+ end
+
+ def AllReferences.keys
+ @@refs.keys
+ end
+ end
+
+
+ ##
+ # Subclass of the SM::ToHtml class that supports looking
+ # up words in the AllReferences list. Those that are
+ # found (like AllReferences in this comment) will
+ # be hyperlinked
+
+ class HyperlinkHtml < SM::ToHtml
+ # We need to record the html path of our caller so we can generate
+ # correct relative paths for any hyperlinks that we find
+ def initialize(from_path, context)
+ super()
+ @from_path = from_path
+
+ @parent_name = context.parent_name
+ @parent_name += "::" if @parent_name
+ @context = context
+ end
+
+ # We're invoked when any text matches the CROSSREF pattern
+ # (defined in MarkUp). If we fine the corresponding reference,
+ # generate a hyperlink. If the name we're looking for contains
+ # no punctuation, we look for it up the module/class chain. For
+ # example, HyperlinkHtml is found, even without the Generators::
+ # prefix, because we look for it in module Generators first.
+
+ def handle_special_CROSSREF(special)
+ name = special.text
+ if name[0,1] == '#'
+ lookup = name[1..-1]
+ name = lookup unless Options.instance.show_hash
+ else
+ lookup = name
+ end
+
+ if /([A-Z].*)[.\#](.*)/ =~ lookup
+ container = $1
+ method = $2
+ ref = @context.find_symbol(container, method)
+ else
+ ref = @context.find_symbol(lookup)
+ end
+
+ if ref and ref.document_self
+ "<a href=\"index.html?a=#{ref.aref}&name=#{name}\">#{name}</a>"
+ else
+ name #it does not need to be a link
+ end
+ end
+
+
+ # Generate a hyperlink for url, labeled with text. Handle the
+ # special cases for img: and link: described under handle_special_HYPEDLINK
+ def gen_url(url, text)
+ if url =~ /([A-Za-z]+):(.*)/
+ type = $1
+ path = $2
+ else
+ type = "http"
+ path = url
+ url = "http://#{url}"
+ end
+
+ if type == "link"
+ url = path
+ end
+
+ if (type == "http" || type == "link") && url =~ /\.(gif|png|jpg|jpeg|bmp)$/
+ "<img src=\"#{url}\">"
+ elsif (type == "http" || type == "link")
+ "<a href=\"#{url}\" target=\"_blank\">#{text}</a>"
+ else
+ "<a href=\"#\" onclick=\"jsHref('#{url}');\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
+
+ end
+ end
+
+ # And we're invoked with a potential external hyperlink mailto:
+ # just gets inserted. http: links are checked to see if they
+ # reference an image. If so, that image gets inserted using an
+ # <img> tag. Otherwise a conventional <a href> is used. We also
+ # support a special type of hyperlink, link:, which is a reference
+ # to a local file whose path is relative to the --op directory.
+
+ def handle_special_HYPERLINK(special)
+ url = special.text
+ gen_url(url, url)
+ end
+
+ # HEre's a hypedlink where the label is different to the URL
+ # <label>[url]
+ #
+
+ def handle_special_TIDYLINK(special)
+ text = special.text
+ # unless text =~ /(\S+)\[(.*?)\]/
+ unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
+ return text
+ end
+ label = $1
+ url = $2
+ gen_url(url, label)
+ end
+
+ end
+
+
+
+ #####################################################################
+ #
+ # Handle common markup tasks for the various Html classes
+ #
+
+ module MarkUp
+
+ # Convert a string in markup format into HTML. We keep a cached
+ # SimpleMarkup object lying around after the first time we're
+ # called per object.
+
+ def markup(str, remove_para=false)
+ return '' unless str
+ unless defined? @markup
+ @markup = SM::SimpleMarkup.new
+
+ # class names, variable names, file names, or instance variables
+ @markup.add_special(/(
+ \b([A-Z]\w*(::\w+)*[.\#]\w+) # A::B.meth
+ | \b([A-Z]\w+(::\w+)*) # A::B..
+ | \#\w+[!?=]? # #meth_name
+ | \b\w+([_\/\.]+\w+)+[!?=]? # meth_name
+ )/x, :CROSSREF)
+
+ # external hyperlinks
+ @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
+
+ # and links of the form <text>[<url>]
+ @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
+ # @markup.add_special(/\b(\S+?\[\S+?\.\S+?\])/, :TIDYLINK)
+
+ end
+ unless defined? @html_formatter
+ @html_formatter = HyperlinkHtml.new(self.path, self)
+ end
+
+ # Convert leading comment markers to spaces, but only
+ # if all non-blank lines have them
+
+ if str =~ /^(?>\s*)[^\#]/
+ content = str
+ else
+ content = str.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
+ end
+
+ res = @markup.convert(content, @html_formatter)
+ if remove_para
+ res.sub!(/^<p>/, '')
+ res.sub!(/<\/p>$/, '')
+ end
+ res
+ end
+
+
+ def style_url(path, css_name=nil)
+ css_name ||= CSS_NAME
+ end
+
+ # Build a webcvs URL with the given 'url' argument. URLs with a '%s' in them
+ # get the file's path sprintfed into them; otherwise they're just catenated
+ # together.
+
+ def cvs_url(url, full_path)
+ if /%s/ =~ url
+ return sprintf( url, full_path )
+ else
+ return url + full_path
+ end
+ end
+ end
+
+
+ #####################################################################
+ #
+ # A Context is built by the parser to represent a container: contexts
+ # hold classes, modules, methods, require lists and include lists.
+ # ClassModule and TopLevel are the context objects we process here
+ #
+ class ContextUser
+
+ include MarkUp
+
+ attr_reader :context
+
+ def initialize(context, options)
+ @context = context
+ @options = options
+
+ end
+
+ # convenience method to build a hyperlink # Where's the DRY in this?? Put this in the template where it belongs
+ def href(link, cls, name)
+ %{"<a href=\"#\" onclick=\"jsHref('#{link}');\" class=\"#{cls}\">#{name}</a>"}
+ end
+
+ # Create a list of HtmlMethod objects for each method
+ # in the corresponding context object. If the @options.show_all
+ # variable is set (corresponding to the <tt>--all</tt> option,
+ # we include all methods, otherwise just the public ones.
+
+ def collect_methods
+ list = @context.method_list
+ unless @options.show_all
+ list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
+ end
+ @methods = list.collect {|m| HtmlMethod.new(m, self, @options) }
+ end
+
+ # Build a summary list of all the methods in this context
+ def build_method_summary_list(path_prefix="")
+ collect_methods unless @methods
+ meths = @methods.sort
+ res = []
+ meths.each do |meth|
+ res << {
+ "name" => CGI.escapeHTML(meth.name),
+ "aref" => meth.aref,
+ "href" => meth.path
+ }
+ end
+ res
+ end
+
+
+ # Build a list of aliases for which we couldn't find a
+ # corresponding method
+ def build_alias_summary_list(section)
+ values = []
+ @context.aliases.each do |al|
+ next unless al.section == section
+ res = {
+ 'old_name' => al.old_name,
+ 'new_name' => al.new_name,
+ }
+ if al.comment && !al.comment.empty?
+ res['desc'] = markup(al.comment, true)
+ end
+ values << res
+ end
+ values
+ end
+
+ # Build a list of constants
+ def build_constants_summary_list(section)
+ values = []
+ @context.constants.each do |co|
+ next unless co.section == section
+ res = {
+ 'name' => co.name,
+ 'value' => CGI.escapeHTML(co.value)
+ }
+ res['desc'] = markup(co.comment, true) if co.comment && !co.comment.empty?
+ values << res
+ end
+ values
+ end
+
+ def build_requires_list(context)
+ potentially_referenced_list(context.requires) {|fn| [fn + ".rb"] }
+ end
+
+ def build_include_list(context)
+ potentially_referenced_list(context.includes)
+ end
+
+ # Build a list from an array of <i>Htmlxxx</i> items. Look up each
+ # in the AllReferences hash: if we find a corresponding entry,
+ # we generate a hyperlink to it, otherwise just output the name.
+ # However, some names potentially need massaging. For example,
+ # you may require a Ruby file without the .rb extension,
+ # but the file names we know about may have it. To deal with
+ # this, we pass in a block which performs the massaging,
+ # returning an array of alternative names to match
+
+ def potentially_referenced_list(array)
+ res = []
+ array.each do |i|
+ ref = AllReferences[i.name]
+ # if !ref
+ # container = @context.parent
+ # while !ref && container
+ # name = container.name + "::" + i.name
+ # ref = AllReferences[name]
+ # container = container.parent
+ # end
+ # end
+
+ ref = @context.find_symbol(i.name)
+ ref = ref.viewer if ref
+
+ if !ref && block_given?
+ possibles = yield(i.name)
+ while !ref and !possibles.empty?
+ ref = AllReferences[possibles.shift]
+ end
+ end
+ h_name = CGI.escapeHTML(i.name)
+ if ref and ref.document_self
+ path = ref.path
+ res << { "name" => h_name, "href" => path }
+ else
+ res << { "name" => h_name, "href" => "" }
+ end
+ end
+ res
+ end
+
+ # Build an array of arrays of method details. The outer array has up
+ # to six entries, public, private, and protected for both class
+ # methods, the other for instance methods. The inner arrays contain
+ # a hash for each method
+
+ def build_method_detail_list(section)
+ outer = []
+
+ methods = @methods.sort
+ for singleton in [true, false]
+ for vis in [ :public, :protected, :private ]
+ res = []
+ methods.each do |m|
+ if m.section == section and
+ m.document_self and
+ m.visibility == vis and
+ m.singleton == singleton
+ row = {}
+ if m.call_seq
+ row["callseq"] = m.call_seq.gsub(/->/, '&rarr;')
+ else
+ row["name"] = CGI.escapeHTML(m.name)
+ row["params"] = m.params
+ end
+ desc = m.description.strip
+ row["m_desc"] = desc unless desc.empty?
+ row["aref"] = m.aref
+ row["href"] = m.path
+ row["m_seq"] = m.seq
+ row["visibility"] = m.visibility.to_s
+
+ alias_names = []
+ m.aliases.each do |other|
+ if other.viewer # won't be if the alias is private
+ alias_names << {
+ 'name' => other.name,
+ 'href' => other.viewer.path,
+ 'aref' => other.viewer.aref
+ }
+ end
+ end
+ unless alias_names.empty?
+ row["aka"] = alias_names
+ end
+
+ #if @options.inline_source
+ code = m.source_code
+ row["sourcecode"] = code if code
+ #else
+ # code = m.src_url
+ #if code
+ # row["codeurl"] = code
+ # row["imgurl"] = m.img_url
+ #end
+ #end
+ res << row
+ end
+ end
+ if res.size > 0
+ outer << {
+ "type" => vis.to_s.capitalize,
+ "category" => singleton ? "Class" : "Instance",
+ "methods" => res
+ }
+ end
+ end
+ end
+ outer
+ end
+
+ # Build the structured list of classes and modules contained
+ # in this context.
+
+ def build_class_list(level, from, section, infile=nil)
+ res = ""
+ prefix = "&nbsp;&nbsp;::" * level;
+
+ from.modules.sort.each do |mod|
+ next unless mod.section == section
+ next if infile && !mod.defined_in?(infile)
+ if mod.document_self
+ res <<
+ prefix <<
+ "Module " <<
+ href(mod.viewer.path, "link", mod.full_name) <<
+ "<br />\n" <<
+ build_class_list(level + 1, mod, section, infile)
+ end
+ end
+
+ from.classes.sort.each do |cls|
+ next unless cls.section == section
+ next if infile && !cls.defined_in?(infile)
+ if cls.document_self
+ res <<
+ prefix <<
+ "Class " <<
+ href(cls.viewer.path, "link", cls.full_name) <<
+ "<br />\n" <<
+ build_class_list(level + 1, cls, section, infile)
+ end
+ end
+
+ res
+ end
+
+ def document_self
+ @context.document_self
+ end
+
+ def diagram_reference(diagram)
+ res = diagram.gsub(/((?:src|href)=")(.*?)"/) {
+ $1 + $2 + '"'
+ }
+ res
+ end
+
+
+ # Find a symbol in ourselves or our parent
+ def find_symbol(symbol, method=nil)
+ res = @context.find_symbol(symbol, method)
+ if res
+ res = res.viewer
+ end
+ res
+ end
+
+ # create table of contents if we contain sections
+
+ def add_table_of_sections
+ toc = []
+ @context.sections.each do |section|
+ if section.title
+ toc << {
+ 'secname' => section.title,
+ 'href' => section.sequence
+ }
+ end
+ end
+
+ @values['toc'] = toc unless toc.empty?
+ end
+
+
+ end
+
+ #####################################################################
+ #
+ # Wrap a ClassModule context
+
+ class HtmlClass < ContextUser
+
+ @@c_seq = "C00000000"
+
+ attr_reader :path
+
+ def initialize(context, html_file, prefix, options)
+ super(context, options)
+ @@c_seq = @@c_seq.succ
+ @c_seq = @@c_seq
+ @html_file = html_file
+ @is_module = context.is_module?
+ @values = {}
+
+ context.viewer = self
+
+ @path = http_url(context.full_name, prefix)
+
+ collect_methods
+
+ AllReferences.add(name, self)
+ end
+
+ # return the relative file name to store this class in,
+ # which is also its url
+ def http_url(full_name, prefix)
+ path = full_name.dup
+ if path['<<']
+ path.gsub!(/<<\s*(\w*)/) { "from-#$1" }
+ end
+ File.join(prefix, path.split("::")) + ".html"
+ end
+
+ def seq
+ @c_seq
+ end
+
+ def aref
+ @c_seq
+ end
+
+ def scope
+ a = @context.full_name.split("::")
+ if a.length > 1
+ a.pop
+ a.join("::")
+ else
+ ""
+ end
+ end
+
+ def name
+ @context.full_name.gsub("#{scope}::", '')
+ end
+
+ def full_name
+ @context.full_name
+ end
+
+ def parent_name
+ @context.parent.full_name
+ end
+
+ def write_on(f)
+ value_hash
+ template = TemplatePage.new(RDoc::Page::BODY,
+ RDoc::Page::CLASS_PAGE,
+ RDoc::Page::METHOD_LIST)
+ template.write_html_on(f, @values)
+ end
+
+ def value_hash
+ class_attribute_values
+ add_table_of_sections
+
+ @values["charset"] = @options.charset
+ @values["style_url"] = style_url(path, @options.css)
+
+ # Convert README to html
+ unless File.exist?('files/README.html')
+ File.open('files/README.html', 'w') do |file|
+ file << markup(File.read(File.expand_path(@options.main_page)))
+ end
+ end
+
+ d = markup(@context.comment)
+ @values["description"] = d unless d.empty?
+
+ ml = build_method_summary_list
+ @values["methods"] = ml unless ml.empty?
+
+ il = build_include_list(@context)
+ @values["includes"] = il unless il.empty?
+
+ @values["sections"] = @context.sections.map do |section|
+
+ secdata = {
+ "sectitle" => section.title,
+ "secsequence" => section.sequence,
+ "seccomment" => markup(section.comment)
+ }
+
+ al = build_alias_summary_list(section)
+ secdata["aliases"] = al unless al.empty?
+
+ co = build_constants_summary_list(section)
+ secdata["constants"] = co unless co.empty?
+
+ al = build_attribute_list(section)
+ secdata["attributes"] = al unless al.empty?
+
+ cl = build_class_list(0, @context, section)
+ secdata["classlist"] = cl unless cl.empty?
+
+ mdl = build_method_detail_list(section)
+ secdata["method_list"] = mdl unless mdl.empty?
+
+ secdata
+ end
+
+ @values
+ end
+
+ def build_attribute_list(section)
+ atts = @context.attributes.sort
+ res = []
+ atts.each do |att|
+ next unless att.section == section
+ if att.visibility == :public || att.visibility == :protected || @options.show_all
+ entry = {
+ "name" => CGI.escapeHTML(att.name),
+ "rw" => att.rw,
+ "a_desc" => markup(att.comment, true)
+ }
+ unless att.visibility == :public || att.visibility == :protected
+ entry["rw"] << "-"
+ end
+ res << entry
+ end
+ end
+ res
+ end
+
+ def class_attribute_values
+ h_name = CGI.escapeHTML(name)
+
+ @values["classmod"] = @is_module ? "Module" : "Class"
+ @values["title"] = "#{@values['classmod']}: #{h_name}"
+
+ c = @context
+ c = c.parent while c and !c.diagram
+ if c && c.diagram
+ @values["diagram"] = diagram_reference(c.diagram)
+ end
+
+ @values["full_name"] = h_name
+ @values["class_seq"] = seq
+ parent_class = @context.superclass
+
+ if parent_class
+ @values["parent"] = CGI.escapeHTML(parent_class)
+
+ if parent_name
+ lookup = parent_name + "::" + parent_class
+ else
+ lookup = parent_class
+ end
+
+ parent_url = AllReferences[lookup] || AllReferences[parent_class]
+
+ if parent_url and parent_url.document_self
+ @values["par_url"] = parent_url.path
+ end
+ end
+
+ files = []
+ @context.in_files.each do |f|
+ res = {}
+ full_path = CGI.escapeHTML(f.file_absolute_name)
+
+ res["full_path"] = full_path
+ res["full_path_url"] = f.viewer.path if f.document_self
+
+ if @options.webcvs
+ res["cvsurl"] = cvs_url( @options.webcvs, full_path )
+ end
+
+ files << res
+ end
+
+ @values['infiles'] = files
+ end
+
+ def <=>(other)
+ self.name <=> other.name
+ end
+
+ end
+
+ #####################################################################
+ #
+ # Handles the mapping of a file's information to HTML. In reality,
+ # a file corresponds to a +TopLevel+ object, containing modules,
+ # classes, and top-level methods. In theory it _could_ contain
+ # attributes and aliases, but we ignore these for now.
+
+ class HtmlFile < ContextUser
+
+ @@f_seq = "F00000000"
+
+ attr_reader :path
+ attr_reader :name
+
+ def initialize(context, options, file_dir)
+ super(context, options)
+ @@f_seq = @@f_seq.succ
+ @f_seq = @@f_seq
+ @values = {}
+
+ @path = http_url(file_dir)
+ @source_file_path = File.expand_path(@context.file_relative_name).gsub("\/doc\/", "/")
+ @name = @context.file_relative_name
+
+ collect_methods
+ AllReferences.add(name, self)
+ context.viewer = self
+ end
+
+ def http_url(file_dir)
+ File.join(file_dir, @context.file_relative_name.tr('.', '_')) + ".html"
+ end
+
+ def filename_to_label
+ @context.file_relative_name.gsub(/%|\/|\?|\#/) {|s| '%' + ("%x" % s[0]) }
+ end
+
+ def seq
+ @f_seq
+ end
+
+ def aref
+ @f_seq
+ end
+
+ def name
+ full_path = @context.file_absolute_name
+ short_name = File.basename(full_path)
+ end
+
+ def full_name
+ @context.file_absolute_name
+ end
+
+ def scope
+ @context.file_relative_name.gsub(/\/#{name}$/, '')
+ end
+
+ def parent_name
+ nil
+ end
+
+ def full_file_source
+ ret_str = ""
+ File.open(@source_file_path, 'r') do |f|
+ while(!f.eof?) do
+ ret_str += f.readline()
+ end
+ end
+ ret_str
+ rescue
+ "file not found -#{@source_file_path}-"
+ #@source_file_path
+ end
+
+ def value_hash
+ file_attribute_values
+ add_table_of_sections
+
+ @values["charset"] = @options.charset
+ @values["href"] = path
+ @values["style_url"] = style_url(path, @options.css)
+ @values["file_seq"] = seq
+
+ #pulling in the source for this file
+ #@values["source_code"] = @context.token_stream
+
+ @values["file_source_code"] = CGI.escapeHTML(full_file_source)
+
+ if @context.comment
+ d = markup(@context.comment)
+ @values["description"] = d if d.size > 0
+ end
+
+ ml = build_method_summary_list
+ @values["methods"] = ml unless ml.empty?
+
+ il = build_include_list(@context)
+ @values["includes"] = il unless il.empty?
+
+ rl = build_requires_list(@context)
+ @values["requires"] = rl unless rl.empty?
+
+
+ file_context = @context
+
+ @values["sections"] = @context.sections.map do |section|
+
+ secdata = {
+ "sectitle" => section.title,
+ "secsequence" => section.sequence,
+ "seccomment" => markup(section.comment)
+ }
+
+ cl = build_class_list(0, @context, section, file_context)
+ @values["classlist"] = cl unless cl.empty?
+
+ mdl = build_method_detail_list(section)
+ secdata["method_list"] = mdl unless mdl.empty?
+
+ al = build_alias_summary_list(section)
+ secdata["aliases"] = al unless al.empty?
+
+ co = build_constants_summary_list(section)
+ @values["constants"] = co unless co.empty?
+
+ secdata
+ end
+
+ @values
+ end
+
+ def write_on(f)
+ value_hash
+ template = TemplatePage.new(RDoc::Page::SRC_BODY,RDoc::Page::FILE_PAGE, RDoc::Page::METHOD_LIST)
+ template.write_html_on(f, @values)
+ end
+
+ def file_attribute_values
+ full_path = @context.file_absolute_name
+ short_name = File.basename(full_path)
+
+ @values["title"] = CGI.escapeHTML("File: #{short_name}")
+
+ if @context.diagram
+ @values["diagram"] = diagram_reference(@context.diagram)
+ end
+
+ @values["short_name"] = CGI.escapeHTML(short_name)
+ @values["full_path"] = CGI.escapeHTML(full_path)
+ @values["dtm_modified"] = @context.file_stat.mtime.to_s
+
+ if @options.webcvs
+ @values["cvsurl"] = cvs_url( @options.webcvs, @values["full_path"] )
+ end
+ end
+
+ def <=>(other)
+ self.name <=> other.name
+ end
+ end
+
+ #####################################################################
+
+ class HtmlMethod
+ include MarkUp
+
+ attr_reader :context
+ attr_reader :src_url
+ attr_reader :img_url
+ attr_reader :source_code
+
+ @@m_seq = "M000000"
+
+ @@all_methods = []
+
+ def HtmlMethod::reset
+ @@all_methods = []
+ end
+
+ def initialize(context, html_class, options)
+ @context = context
+ @html_class = html_class
+ @options = options
+ @@m_seq = @@m_seq.succ
+ @m_seq = @@m_seq
+ @@all_methods << self
+
+ context.viewer = self
+
+ if (ts = @context.token_stream)
+ @source_code = markup_code(ts)
+ #unless @options.inline_source
+ # @src_url = create_source_code_file(@source_code)
+ # @img_url = MERBGenerator.gen_url(path, 'source.png')
+ #end
+ end
+ AllReferences.add(name, self)
+ end
+
+ def seq
+ @m_seq
+ end
+
+ def aref
+ @m_seq
+ end
+
+ def scope
+ @html_class.full_name
+ end
+
+ # return a reference to outselves to be used as an href=
+ # the form depends on whether we're all in one file
+ # or in multiple files
+
+ def name
+ @context.name
+ end
+
+ def section
+ @context.section
+ end
+
+ def parent_name
+ if @context.parent.parent
+ @context.parent.parent.full_name
+ else
+ nil
+ end
+ end
+
+ def path
+ @html_class.path
+ end
+
+ def description
+ markup(@context.comment)
+ end
+
+ def visibility
+ @context.visibility
+ end
+
+ def singleton
+ @context.singleton
+ end
+
+ def call_seq
+ cs = @context.call_seq
+ if cs
+ cs.gsub(/\n/, "<br />\n")
+ else
+ nil
+ end
+ end
+
+ def params
+ # params coming from a call-seq in 'C' will start with the
+ # method name
+ p = @context.params
+ if p !~ /^\w/
+ p = @context.params.gsub(/\s*\#.*/, '')
+ p = p.tr("\n", " ").squeeze(" ")
+ p = "(" + p + ")" unless p[0] == ?(
+
+ if (block = @context.block_params)
+ # If this method has explicit block parameters, remove any
+ # explicit &block
+
+ p.sub!(/,?\s*&\w+/, '')
+
+ block.gsub!(/\s*\#.*/, '')
+ block = block.tr("\n", " ").squeeze(" ")
+ if block[0] == ?(
+ block.sub!(/^\(/, '').sub!(/\)/, '')
+ end
+ p << " {|#{block.strip}| ...}"
+ end
+ end
+ CGI.escapeHTML(p)
+ end
+
+ def create_source_code_file(code_body)
+ meth_path = @html_class.path.sub(/\.html$/, '.src')
+ File.makedirs(meth_path)
+ file_path = File.join(meth_path, seq) + ".html"
+
+ template = TemplatePage.new(RDoc::Page::SRC_PAGE)
+ File.open(file_path, "w") do |f|
+ values = {
+ 'title' => CGI.escapeHTML(name),
+ 'code' => code_body,
+ 'style_url' => style_url(file_path, @options.css),
+ 'charset' => @options.charset
+ }
+ template.write_html_on(f, values)
+ end
+ file_path
+ end
+
+ def HtmlMethod.all_methods
+ @@all_methods
+ end
+
+ def <=>(other)
+ @context <=> other.context
+ end
+
+ ##
+ # Given a sequence of source tokens, mark up the source code
+ # to make it look purty.
+
+
+ def markup_code(tokens)
+ src = ""
+ tokens.each do |t|
+ next unless t
+ # p t.class
+ # style = STYLE_MAP[t.class]
+ style = case t
+ when RubyToken::TkCONSTANT then "ruby-constant"
+ when RubyToken::TkKW then "ruby-keyword kw"
+ when RubyToken::TkIVAR then "ruby-ivar"
+ when RubyToken::TkOp then "ruby-operator"
+ when RubyToken::TkId then "ruby-identifier"
+ when RubyToken::TkNode then "ruby-node"
+ when RubyToken::TkCOMMENT then "ruby-comment cmt"
+ when RubyToken::TkREGEXP then "ruby-regexp re"
+ when RubyToken::TkSTRING then "ruby-value str"
+ when RubyToken::TkVal then "ruby-value"
+ else
+ nil
+ end
+
+ text = CGI.escapeHTML(t.text)
+
+ if style
+ src << "<span class=\"#{style}\">#{text}</span>"
+ else
+ src << text
+ end
+ end
+
+ add_line_numbers(src)
+ src
+ end
+
+ # we rely on the fact that the first line of a source code
+ # listing has
+ # # File xxxxx, line dddd
+
+ def add_line_numbers(src)
+ if src =~ /\A.*, line (\d+)/
+ first = $1.to_i - 1
+ last = first + src.count("\n")
+ size = last.to_s.length
+ real_fmt = "%#{size}d: "
+ fmt = " " * (size+2)
+ src.gsub!(/^/) do
+ res = sprintf(fmt, first)
+ first += 1
+ fmt = real_fmt
+ res
+ end
+ end
+ end
+
+ def document_self
+ @context.document_self
+ end
+
+ def aliases
+ @context.aliases
+ end
+
+ def find_symbol(symbol, method=nil)
+ res = @context.parent.find_symbol(symbol, method)
+ if res
+ res = res.viewer
+ end
+ res
+ end
+ end
+
+ #####################################################################
+
+ class MERBGenerator
+
+ include MarkUp
+
+ # Generators may need to return specific subclasses depending
+ # on the options they are passed. Because of this
+ # we create them using a factory
+
+ def MERBGenerator.for(options)
+ AllReferences::reset
+ HtmlMethod::reset
+
+ MERBGenerator.new(options)
+
+ end
+
+ class <<self
+ protected :new
+ end
+
+ # Set up a new HTML generator. Basically all we do here is load
+ # up the correct output temlate
+
+ def initialize(options) #:not-new:
+ @options = options
+ load_html_template
+ end
+
+
+ ##
+ # Build the initial indices and output objects
+ # based on an array of TopLevel objects containing
+ # the extracted information.
+
+ def generate(toplevels)
+ @toplevels = toplevels
+ @files = []
+ @classes = []
+
+ write_style_sheet
+ write_javascript
+ gen_sub_directories()
+ build_indices
+ generate_html
+ end
+
+ private
+
+ ##
+ # Load up the AJAX HTML template specified in the options.
+ # If the template name contains a slash, use it literally
+ #
+ def load_html_template
+ template = @options.template
+ unless template =~ %r{/|\\}
+ template = File.join("rdoc/generators/template", @options.generator.key, template)
+ end
+ require template
+ extend RDoc::Page
+ rescue LoadError
+ $stderr.puts "Could not find AJAX template '#{template}'"
+ exit 99
+ end
+
+ ##
+ # Write out the style sheet used by the main frames
+ #
+
+ def write_style_sheet
+ template = TemplatePage.new(RDoc::Page::STYLE)
+ File.open(CSS_NAME, "w") do |f|
+ values = { "font" => "helvetica"} #this is not used anywhere but the template function demands a hash of values
+ template.write_html_on(f, values)
+ end
+ end
+
+ def write_javascript
+ #Argh... I couldn't figure out how to copy these from the template dir so they were copied into
+ # the template file "ajax.rb" and processed similarlly to the style sheets. Not exactly a good thing to do with
+ # external library code. Not very DRY.
+
+ File.open("api_grease.js", "w") do |f|
+ f << RDoc::Page::API_GREASE_JS
+ end
+
+ File.open("prototype.js", "w") do |f|
+ f << RDoc::Page::PROTOTYPE_JS
+ end
+
+ rescue LoadError
+ $stderr.puts "Could not find AJAX template"
+ exit 99
+ end
+
+ ##
+ # See the comments at the top for a description of the
+ # directory structure
+
+ def gen_sub_directories
+ File.makedirs(FILE_DIR, CLASS_DIR)
+ rescue
+ $stderr.puts $!.message
+ exit 1
+ end
+
+ ##
+ # Generate:
+ #
+ # * a list of HtmlFile objects for each TopLevel object.
+ # * a list of HtmlClass objects for each first level
+ # class or module in the TopLevel objects
+ # * a complete list of all hyperlinkable terms (file,
+ # class, module, and method names)
+
+ def build_indices
+
+ @toplevels.each do |toplevel|
+ @files << HtmlFile.new(toplevel, @options, FILE_DIR)
+ end
+
+ RDoc::TopLevel.all_classes_and_modules.each do |cls|
+ build_class_list(cls, @files[0], CLASS_DIR)
+ end
+ end
+
+ def build_class_list(from, html_file, class_dir)
+ @classes << HtmlClass.new(from, html_file, class_dir, @options)
+ from.each_classmodule do |mod|
+ build_class_list(mod, html_file, class_dir)
+ end
+ end
+
+ ##
+ # Generate all the HTML
+ #
+ def generate_html
+ # the individual descriptions for files and classes
+ gen_into(@files)
+ gen_into(@classes)
+ # and the index files
+ gen_file_index
+ gen_class_index
+ gen_method_index
+ gen_main_index
+
+ # this method is defined in the template file
+ write_extra_pages if defined? write_extra_pages
+ end
+
+ def gen_into(list)
+ list.each do |item|
+ if item.document_self
+ op_file = item.path
+ File.makedirs(File.dirname(op_file))
+ File.open(op_file, "w") { |file| item.write_on(file) }
+ end
+ end
+
+ end
+
+ def gen_file_index
+ gen_an_index(@files, 'Files',
+ RDoc::Page::FILE_INDEX,
+ "fr_file_index.html")
+ end
+
+ def gen_class_index
+ gen_an_index(@classes, 'Classes',
+ RDoc::Page::CLASS_INDEX,
+ "fr_class_index.html")
+ end
+
+ def gen_method_index
+ gen_an_index(HtmlMethod.all_methods, 'Methods',
+ RDoc::Page::METHOD_INDEX,
+ "fr_method_index.html")
+ end
+
+
+ def gen_an_index(collection, title, template, filename)
+ template = TemplatePage.new(RDoc::Page::FR_INDEX_BODY, template)
+ res = []
+ collection.sort.each do |f|
+ if f.document_self
+ res << { "href" => f.path, "name" => f.name, "scope" => f.scope, "seq_id" => f.seq }
+ end
+ end
+
+ values = {
+ "entries" => res,
+ 'list_title' => CGI.escapeHTML(title),
+ 'index_url' => main_url,
+ 'charset' => @options.charset,
+ 'style_url' => style_url('', @options.css),
+ }
+
+ File.open(filename, "w") do |f|
+ template.write_html_on(f, values)
+ end
+ end
+
+ # The main index page is mostly a template frameset, but includes
+ # the initial page. If the <tt>--main</tt> option was given,
+ # we use this as our main page, otherwise we use the
+ # first file specified on the command line.
+
+ def gen_main_index
+ template = TemplatePage.new(RDoc::Page::INDEX)
+ File.open("index.html", "w") do |f|
+ tStr = ""
+ #File.open(main_url, 'r') do |g|
+ # tStr = markup(g)
+ #end
+ values = {
+ "initial_page" => tStr,
+ 'title' => CGI.escapeHTML(@options.title),
+ 'charset' => @options.charset,
+ 'content' => File.read('files/README.html')
+ }
+
+ values['inline_source'] = true
+ template.write_html_on(f, values)
+ end
+ end
+
+ # return the url of the main page
+ def main_url
+ "files/README.html"
+ end
+
+
+ end
+
+end
640 doc/rdoc/generators/template/merb/api_grease.js
@@ -0,0 +1,640 @@
+
+function setupPage(){
+ hookUpActiveSearch();
+ hookUpTabs();
+ suppressPostbacks();
+ var url_params = getUrlParams();
+ if (url_params != null){
+ loadUrlParams(url_params);
+ }else{
+ loadDefaults();
+ }
+ resizeDivs();
+ window.onresize = function(){ resizeDivs(); };
+}
+
+function getUrlParams(){
+ var window_location = window.location.href
+ var param_pos = window_location.search(/\?/)
+ if (param_pos > 0){
+ return(window_location.slice(param_pos, window_location.length));
+ }else{
+ return(null);
+ }
+}
+
+function loadUrlParams(url_param){
+ //get the tabs
+ var t = getTabs();
+ // now find our variables
+ var s_params = /(\?)(a=.+?)(&)(name=.*)/;
+ var results = url_param.match(s_params);
+ url_anchor = results[2].replace(/a=/,'');
+
+ if (url_anchor.match(/M.+/)){//load the methods tab and scroller content
+ setActiveTabAndLoadContent(t[0]);
+ }else{
+ if(url_anchor.match(/C.+/)){ //load the classes tab and scroller content
+ setActiveTabAndLoadContent(t[1]);
+ }else{
+ if (url_anchor.match(/F.+/)){//load the files tab
+ setActiveTabAndLoadContent(t[2]);
+ }else{
+ // default to loading the methods
+ setActiveTabAndLoadContent(t[0]);
+ }
+ }
+ }
+ paramLoadOfContentAnchor(url_anchor + "_link");
+}
+
+function updateUrlParams(anchor_id, name){
+ //Also setting the page title
+ //window.document.title = name + " method - MerbBrain.com ";
+
+ //updating the window location
+ var current_href = window.location.href;
+ //var m_name = name.replace("?","?");
+ var rep_str = ".html?a=" + anchor_id + "&name=" + name;
+ var new_href = current_href.replace(/\.html.*/, rep_str);
+ if (new_href != current_href){
+ window.location.href = new_href;
+ }
+}
+
+//does as it says...
+function hookUpActiveSearch(){
+
+ var s_field = $('searchForm').getInputs('text')[0];
+ //var s_field = document.forms[0].searchText;
+ Event.observe(s_field, 'keydown', function(event) {
+ var el = Event.element(event);
+ var key = event.which || event.keyCode;
+
+ switch (key) {
+ case Event.KEY_RETURN:
+ forceLoadOfContentAnchor(getCurrentAnchor());
+ Event.stop(event);
+ break;
+
+ case Event.KEY_UP:
+ scrollListToElementOffset(getCurrentAnchor(),-1);
+ break;
+
+ case Event.KEY_DOWN:
+ scrollListToElementOffset(getCurrentAnchor(),1);
+ break;
+
+ default:
+ break;
+ }
+
+ });
+
+ Event.observe(s_field, 'keyup', function(event) {
+ var el = Event.element(event);
+ var key = event.which || event.keyCode;
+ switch (key) {
+ case Event.KEY_RETURN:
+ Event.stop(event);
+ break;
+
+ case Event.KEY_UP:
+ break;
+
+ case Event.KEY_DOWN:
+ break;
+
+ default:
+ scrollToName(el.value);
+ setSavedSearch(getCurrentTab(), el.value);
+ break;
+ }
+
+ });
+
+ Event.observe(s_field, 'keypress', function(event){
+ var el = Event.element(event);
+ var key = event.which || event.keyCode;
+ switch (key) {
+ case Event.KEY_RETURN:
+ Event.stop(event);
+ break;
+
+ default:
+ break;
+ }
+
+ });
+
+ //Event.observe(document, 'keypress', function(event){
+ // var key = event.which || event.keyCode;
+ // if (key == Event.KEY_TAB){
+ // cycleNextTab();
+ // Event.stop(event);
+ // }
+ //});
+}
+
+function hookUpTabs(){
+
+ var tabs = getTabs();
+ for(x=0; x < tabs.length; x++)
+ {
+ Event.observe(tabs[x], 'click', function(event){
+ var el = Event.element(event);
+ setActiveTabAndLoadContent(el);
+ });
+ //tabs[x].onclick = function (){ return setActiveTabAndLoadContent(this);}; //the prototype guys say this is bad..
+ }
+
+}
+
+function suppressPostbacks(){
+ Event.observe('searchForm', 'submit', function(event){
+ Event.stop(event);
+ });
+}
+
+function loadDefaults(){
+ var t = getTabs();
+ setActiveTabAndLoadContent(t[0]); //default loading of the first tab
+}
+
+function resizeDivs(){
+ var inner_height = 700;
+ if (window.innerHeight){
+ inner_height = window.innerHeight; //all browsers except IE use this to determine the space available inside a window. Thank you Microsoft!!
+ }else{
+ if(document.documentElement.clientHeight > 0){ //IE uses this in 'strict' mode
+ inner_height = document.documentElement.clientHeight;
+ }else{
+ inner_height = document.body.clientHeight; //IE uses this in 'quirks' mode
+ }
+ }
+ $('rdocContent').style.height = (inner_height - 92) + "px";//Thankfully all browsers can agree on how to set the height of a div
+ $('listScroller').style.height = (inner_height - 88) + "px";
+}
+
+//The main function for handling clicks on the tabs
+function setActiveTabAndLoadContent(current_tab){
+ changeLoadingStatus("on");
+ var tab_string = String(current_tab.innerHTML).strip(); //thank you ProtoType!
+ switch (tab_string){
+ case "classes":
+ setCurrentTab("classes");
+ loadScrollerContent('fr_class_index.html');
+ setSearchFieldValue(getSavedSearch("classes"));
+ scrollToName(getSavedSearch("classes"));
+ setSearchFocus();
+ break;
+
+ case "files":
+ setCurrentTab("files");
+ loadScrollerContent('fr_file_index.html');
+ setSearchFieldValue(getSavedSearch("files"));
+ scrollToName(getSavedSearch("files"));
+ setSearchFocus();
+ break;
+
+ case "methods":
+ setCurrentTab("methods");
+ loadScrollerContent('fr_method_index.html');
+ setSearchFieldValue(getSavedSearch("methods"));
+ scrollToName(getSavedSearch("methods"));
+ setSearchFocus();
+ break;
+
+ default:
+ break;
+ }
+ changeLoadingStatus("off");
+}
+
+function cycleNextTab(){
+ var currentT = getCurrentTab();
+ var tabs = getTabs();
+ if (currentT == "methods"){
+ setActiveTabAndLoadContent(tabs[1]);
+ setSearchFocus();
+ }else{
+ if (currentT == "classes"){
+ setActiveTabAndLoadContent(tabs[2]);
+ setSearchFocus();
+ }else{
+ if (currentT == "files"){
+ setActiveTabAndLoadContent(tabs[0]);
+ setSearchFocus();
+ }
+ }
+ }
+}
+
+function getTabs(){
+ return($('groupType').getElementsByTagName('li'));
+}
+
+var Active_Tab = "";
+function getCurrentTab(){
+ return Active_Tab;
+}
+
+function setCurrentTab(tab_name){
+ var tabs = getTabs();
+ for(x=0; x < tabs.length; x++)
+ {
+ if(tabs[x].innerHTML.strip() == tab_name) //W00t!!! String.prototype.strip!
+ {
+ tabs[x].className = "activeLi";
+ Active_Tab = tab_name;
+ }
+ else
+ {
+ tabs[x].className = "";
+ }
+ }
+}
+
+//These globals should not be used globally (hence the getters and setters)
+var File_Search = "";
+var Method_Search = "";
+var Class_Search = "";
+function setSavedSearch(tab_name, s_val){
+ switch(tab_name){
+ case "methods":
+ Method_Search = s_val;
+ break;
+ case "files":
+ File_Search = s_val;
+ break;
+ case "classes":
+ Class_Search = s_val;
+ break;
+ }
+}
+
+function getSavedSearch(tab_name){
+ switch(tab_name){
+ case "methods":
+ return (Method_Search);
+ break;
+ case "files":
+ return (File_Search);
+ break;
+ case "classes":
+ return (Class_Search);
+ break;
+ }
+}
+
+//These globals handle the history stack
+
+
+function setListScrollerContent(s){
+
+ $('listScroller').innerHTML = s;
+}
+
+function setMainContent(s){
+
+ $('rdocContent').innerHTML = s;
+}
+
+function setSearchFieldValue(s){
+
+ document.forms[0].searchText.value = s;
+}
+
+function getSearchFieldValue(){
+
+ return Form.Element.getValue('searchText');
+}
+
+function setSearchFocus(){
+
+ document.forms[0].searchText.focus();
+}
+
+var Anchor_ID_Of_Current = null; // holds the last highlighted anchor tag in the scroll lsit
+function getCurrentAnchor(){
+ return(Anchor_ID_Of_Current);
+}
+
+function setCurrentAnchor(a_id){
+ Anchor_ID_Of_Current = a_id;
+}
+
+//var Index_Of_Current = 0; //holds the last highlighted index
+//function getCurrentIndex(){
+// return (Index_Of_Current);
+//}
+
+//function setCurrentIndex(new_i){
+// Index_Of_Current = new_i;
+//}
+
+function loadScrollerContent(url){
+
+ var scrollerHtml = new Ajax.Request(url, {
+ asynchronous: false,
+ method: 'get',
+ onComplete: function(method_data) {
+ setListScrollerContent(method_data.responseText);
+ }
+ });
+
+}
+
+//called primarily from the links inside the scroller list
+//loads the main page div then jumps to the anchor/element with id
+function loadContent(url, anchor_id){
+
+ var mainHtml = new Ajax.Request(url, {
+ method: 'get',
+ onLoading: changeLoadingStatus("on"),
+ onSuccess: function(method_data) {
+ setMainContent(method_data.responseText);},
+ onComplete: function(request) {
+ changeLoadingStatus("off");
+ new jumpToAnchor(anchor_id);
+ }
+ });
+}
+
+//An alternative function that also will stuff the index history for methods, files, classes
+function loadIndexContent(url, anchor_id, name, scope)
+{
+ if (From_URL_Param == true){
+ var mainHtml = new Ajax.Request(url, {
+ method: 'get',
+ onLoading: changeLoadingStatus("on"),
+ onSuccess: function(method_data) {
+ setMainContent(method_data.responseText);},
+ onComplete: function(request) {
+ changeLoadingStatus("off");
+ updateBrowserBar(name, anchor_id, scope);
+ new jumpToAnchor(anchor_id);}
+ });
+ From_URL_Param = false;
+ }else{
+ updateUrlParams(anchor_id, name);
+ }
+
+}
+
+function updateBrowserBar(name, anchor_id, scope){
+ if (getCurrentTab() == "methods"){
+ $('browserBarInfo').update("<small>class/module:</small>&nbsp;<a href=\"#\" onclick=\"jumpToTop();\">" + scope + "</a>&nbsp;&nbsp;<small>method:</small>&nbsp;<strong><a href=\"#\" onclick=\"jumpToAnchor('"+ anchor_id +"')\">" + name + "</a></strong> ");
+ }else{ if(getCurrentTab() == "classes"){
+ $('browserBarInfo').update("<small>class/module:</small>&nbsp;<a href=\"#\" onclick=\"jumpToTop();\">" + scope + "::" + name + "</strong> ");
+ }else{
+ $('browserBarInfo').update("<small>file:</small>&nbsp;<a href=\"#\" onclick=\"jumpToTop();\">" + scope + "/" + name + "</strong> ");